diff --git a/src/component/tooltip/TooltipContent.js b/src/component/tooltip/TooltipContent.js
index 95e58eead4..6cdbc3f282 100644
--- a/src/component/tooltip/TooltipContent.js
+++ b/src/component/tooltip/TooltipContent.js
@@ -20,6 +20,7 @@
import * as zrUtil from 'zrender/src/core/util';
import * as zrColor from 'zrender/src/tool/color';
import * as eventUtil from 'zrender/src/core/event';
+import * as domUtil from 'zrender/src/core/dom';
import env from 'zrender/src/core/env';
import * as formatUtil from '../../util/format';
@@ -121,24 +122,63 @@ function assembleCssText(tooltipModel) {
return cssText.join(';') + ';';
}
+// If not able to make, do not modify the input `out`.
+function makeStyleCoord(out, zr, appendToBody, zrX, zrY) {
+ var zrPainter = zr && zr.painter;
+
+ if (appendToBody) {
+ var zrViewportRoot = zrPainter && zrPainter.getViewportRoot();
+ if (zrViewportRoot) {
+ // Some APPs might use scale on body, so we support CSS transform here.
+ domUtil.transformLocalCoord(out, zrViewportRoot, document.body, zrX, zrY);
+ }
+ }
+ else {
+ out[0] = zrX;
+ out[1] = zrY;
+ // xy should be based on canvas root. But tooltipContent is
+ // the sibling of canvas root. So padding of ec container
+ // should be considered here.
+ var viewportRootOffset = zrPainter && zrPainter.getViewportRootOffset();
+ if (viewportRootOffset) {
+ out[0] += viewportRootOffset.offsetLeft;
+ out[1] += viewportRootOffset.offsetTop;
+ }
+ }
+}
+
/**
* @alias module:echarts/component/tooltip/TooltipContent
+ * @param {HTMLElement} container
+ * @param {ExtensionAPI} api
+ * @param {Object} [opt]
+ * @param {boolean} [opt.appendToBody]
+ * `false`: the DOM element will be inside the container. Default value.
+ * `true`: the DOM element will be appended to HTML body, which avoid
+ * some overflow clip but intrude outside of the container.
* @constructor
*/
-function TooltipContent(container, api) {
+function TooltipContent(container, api, opt) {
if (env.wxa) {
return null;
}
var el = document.createElement('div');
+ el.domBelongToZr = true;
+ this.el = el;
var zr = this._zr = api.getZr();
+ var appendToBody = this._appendToBody = opt && opt.appendToBody;
- this.el = el;
+ this._styleCoord = [0, 0];
- this._x = api.getWidth() / 2;
- this._y = api.getHeight() / 2;
+ makeStyleCoord(this._styleCoord, zr, appendToBody, api.getWidth() / 2, api.getHeight() / 2);
- document.body.appendChild(el);
+ if (appendToBody) {
+ document.body.appendChild(el);
+ }
+ else {
+ container.appendChild(el);
+ }
this._container = container;
@@ -172,7 +212,8 @@ function TooltipContent(container, api) {
// Try trigger zrender event to avoid mouse
// in and out shape too frequently
var handler = zr.handler;
- eventUtil.normalizeEvent(container, e, true);
+ var zrViewportRoot = zr.painter.getViewportRoot();
+ eventUtil.normalizeEvent(zrViewportRoot, e, true);
handler.dispatch('mousemove', e);
}
};
@@ -217,12 +258,13 @@ TooltipContent.prototype = {
show: function (tooltipModel) {
clearTimeout(this._hideTimeout);
var el = this.el;
+ var styleCoord = this._styleCoord;
el.style.cssText = gCssText + assembleCssText(tooltipModel)
// Because of the reason described in:
// http://stackoverflow.com/questions/21125587/css3-transition-not-working-in-chrome-anymore
// we should set initial value to `left` and `top`.
- + ';left:' + this._x + 'px;top:' + this._y + 'px;'
+ + ';left:' + styleCoord[0] + 'px;top:' + styleCoord[1] + 'px;'
+ (tooltipModel.get('extraCssText') || '');
el.style.display = el.innerHTML ? 'block' : 'none';
@@ -250,23 +292,13 @@ TooltipContent.prototype = {
return [el.clientWidth, el.clientHeight];
},
- moveTo: function (x, y) {
- // xy should be based on canvas root. But tooltipContent is
- // the sibling of canvas root. So padding of ec container
- // should be considered here.
- var zr = this._zr;
- var viewportRootOffset;
- if (zr && zr.painter && (viewportRootOffset = zr.painter.getViewportRootOffset())) {
- x += viewportRootOffset.offsetLeft;
- y += viewportRootOffset.offsetTop;
- }
+ moveTo: function (zrX, zrY) {
+ var styleCoord = this._styleCoord;
+ makeStyleCoord(styleCoord, this._zr, this._appendToBody, zrX, zrY);
var style = this.el.style;
- style.left = x + 'px';
- style.top = y + 'px';
-
- this._x = x;
- this._y = y;
+ style.left = styleCoord[0] + 'px';
+ style.top = styleCoord[1] + 'px';
},
hide: function () {
@@ -292,7 +324,6 @@ TooltipContent.prototype = {
return this._show;
},
-
dispose: function () {
this.el.parentNode.removeChild(this.el);
},
diff --git a/src/component/tooltip/TooltipView.js b/src/component/tooltip/TooltipView.js
index 69316529cf..8fa998186c 100644
--- a/src/component/tooltip/TooltipView.js
+++ b/src/component/tooltip/TooltipView.js
@@ -56,7 +56,9 @@ export default echarts.extendComponentView({
var tooltipContent;
if (this._renderMode === 'html') {
- tooltipContent = new TooltipContent(api.getDom(), api);
+ tooltipContent = new TooltipContent(api.getDom(), api, {
+ appendToBody: tooltipModel.get('appendToBody', true)
+ });
this._newLine = '
';
}
else {
@@ -65,10 +67,6 @@ export default echarts.extendComponentView({
}
this._tooltipContent = tooltipContent;
-
- this._event = {};
- this._viewWidth = document.body.clientWidth;
- this._viewHeight = document.body.clientHeight;
},
render: function (tooltipModel, ecModel, api) {
@@ -130,7 +128,6 @@ export default echarts.extendComponentView({
// If 'none', it is not controlled by mouse totally.
if (triggerOn !== 'none') {
if (triggerOn.indexOf(currTrigger) >= 0) {
- this._event = e.event;
this._tryShow(e, dispatchAction);
}
else if (currTrigger === 'leave') {
@@ -206,8 +203,7 @@ export default echarts.extendComponentView({
this._tryShow({
offsetX: payload.x,
offsetY: payload.y,
- target: el,
- event: this._event
+ target: el
}, dispatchAction);
}
else if (dataByCoordSys) {
@@ -215,7 +211,6 @@ export default echarts.extendComponentView({
offsetX: payload.x,
offsetY: payload.y,
position: payload.position,
- event: this._event,
dataByCoordSys: payload.dataByCoordSys,
tooltipOption: payload.tooltipOption
}, dispatchAction);
@@ -234,8 +229,7 @@ export default echarts.extendComponentView({
offsetX: cx,
offsetY: cy,
position: payload.position,
- target: pointInfo.el,
- event: this._event
+ target: pointInfo.el
}, dispatchAction);
}
}
@@ -252,8 +246,7 @@ export default echarts.extendComponentView({
offsetX: payload.x,
offsetY: payload.y,
position: payload.position,
- target: api.getZr().findHover(payload.x, payload.y).target,
- event: this._event
+ target: api.getZr().findHover(payload.x, payload.y).target
}, dispatchAction);
}
},
@@ -320,8 +313,8 @@ export default echarts.extendComponentView({
}
// Save mouse x, mouse y. So we can try to keep showing the tip if chart is refreshed
- this._lastX = e.event.pageX;
- this._lastY = e.event.pageY;
+ this._lastX = e.offsetX;
+ this._lastY = e.offsetY;
var dataByCoordSys = e.dataByCoordSys;
if (dataByCoordSys && dataByCoordSys.length) {
@@ -359,7 +352,9 @@ export default echarts.extendComponentView({
_showAxisTooltip: function (dataByCoordSys, e) {
var ecModel = this._ecModel;
var globalTooltipModel = this._tooltipModel;
- var point = [e.event.pageX, e.event.pageY];
+
+ var point = [e.offsetX, e.offsetY];
+
var singleDefaultHTML = [];
var singleParamsList = [];
var singleTooltipModel = buildTooltipModel([
@@ -515,7 +510,7 @@ export default echarts.extendComponentView({
this._showOrMove(tooltipModel, function () {
this._showTooltipContent(
tooltipModel, defaultHtml, params, asyncTicket,
- e.event.pageX, e.event.pageY, e.position, e.target, markers
+ e.offsetX, e.offsetY, e.position, e.target, markers
);
});
@@ -551,7 +546,7 @@ export default echarts.extendComponentView({
this._showOrMove(subTooltipModel, function () {
this._showTooltipContent(
subTooltipModel, defaultHtml, subTooltipModel.get('formatterParams') || {},
- asyncTicket, e.event.pageX, e.event.pageY, e.position, el
+ asyncTicket, e.offsetX, e.offsetY, e.position, el
);
});
@@ -613,8 +608,9 @@ export default echarts.extendComponentView({
* @return {Array.}
*/
_updatePosition: function (tooltipModel, positionExpr, x, y, content, params, el) {
- var viewWidth = this._viewWidth;
- var viewHeight = this._viewHeight;
+ var viewWidth = this._api.getWidth();
+ var viewHeight = this._api.getHeight();
+
positionExpr = positionExpr || tooltipModel.get('position');
var contentSize = content.getSize();
diff --git a/test/runTest/actions/__meta__.json b/test/runTest/actions/__meta__.json
index d55e775171..4b5c793939 100644
--- a/test/runTest/actions/__meta__.json
+++ b/test/runTest/actions/__meta__.json
@@ -134,6 +134,7 @@
"toolbox-title": 4,
"toolbox-tooltip": 1,
"tooltip": 10,
+ "tooltip-appendToBody": 4,
"tooltip-axisPointer": 20,
"tooltip-axisPointer2": 1,
"tooltip-cascade": 4,
diff --git a/test/runTest/actions/tooltip-appendToBody.json b/test/runTest/actions/tooltip-appendToBody.json
new file mode 100644
index 0000000000..26033aa71c
--- /dev/null
+++ b/test/runTest/actions/tooltip-appendToBody.json
@@ -0,0 +1 @@
+[{"name":"Action 1","ops":[{"type":"mousemove","time":877,"x":731,"y":147},{"type":"mousemove","time":1084,"x":563,"y":160},{"type":"mousemove","time":1309,"x":562,"y":160},{"type":"mousemove","time":1510,"x":364,"y":193},{"type":"mousemove","time":1719,"x":320,"y":194},{"type":"mousemove","time":1926,"x":316,"y":208},{"type":"mousemove","time":2126,"x":316,"y":211},{"type":"mousemove","time":2826,"x":316,"y":212},{"type":"mousemove","time":3026,"x":314,"y":234},{"type":"mousemove","time":3226,"x":315,"y":242},{"type":"mousemove","time":3435,"x":315,"y":242},{"type":"mousemove","time":3493,"x":315,"y":242},{"type":"mousemove","time":3693,"x":315,"y":262},{"type":"mousemove","time":3893,"x":316,"y":273},{"type":"mousemove","time":4093,"x":319,"y":290},{"type":"mousemove","time":4393,"x":319,"y":291},{"type":"mousemove","time":4593,"x":342,"y":290},{"type":"mousemove","time":4797,"x":604,"y":269},{"type":"mousemove","time":4998,"x":612,"y":262},{"type":"mousemove","time":5209,"x":625,"y":249},{"type":"mousemove","time":5415,"x":607,"y":249},{"type":"mousemove","time":5627,"x":505,"y":248},{"type":"mousewheel","time":5764,"x":505,"y":248,"deltaY":1},{"type":"mousewheel","time":5815,"x":505,"y":248,"deltaY":4},{"type":"mousewheel","time":5847,"x":505,"y":248,"deltaY":7},{"type":"mousewheel","time":5873,"x":505,"y":248,"deltaY":4},{"type":"mousewheel","time":5907,"x":505,"y":248,"deltaY":5},{"type":"mousewheel","time":5930,"x":505,"y":248,"deltaY":1},{"type":"mousemove","time":6497,"x":501,"y":251},{"type":"mousemove","time":6697,"x":407,"y":330},{"type":"mousemove","time":6906,"x":405,"y":333},{"type":"mousedown","time":7161,"x":405,"y":333},{"type":"mousemove","time":7199,"x":388,"y":345},{"type":"mousemove","time":7409,"x":368,"y":363},{"type":"mousemove","time":7615,"x":368,"y":363},{"type":"mousemove","time":7828,"x":388,"y":369},{"type":"mousemove","time":8045,"x":389,"y":369},{"type":"mousemove","time":8251,"x":364,"y":359},{"type":"mousemove","time":8460,"x":358,"y":336},{"type":"mouseup","time":8811,"x":358,"y":336},{"time":8812,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":8823,"x":349,"y":333},{"type":"mousemove","time":9029,"x":292,"y":282},{"type":"mousemove","time":9231,"x":286,"y":272},{"type":"mousemove","time":9447,"x":283,"y":248},{"type":"mousemove","time":9647,"x":283,"y":251},{"type":"mousemove","time":9847,"x":283,"y":253}],"scrollY":0,"scrollX":0,"timestamp":1578864522547},{"name":"Action 2","ops":[{"type":"mousemove","time":1064,"x":179,"y":319},{"type":"mousemove","time":1264,"x":208,"y":323},{"type":"mousemove","time":1473,"x":239,"y":323},{"type":"mousemove","time":1681,"x":242,"y":323},{"type":"mousemove","time":1881,"x":274,"y":335},{"type":"mousemove","time":2083,"x":302,"y":343},{"type":"mousemove","time":2283,"x":324,"y":346},{"type":"mousemove","time":2483,"x":331,"y":348},{"type":"mousemove","time":2917,"x":331,"y":348},{"type":"mousemove","time":3117,"x":331,"y":336},{"type":"mousemove","time":3327,"x":333,"y":331},{"type":"mousemove","time":3543,"x":337,"y":346},{"type":"mousemove","time":3767,"x":336,"y":354},{"type":"mousemove","time":3975,"x":336,"y":356},{"type":"mousemove","time":4184,"x":336,"y":354},{"type":"mousemove","time":4384,"x":356,"y":323},{"type":"mousemove","time":4594,"x":357,"y":322},{"type":"mousemove","time":4883,"x":358,"y":322},{"type":"mousemove","time":5083,"x":362,"y":325},{"type":"mousemove","time":5283,"x":352,"y":331},{"type":"mousemove","time":5484,"x":344,"y":338},{"type":"mousemove","time":5699,"x":338,"y":343},{"type":"mousemove","time":5907,"x":337,"y":344},{"type":"mousemove","time":6119,"x":352,"y":342},{"type":"mousemove","time":6324,"x":344,"y":346},{"type":"mousemove","time":6532,"x":338,"y":350},{"type":"mousemove","time":6743,"x":334,"y":350},{"type":"mousemove","time":6959,"x":334,"y":350}],"scrollY":157,"scrollX":0,"timestamp":1578864545306},{"name":"Action 3","ops":[{"type":"mousemove","time":880,"x":188,"y":96},{"type":"mousemove","time":1080,"x":218,"y":58},{"type":"mousemove","time":1280,"x":233,"y":35},{"type":"mousemove","time":1487,"x":244,"y":26},{"type":"mousemove","time":1704,"x":247,"y":22},{"type":"mousedown","time":2221,"x":247,"y":22},{"type":"mouseup","time":2537,"x":247,"y":22},{"time":2538,"delay":400,"type":"screenshot-auto"},{"type":"mousedown","time":3186,"x":247,"y":22},{"type":"mouseup","time":3772,"x":247,"y":22},{"time":3773,"delay":400,"type":"screenshot-auto"}],"scrollY":579,"scrollX":0,"timestamp":1578864579827},{"name":"Action 4","ops":[{"type":"mousemove","time":949,"x":276,"y":348},{"type":"mousemove","time":1156,"x":294,"y":338},{"type":"mousemove","time":1365,"x":314,"y":325},{"type":"mousemove","time":1574,"x":334,"y":319},{"type":"mousemove","time":1780,"x":337,"y":316},{"type":"mousemove","time":1989,"x":330,"y":317},{"type":"mousemove","time":2198,"x":331,"y":317},{"type":"mousemove","time":2409,"x":353,"y":311},{"type":"mousemove","time":2626,"x":356,"y":310},{"type":"mousemove","time":3164,"x":361,"y":307},{"type":"mousemove","time":3364,"x":390,"y":293},{"type":"mousemove","time":3575,"x":343,"y":324},{"type":"mousemove","time":3797,"x":348,"y":321},{"type":"mousemove","time":4040,"x":361,"y":305},{"type":"mousemove","time":4265,"x":357,"y":306},{"type":"mousemove","time":4474,"x":356,"y":308},{"type":"mousemove","time":4781,"x":359,"y":306},{"type":"mousemove","time":4990,"x":390,"y":289},{"type":"mousemove","time":5547,"x":390,"y":289},{"type":"mousemove","time":5747,"x":395,"y":291},{"type":"mousemove","time":5958,"x":392,"y":287},{"type":"mousemove","time":6164,"x":391,"y":290},{"type":"mousemove","time":6364,"x":394,"y":289},{"type":"mousemove","time":6567,"x":385,"y":277},{"type":"mousemove","time":6773,"x":385,"y":277},{"type":"mousemove","time":6970,"x":378,"y":281},{"type":"mousemove","time":7170,"x":345,"y":303},{"type":"mousemove","time":7372,"x":338,"y":306},{"type":"mousemove","time":7582,"x":324,"y":306},{"type":"mousemove","time":7797,"x":307,"y":307},{"type":"mousemove","time":7970,"x":307,"y":307},{"type":"mousemove","time":8171,"x":223,"y":294}],"scrollY":579,"scrollX":0,"timestamp":1578864604914}]
\ No newline at end of file