提交 534aa14a 编写于 作者: S sushuang
......@@ -280,6 +280,25 @@ TooltipContent.prototype = {
isShow: function () {
return this._show;
},
getOuterSize: function () {
var width = this.el.clientWidth;
var height = this.el.clientHeight;
// Consider browser compatibility.
// IE8 does not support getComputedStyle.
if (document.defaultView && document.defaultView.getComputedStyle) {
var stl = document.defaultView.getComputedStyle(this.el);
if (stl) {
width += parseInt(stl.paddingLeft, 10) + parseInt(stl.paddingRight, 10)
+ parseInt(stl.borderLeftWidth, 10) + parseInt(stl.borderRightWidth, 10);
height += parseInt(stl.paddingTop, 10) + parseInt(stl.paddingBottom, 10)
+ parseInt(stl.borderTopWidth, 10) + parseInt(stl.borderBottomWidth, 10);
}
}
return {width: width, height: height};
}
};
......
......@@ -46,6 +46,11 @@ export default echarts.extendComponentModel({
displayMode: 'single', // 'single' | 'multipleByCoordSys'
useHtml: 'auto', // 'auto', true, or false
// 'auto': use html by default, and use non-html if `document` is not defined
// true: use html for tooltip
// false: use canvas, svg, and etc. for tooltip
// 位置 {Array} | {Function}
// position: null
// Consider triggered from axisPointer handle, verticalAlign should be 'middle'
......
/*
* 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';
import Text from 'zrender/src/graphic/Text';
/**
* @alias module:echarts/component/tooltip/TooltipRichContent
* @constructor
*/
function TooltipRichContent(api) {
// this.el = new Group();
var zr = this._zr = api.getZr();
// zr.add(this.el);
this._x = api.getWidth() / 2;
this._y = 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 () {
},
show: function (tooltipModel) {
if (this._hideTimeout) {
clearTimeout(this._hideTimeout);
}
this.el.attr('show', true);
this._show = true;
},
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);
markers['marker' + name] = {
textWidth: 12,
textHeight: 12,
textBorderRadius: 6,
textBackgroundColor: markerRich[name]
};
text = text.substr(endId + 1);
startId = text.indexOf('{marker');
}
this.el = new Text({
style: {
rich: markers,
text: content,
textLineHeight: 20,
textBackgroundColor: tooltipModel.get('backgroundColor'),
textBorderRadius: tooltipModel.get('borderRadius'),
textFill: tooltipModel.get('textStyle.color'),
textPadding: tooltipModel.get('padding')
},
z: tooltipModel.get('z')
});
this._zr.add(this.el);
},
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) {
this.el.attr('position', [x, y]);
}
},
hide: function () {
},
hideLater: function (time) {
},
isShow: function () {
return this._show;
},
getOuterSize: function () {
return this.getSize();
}
};
export default TooltipRichContent;
......@@ -21,6 +21,7 @@ import * as echarts from '../../echarts';
import * as zrUtil from 'zrender/src/core/util';
import env from 'zrender/src/core/env';
import TooltipContent from './TooltipContent';
import TooltipRichContent from './TooltipRichContent';
import * as formatUtil from '../../util/format';
import * as numberUtil from '../../util/number';
import * as graphic from '../../util/graphic';
......@@ -47,7 +48,25 @@ export default echarts.extendComponentView({
if (env.node) {
return;
}
var tooltipContent = new TooltipContent(api.getDom(), api);
var tooltip = ecModel.get('tooltip');
this._isRich = false;
if (tooltip.length && (tooltip[0].useHtml === false // force using non-html
|| tooltip[0].useHtml === 'auto' && !document)) // auto using non-html when no `document`
{
this._isRich = true;
}
var tooltipContent
if (this._isRich) {
tooltipContent = new TooltipRichContent(api);
}
else {
tooltipContent = new TooltipContent(api.getDom(), api);
}
this._newLine = this._isRich ? '\n' : '<br/>';
this._tooltipContent = tooltipContent;
},
......@@ -345,6 +364,11 @@ export default echarts.extendComponentView({
globalTooltipModel
]);
var isRich = this._isRich;
var newLine = this._newLine;
var markers = {};
each(dataByCoordSys, function (itemCoordSys) {
// var coordParamList = [];
// var coordDefaultHTML = [];
......@@ -385,7 +409,18 @@ export default echarts.extendComponentView({
if (dataParams) {
singleParamsList.push(dataParams);
seriesDefaultHTML.push(series.formatTooltip(dataIndex, true));
var seriesTooltip = series.formatTooltip(dataIndex, true, null, isRich);
var html;
if (zrUtil.isObject(seriesTooltip)) {
html = seriesTooltip.html;
var newMarkers = seriesTooltip.markers;
zrUtil.merge(markers, newMarkers);
}
else {
html = seriesTooltip;
}
seriesDefaultHTML.push(html);
}
});
......@@ -394,16 +429,21 @@ export default echarts.extendComponentView({
// (1) shold be the first data which has name?
// (2) themeRiver, firstDataIndex is array, and first line is unnecessary.
var firstLine = valueLabel;
singleDefaultHTML.push(
(firstLine ? formatUtil.encodeHTML(firstLine) + '<br />' : '')
+ seriesDefaultHTML.join('<br />')
);
if (isRich) {
singleDefaultHTML.push(seriesDefaultHTML.join(newLine))
}
else {
singleDefaultHTML.push(
(firstLine ? formatUtil.encodeHTML(firstLine) + newLine : '')
+ seriesDefaultHTML.join(newLine)
);
}
});
}, this);
// In most case, the second axis is shown upper than the first one.
singleDefaultHTML.reverse();
singleDefaultHTML = singleDefaultHTML.join('<br /><br />');
singleDefaultHTML = singleDefaultHTML.join(this._newLine + this._newLine);
var positionExpr = e.position;
this._showOrMove(singleTooltipModel, function () {
......@@ -419,7 +459,7 @@ export default echarts.extendComponentView({
else {
this._showTooltipContent(
singleTooltipModel, singleDefaultHTML, singleParamsList, Math.random(),
point[0], point[1], positionExpr
point[0], point[1], positionExpr, undefined, markers
);
}
});
......@@ -455,13 +495,23 @@ export default echarts.extendComponentView({
}
var params = dataModel.getDataParams(dataIndex, dataType);
var defaultHtml = dataModel.formatTooltip(dataIndex, false, dataType);
var seriesTooltip = dataModel.formatTooltip(dataIndex, false, dataType, this._isRich);
var defaultHtml, markers;
if (zrUtil.isObject(seriesTooltip)) {
defaultHtml = seriesTooltip.html;
markers = seriesTooltip.markers;
}
else {
defaultHtml = seriesTooltip;
markers = null;
}
var asyncTicket = 'item_' + dataModel.name + '_' + dataIndex;
this._showOrMove(tooltipModel, function () {
this._showTooltipContent(
tooltipModel, defaultHtml, params, asyncTicket,
e.offsetX, e.offsetY, e.position, e.target
e.offsetX, e.offsetY, e.position, e.target, markers
);
});
......@@ -509,7 +559,7 @@ export default echarts.extendComponentView({
},
_showTooltipContent: function (
tooltipModel, defaultHtml, params, asyncTicket, x, y, positionExpr, el
tooltipModel, defaultHtml, params, asyncTicket, x, y, positionExpr, el, markers
) {
// Reset ticket
this._ticket = '';
......@@ -530,7 +580,7 @@ export default echarts.extendComponentView({
else if (typeof formatter === 'function') {
var callback = bind(function (cbTicket, html) {
if (cbTicket === this._ticket) {
tooltipContent.setContent(html);
tooltipContent.setContent(html, markers, tooltipModel);
this._updatePosition(
tooltipModel, positionExpr, x, y, tooltipContent, params, el
);
......@@ -540,7 +590,7 @@ export default echarts.extendComponentView({
html = formatter(params, asyncTicket, callback);
}
tooltipContent.setContent(html);
tooltipContent.setContent(html, markers, tooltipModel);
tooltipContent.show(tooltipModel);
this._updatePosition(
......@@ -604,7 +654,7 @@ export default echarts.extendComponentView({
}
else {
var pos = refixTooltipPosition(
x, y, content.el, viewWidth, viewHeight, align ? null : 20, vAlign ? null : 20
x, y, content, viewWidth, viewHeight, align ? null : 20, vAlign ? null : 20
);
x = pos[0];
y = pos[1];
......@@ -615,7 +665,7 @@ export default echarts.extendComponentView({
if (tooltipModel.get('confine')) {
var pos = confineTooltipPosition(
x, y, content.el, viewWidth, viewHeight
x, y, content, viewWidth, viewHeight
);
x = pos[0];
y = pos[1];
......@@ -715,8 +765,8 @@ function makeDispatchAction(payload, api) {
return payload.dispatchAction || zrUtil.bind(api.dispatchAction, api);
}
function refixTooltipPosition(x, y, el, viewWidth, viewHeight, gapH, gapV) {
var size = getOuterSize(el);
function refixTooltipPosition(x, y, content, viewWidth, viewHeight, gapH, gapV) {
var size = content.getOuterSize();
var width = size.width;
var height = size.height;
......@@ -739,8 +789,8 @@ function refixTooltipPosition(x, y, el, viewWidth, viewHeight, gapH, gapV) {
return [x, y];
}
function confineTooltipPosition(x, y, el, viewWidth, viewHeight) {
var size = getOuterSize(el);
function confineTooltipPosition(x, y, content, viewWidth, viewHeight) {
var size = content.getOuterSize();
var width = size.width;
var height = size.height;
......@@ -752,25 +802,6 @@ function confineTooltipPosition(x, y, el, viewWidth, viewHeight) {
return [x, y];
}
function getOuterSize(el) {
var width = el.clientWidth;
var height = el.clientHeight;
// Consider browser compatibility.
// IE8 does not support getComputedStyle.
if (document.defaultView && document.defaultView.getComputedStyle) {
var stl = document.defaultView.getComputedStyle(el);
if (stl) {
width += parseInt(stl.paddingLeft, 10) + parseInt(stl.paddingRight, 10)
+ parseInt(stl.borderLeftWidth, 10) + parseInt(stl.borderRightWidth, 10);
height += parseInt(stl.paddingTop, 10) + parseInt(stl.paddingBottom, 10)
+ parseInt(stl.borderTopWidth, 10) + parseInt(stl.borderBottomWidth, 10);
}
}
return {width: width, height: height};
}
function calcTooltipPosition(position, rect, contentSize) {
var domWidth = contentSize[0];
var domHeight = contentSize[1];
......
......@@ -303,8 +303,15 @@ var SeriesModel = ComponentModel.extend({
* @param {number} dataIndex
* @param {boolean} [multipleSeries=false]
* @param {number} [dataType]
* @param {boolean} [isRich=false]
* @return {Object} formatted tooltip with `html` and `markers`
*/
formatTooltip: function (dataIndex, multipleSeries, dataType) {
formatTooltip: function (dataIndex, multipleSeries, dataType, isRich) {
var series = this;
var newLine = isRich ? '\n' : '<br/>';
var markers = {};
var markerId = 0;
function formatArrayValue(value) {
// ??? TODO refactor these logic.
......@@ -330,7 +337,8 @@ var SeriesModel = ComponentModel.extend({
return;
}
var dimType = dimInfo.type;
var dimHead = getTooltipMarker({color: color, type: 'subItem'});
var markName = series.seriesIndex + 'at' + markerId;
var dimHead = getTooltipMarker({color: color, type: 'subItem', isRich: isRich, markerId: markName});
var valStr = (vertially
? dimHead + encodeHTML(dimInfo.displayName || '-') + ': '
: ''
......@@ -343,9 +351,17 @@ var SeriesModel = ComponentModel.extend({
: addCommas(val)
);
valStr && result.push(valStr);
if (isRich) {
markers[markName] = color;
++markerId;
}
}
return (vertially ? '<br/>' : '') + result.join(vertially ? '<br/>' : ', ');
return {
html: (vertially ? isRich : '') + result.join(vertially ? isRich : ', '),
markers: markers
};
}
function formatSingleValue(val) {
......@@ -371,7 +387,10 @@ var SeriesModel = ComponentModel.extend({
? formatSingleValue(retrieveRawValue(data, dataIndex, tooltipDims[0]))
: formatSingleValue(isValueArr ? value[0] : value);
var colorEl = getTooltipMarker(color);
var markName = series.seriesIndex + 'at' + markerId;
var colorEl = getTooltipMarker({ color: color, type: 'item', isRich: isRich, markerId: markName });
markers[markName] = color;
++markerId;
var name = data.getName(dataIndex);
......@@ -380,16 +399,21 @@ var SeriesModel = ComponentModel.extend({
seriesName = '';
}
seriesName = seriesName
? encodeHTML(seriesName) + (!multipleSeries ? '<br/>' : ': ')
? encodeHTML(seriesName) + (!multipleSeries ? newLine : ': ')
: '';
return !multipleSeries
var html = !multipleSeries
? seriesName + colorEl
+ (name
? encodeHTML(name) + ': ' + formattedValue
: formattedValue
)
: colorEl + seriesName + formattedValue;
return {
html: html,
markers: markers
};
},
/**
......
......@@ -135,6 +135,7 @@ export function formatTplSimple(tpl, param, encode) {
* @param {string} [opt.color]
* @param {string} [opt.extraCssText]
* @param {string} [opt.type='item'] 'item' or 'subItem'
* @param {boolean} [opt.isRich=false] if renders with rich text
* @return {string}
*/
export function getTooltipMarker(opt, extraCssText) {
......@@ -142,18 +143,25 @@ export function getTooltipMarker(opt, extraCssText) {
var color = opt.color;
var type = opt.type;
var extraCssText = opt.extraCssText;
var isRich = opt.isRich == null ? false : opt.isRich;
if (!color) {
return '';
}
return type === 'subItem'
if (isRich) {
// Space for rich element marker
return '{marker' + opt.markerId + '|} ';
}
else {
return type === 'subItem'
? '<span style="display:inline-block;vertical-align:middle;margin-right:8px;margin-left:3px;'
+ 'border-radius:4px;width:4px;height:4px;background-color:'
+ encodeHTML(color) + ';' + (extraCssText || '') + '"></span>'
: '<span style="display:inline-block;margin-right:5px;'
+ 'border-radius:10px;width:10px;height:10px;background-color:'
+ encodeHTML(color) + ';' + (extraCssText || '') + '"></span>';
}
}
function pad(str, len) {
......
<!--
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.
-->
<html>
<head>
<meta charset="utf-8">
<script src="lib/esl.js"></script>
<script src="lib/config.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<style>
html, body, #main {
width: 100%;
height: 100%;
margin: 0;
}
#main {
background: #fff;
}
</style>
<div id="main"></div>
<script>
require([
'echarts'
// 'echarts/chart/bar',
// 'echarts/chart/line',
// 'echarts/component/legend',
// 'echarts/component/grid',
// 'echarts/component/tooltip',
// 'echarts/component/toolbox',
// 'echarts/component/title',
// 'zrender/vml/vml'
], function (echarts) {
var chart = echarts.init(document.getElementById('main'));
chart.setOption({
backgroundColor: '#eee',
tooltip: {
show: true,
useHtml: false,
trigger: 'axis'
},
yAxis: {
type: 'value'
},
xAxis: {
type: 'category',
data: ['A', 'B', 'C']
},
series: [{
name: 'bar0',
type: 'bar',
data: [2, 3, 6]
}, {
name: 'bar1',
type: 'bar',
data: [1, 0, 9]
}, {
name: 'bar2',
type: 'bar',
data: ['-', 2, 1]
}]
});
window.onresize = chart.resize;
});
</script>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册