252 lines
6.8 KiB
JavaScript
252 lines
6.8 KiB
JavaScript
|
|
||
|
/*
|
||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||
|
* or more contributor license agreements. See the NOTICE file
|
||
|
* distributed with this work for additional information
|
||
|
* regarding copyright ownership. The ASF licenses this file
|
||
|
* to you under the Apache License, Version 2.0 (the
|
||
|
* "License"); you may not use this file except in compliance
|
||
|
* with the License. You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing,
|
||
|
* software distributed under the License is distributed on an
|
||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||
|
* KIND, either express or implied. See the License for the
|
||
|
* specific language governing permissions and limitations
|
||
|
* under the License.
|
||
|
*/
|
||
|
|
||
|
var zrUtil = require("zrender/lib/core/util");
|
||
|
|
||
|
var Text = require("zrender/lib/graphic/Text");
|
||
|
|
||
|
var graphicUtil = require("../../util/graphic");
|
||
|
|
||
|
/*
|
||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||
|
* or more contributor license agreements. See the NOTICE file
|
||
|
* distributed with this work for additional information
|
||
|
* regarding copyright ownership. The ASF licenses this file
|
||
|
* to you under the Apache License, Version 2.0 (the
|
||
|
* "License"); you may not use this file except in compliance
|
||
|
* with the License. You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing,
|
||
|
* software distributed under the License is distributed on an
|
||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||
|
* KIND, either express or implied. See the License for the
|
||
|
* specific language governing permissions and limitations
|
||
|
* under the License.
|
||
|
*/
|
||
|
// import Group from 'zrender/src/container/Group';
|
||
|
function makeStyleCoord(out, zr, zrX, zrY) {
|
||
|
out[0] = zrX;
|
||
|
out[1] = zrY;
|
||
|
out[2] = out[0] / zr.getWidth(); // The ratio of left to width
|
||
|
|
||
|
out[3] = out[1] / zr.getHeight(); // The ratio of top to height
|
||
|
}
|
||
|
/**
|
||
|
* @alias module:echarts/component/tooltip/TooltipRichContent
|
||
|
* @constructor
|
||
|
*/
|
||
|
|
||
|
|
||
|
function TooltipRichContent(api) {
|
||
|
var zr = this._zr = api.getZr();
|
||
|
this._styleCoord = [0, 0, 0, 0]; // [left, top, left/width, top/height]
|
||
|
|
||
|
makeStyleCoord(this._styleCoord, zr, api.getWidth() / 2, api.getHeight() / 2);
|
||
|
this._show = false;
|
||
|
/**
|
||
|
* @private
|
||
|
*/
|
||
|
|
||
|
this._hideTimeout;
|
||
|
}
|
||
|
|
||
|
TooltipRichContent.prototype = {
|
||
|
constructor: TooltipRichContent,
|
||
|
|
||
|
/**
|
||
|
* @private
|
||
|
* @type {boolean}
|
||
|
*/
|
||
|
_enterable: true,
|
||
|
|
||
|
/**
|
||
|
* Update when tooltip is rendered
|
||
|
*/
|
||
|
update: function (tooltipModel) {
|
||
|
var alwaysShowContent = tooltipModel.get('alwaysShowContent');
|
||
|
alwaysShowContent && this._moveTooltipIfResized();
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* when `alwaysShowContent` is true,
|
||
|
* we should move the tooltip after chart resized
|
||
|
*/
|
||
|
_moveTooltipIfResized: function () {
|
||
|
var ratioX = this._styleCoord[2]; // The ratio of left to width
|
||
|
|
||
|
var ratioY = this._styleCoord[3]; // The ratio of top to height
|
||
|
|
||
|
var realX = ratioX * this._zr.getWidth();
|
||
|
|
||
|
var realY = ratioY * this._zr.getHeight();
|
||
|
|
||
|
this.moveTo(realX, realY);
|
||
|
},
|
||
|
show: function (tooltipModel) {
|
||
|
if (this._hideTimeout) {
|
||
|
clearTimeout(this._hideTimeout);
|
||
|
}
|
||
|
|
||
|
this.el.attr('show', true);
|
||
|
this._show = true;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Set tooltip content
|
||
|
*
|
||
|
* @param {string} content rich text string of content
|
||
|
* @param {Object} markerRich rich text style
|
||
|
* @param {Object} tooltipModel tooltip model
|
||
|
*/
|
||
|
setContent: function (content, markerRich, tooltipModel) {
|
||
|
if (this.el) {
|
||
|
this._zr.remove(this.el);
|
||
|
}
|
||
|
|
||
|
var markers = {};
|
||
|
var text = content;
|
||
|
var prefix = '{marker';
|
||
|
var suffix = '|}';
|
||
|
var startId = text.indexOf(prefix);
|
||
|
|
||
|
while (startId >= 0) {
|
||
|
var endId = text.indexOf(suffix);
|
||
|
var name = text.substr(startId + prefix.length, endId - startId - prefix.length);
|
||
|
|
||
|
if (name.indexOf('sub') > -1) {
|
||
|
markers['marker' + name] = {
|
||
|
textWidth: 4,
|
||
|
textHeight: 4,
|
||
|
textBorderRadius: 2,
|
||
|
textBackgroundColor: markerRich[name],
|
||
|
// TODO: textOffset is not implemented for rich text
|
||
|
textOffset: [3, 0]
|
||
|
};
|
||
|
} else {
|
||
|
markers['marker' + name] = {
|
||
|
textWidth: 10,
|
||
|
textHeight: 10,
|
||
|
textBorderRadius: 5,
|
||
|
textBackgroundColor: markerRich[name]
|
||
|
};
|
||
|
}
|
||
|
|
||
|
text = text.substr(endId + 1);
|
||
|
startId = text.indexOf('{marker');
|
||
|
}
|
||
|
|
||
|
var textStyleModel = tooltipModel.getModel('textStyle');
|
||
|
var fontSize = textStyleModel.get('fontSize');
|
||
|
var lineHeight = tooltipModel.get('textLineHeight');
|
||
|
|
||
|
if (lineHeight == null) {
|
||
|
lineHeight = Math.round(fontSize * 3 / 2);
|
||
|
}
|
||
|
|
||
|
this.el = new Text({
|
||
|
style: graphicUtil.setTextStyle({}, textStyleModel, {
|
||
|
rich: markers,
|
||
|
text: content,
|
||
|
textBackgroundColor: tooltipModel.get('backgroundColor'),
|
||
|
textBorderRadius: tooltipModel.get('borderRadius'),
|
||
|
textFill: tooltipModel.get('textStyle.color'),
|
||
|
textPadding: tooltipModel.get('padding'),
|
||
|
textLineHeight: lineHeight
|
||
|
}),
|
||
|
z: tooltipModel.get('z')
|
||
|
});
|
||
|
|
||
|
this._zr.add(this.el);
|
||
|
|
||
|
var self = this;
|
||
|
this.el.on('mouseover', function () {
|
||
|
// clear the timeout in hideLater and keep showing tooltip
|
||
|
if (self._enterable) {
|
||
|
clearTimeout(self._hideTimeout);
|
||
|
self._show = true;
|
||
|
}
|
||
|
|
||
|
self._inContent = true;
|
||
|
});
|
||
|
this.el.on('mouseout', function () {
|
||
|
if (self._enterable) {
|
||
|
if (self._show) {
|
||
|
self.hideLater(self._hideDelay);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
self._inContent = false;
|
||
|
});
|
||
|
},
|
||
|
setEnterable: function (enterable) {
|
||
|
this._enterable = enterable;
|
||
|
},
|
||
|
getSize: function () {
|
||
|
var bounding = this.el.getBoundingRect();
|
||
|
return [bounding.width, bounding.height];
|
||
|
},
|
||
|
moveTo: function (x, y) {
|
||
|
if (this.el) {
|
||
|
var styleCoord = this._styleCoord;
|
||
|
makeStyleCoord(styleCoord, this._zr, x, y);
|
||
|
this.el.attr('position', [styleCoord[0], styleCoord[1]]);
|
||
|
}
|
||
|
},
|
||
|
hide: function () {
|
||
|
if (this.el) {
|
||
|
this.el.hide();
|
||
|
}
|
||
|
|
||
|
this._show = false;
|
||
|
},
|
||
|
hideLater: function (time) {
|
||
|
if (this._show && !(this._inContent && this._enterable)) {
|
||
|
if (time) {
|
||
|
this._hideDelay = time; // Set show false to avoid invoke hideLater multiple times
|
||
|
|
||
|
this._show = false;
|
||
|
this._hideTimeout = setTimeout(zrUtil.bind(this.hide, this), time);
|
||
|
} else {
|
||
|
this.hide();
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
isShow: function () {
|
||
|
return this._show;
|
||
|
},
|
||
|
dispose: function () {
|
||
|
clearTimeout(this._hideTimeout);
|
||
|
|
||
|
if (this.el) {
|
||
|
this._zr.remove(this.el);
|
||
|
}
|
||
|
},
|
||
|
getOuterSize: function () {
|
||
|
var size = this.getSize();
|
||
|
return {
|
||
|
width: size[0],
|
||
|
height: size[1]
|
||
|
};
|
||
|
}
|
||
|
};
|
||
|
var _default = TooltipRichContent;
|
||
|
module.exports = _default;
|