From 579b537e98544d2bd4de93e08ea138247588b2bc Mon Sep 17 00:00:00 2001 From: plainheart Date: Fri, 2 Oct 2020 16:05:09 +0800 Subject: [PATCH 1/2] feat(tooltip): allow adding class to tooltip DOM. --- src/component/tooltip/TooltipHTMLContent.ts | 7 +++++++ src/component/tooltip/TooltipModel.ts | 8 +++++++- src/component/tooltip/TooltipView.ts | 3 ++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/component/tooltip/TooltipHTMLContent.ts b/src/component/tooltip/TooltipHTMLContent.ts index 2545342fe5..9000b78dc5 100644 --- a/src/component/tooltip/TooltipHTMLContent.ts +++ b/src/component/tooltip/TooltipHTMLContent.ts @@ -207,6 +207,12 @@ interface TooltipContentOption { * some overflow clip but intrude outside of the container. */ appendToBody: boolean + + /** + * specified class name of tooltip dom + * @type {[type]} + */ + className?: string } class TooltipHTMLContent { @@ -245,6 +251,7 @@ class TooltipHTMLContent { const el = document.createElement('div'); // TODO: TYPE (el as any).domBelongToZr = true; + opt.className && (el.className = opt.className); this.el = el; const zr = this._zr = api.getZr(); const appendToBody = this._appendToBody = opt && opt.appendToBody; diff --git a/src/component/tooltip/TooltipModel.ts b/src/component/tooltip/TooltipModel.ts index a7bd3e34db..5722380487 100644 --- a/src/component/tooltip/TooltipModel.ts +++ b/src/component/tooltip/TooltipModel.ts @@ -65,6 +65,12 @@ export interface TooltipOption extends CommonTooltipOption { ComponentModel.registerClass(TooltipModel); -export default TooltipModel; \ No newline at end of file +export default TooltipModel; diff --git a/src/component/tooltip/TooltipView.ts b/src/component/tooltip/TooltipView.ts index e85767b5dc..e129534d9e 100644 --- a/src/component/tooltip/TooltipView.ts +++ b/src/component/tooltip/TooltipView.ts @@ -167,7 +167,8 @@ class TooltipView extends ComponentView { this._tooltipContent = this._renderMode === 'richText' ? new TooltipRichContent(api) : new TooltipHTMLContent(api.getDom(), api, { - appendToBody: tooltipModel.get('appendToBody', true) + appendToBody: tooltipModel.get('appendToBody', true), + className: tooltipModel.get('className', true) }); } From 61c07bb27a9c1c2de0a9353d712af50fcb1a1208 Mon Sep 17 00:00:00 2001 From: plainheart Date: Fri, 2 Oct 2020 17:09:11 +0800 Subject: [PATCH 2/2] chore(tooltip): migrate changes in PR apache#12834 to next branch. * See https://github.com/apache/incubator-echarts/pull/12834 --- src/component/tooltip/TooltipHTMLContent.ts | 45 +++++++++++++++------ src/component/tooltip/TooltipRichContent.ts | 37 +++++++++++++++-- src/component/tooltip/TooltipView.ts | 9 ++--- test/tooltip-windowResize.html | 44 +++++++++++++++++--- 4 files changed, 109 insertions(+), 26 deletions(-) diff --git a/src/component/tooltip/TooltipHTMLContent.ts b/src/component/tooltip/TooltipHTMLContent.ts index 9000b78dc5..3a717f674c 100644 --- a/src/component/tooltip/TooltipHTMLContent.ts +++ b/src/component/tooltip/TooltipHTMLContent.ts @@ -198,6 +198,9 @@ function makeStyleCoord(out: number[], zr: ZRenderType, appendToBody: boolean, z out[1] += viewportRootOffset.offsetTop; } } + + out[2] = out[0] / zr.getWidth(); + out[3] = out[1] / zr.getHeight(); } interface TooltipContentOption { @@ -207,12 +210,6 @@ interface TooltipContentOption { * some overflow clip but intrude outside of the container. */ appendToBody: boolean - - /** - * specified class name of tooltip dom - * @type {[type]} - */ - className?: string } class TooltipHTMLContent { @@ -223,7 +220,7 @@ class TooltipHTMLContent { private _show: boolean = false; - private _styleCoord: [number, number] = [0, 0]; + private _styleCoord: [number, number, number, number] = [0, 0, 0, 0]; private _appendToBody: boolean; private _enterable = true; @@ -251,7 +248,6 @@ class TooltipHTMLContent { const el = document.createElement('div'); // TODO: TYPE (el as any).domBelongToZr = true; - opt.className && (el.className = opt.className); this.el = el; const zr = this._zr = api.getZr(); const appendToBody = this._appendToBody = opt && opt.appendToBody; @@ -308,7 +304,7 @@ class TooltipHTMLContent { /** * Update when tooltip is rendered */ - update() { + update(tooltipModel: Model) { // FIXME // Move this logic to ec main? const container = this._container; @@ -318,6 +314,14 @@ class TooltipHTMLContent { if (domStyle.position !== 'absolute' && stl.position !== 'absolute') { domStyle.position = 'relative'; } + + // move tooltip if chart resized + const alwaysShowContent = tooltipModel.get('alwaysShowContent'); + alwaysShowContent && this._moveIfResized(); + + // update className + this.el.className = tooltipModel.get('className') || ''; + // Hide the tooltip // PENDING // this.hide(); @@ -339,10 +343,10 @@ class TooltipHTMLContent { el.style.display = el.innerHTML ? 'block' : 'none'; - // If mouse occsionally move over the tooltip, a mouseout event will be - // triggered by canvas, and cuase some unexpectable result like dragging + // If mouse occasionally move over the tooltip, a mouseout event will be + // triggered by canvas, and cause some unexpectable result like dragging // stop, "unfocusAdjacency". Here `pointer-events: none` is used to solve - // it. Although it is not suppored by IE8~IE10, fortunately it is a rare + // it. Although it is not supported by IE8~IE10, fortunately it is a rare // scenario. el.style.pointerEvents = this._enterable ? 'auto' : 'none'; @@ -392,6 +396,21 @@ class TooltipHTMLContent { } } + /** + * when `alwaysShowContent` is true, + * move the tooltip after chart resized + */ + _moveIfResized() { + // The ratio of left to width + const ratioX = this._styleCoord[2]; + // The ratio of top to height + const ratioY = this._styleCoord[3]; + this.moveTo( + ratioX * this._zr.getWidth(), + ratioY * this._zr.getHeight() + ); + } + hide() { this.el.style.display = 'none'; this._show = false; @@ -401,7 +420,7 @@ class TooltipHTMLContent { if (this._show && !(this._inContent && this._enterable)) { if (time) { this._hideDelay = time; - // Set show false to avoid invoke hideLater mutiple times + // Set show false to avoid invoke hideLater multiple times this._show = false; this._hideTimeout = setTimeout(zrUtil.bind(this.hide, this), time) as any; } diff --git a/src/component/tooltip/TooltipRichContent.ts b/src/component/tooltip/TooltipRichContent.ts index d9f96522cc..aee80c6112 100644 --- a/src/component/tooltip/TooltipRichContent.ts +++ b/src/component/tooltip/TooltipRichContent.ts @@ -32,6 +32,8 @@ class TooltipRichContent { private _show = false; + private _styleCoord: [number, number, number, number] = [0, 0, 0, 0]; + private _hideTimeout: number; private _enterable = true; @@ -44,13 +46,15 @@ class TooltipRichContent { constructor(api: ExtensionAPI) { this._zr = api.getZr(); + makeStyleCoord(this._styleCoord, this._zr, api.getWidth() / 2, api.getHeight() / 2); } /** * Update when tooltip is rendered */ - update() { - // noop + update(tooltipModel: Model) { + const alwaysShowContent = tooltipModel.get('alwaysShowContent'); + alwaysShowContent && this._moveIfResized(); } show() { @@ -136,6 +140,10 @@ class TooltipRichContent { moveTo(x: number, y: number) { const el = this.el; if (el) { + const styleCoord = this._styleCoord; + makeStyleCoord(styleCoord, this._zr, x, y); + x = styleCoord[0]; + y = styleCoord[1]; const style = el.style; const borderWidth = mathMaxWith0(style.borderWidth || 0); const shadowOuterSize = calcShadowOuterSize(style); @@ -146,6 +154,22 @@ class TooltipRichContent { } } + + /** + * when `alwaysShowContent` is true, + * move the tooltip after chart resized + */ + _moveIfResized() { + // The ratio of left to width + const ratioX = this._styleCoord[2]; + // The ratio of top to height + const ratioY = this._styleCoord[3]; + this.moveTo( + ratioX * this._zr.getWidth(), + ratioY * this._zr.getHeight() + ); + } + hide() { if (this.el) { this.el.hide(); @@ -157,7 +181,7 @@ class TooltipRichContent { if (this._show && !(this._inContent && this._enterable)) { if (time) { this._hideDelay = time; - // Set show false to avoid invoke hideLater mutiple times + // Set show false to avoid invoke hideLater multiple times this._show = false; this._hideTimeout = setTimeout(zrUtil.bind(this.hide, this), time) as any; } @@ -200,4 +224,11 @@ function calcShadowOuterSize(style: TextStyleProps) { }; } +function makeStyleCoord(out: number[], zr: ZRenderType, zrX: number, zrY: number) { + out[0] = zrX; + out[1] = zrY; + out[2] = out[0] / zr.getWidth(); + out[3] = out[1] / zr.getHeight(); +} + export default TooltipRichContent; diff --git a/src/component/tooltip/TooltipView.ts b/src/component/tooltip/TooltipView.ts index e129534d9e..f17d810946 100644 --- a/src/component/tooltip/TooltipView.ts +++ b/src/component/tooltip/TooltipView.ts @@ -167,8 +167,7 @@ class TooltipView extends ComponentView { this._tooltipContent = this._renderMode === 'richText' ? new TooltipRichContent(api) : new TooltipHTMLContent(api.getDom(), api, { - appendToBody: tooltipModel.get('appendToBody', true), - className: tooltipModel.get('className', true) + appendToBody: tooltipModel.get('appendToBody', true) }); } @@ -197,7 +196,7 @@ class TooltipView extends ComponentView { this._alwaysShowContent = tooltipModel.get('alwaysShowContent'); const tooltipContent = this._tooltipContent; - tooltipContent.update(); + tooltipContent.update(tooltipModel); tooltipContent.setEnterable(tooltipModel.get('enterable')); this._initGlobalListener(); @@ -451,7 +450,7 @@ class TooltipView extends ComponentView { ) { // showDelay is used in this case: tooltip.enterable is set // as true. User intent to move mouse into tooltip and click - // something. `showDelay` makes it easyer to enter the content + // something. `showDelay` makes it easier to enter the content // but tooltip do not move immediately. const delay = tooltipModel.get('showDelay'); cb = zrUtil.bind(cb, this); @@ -667,7 +666,7 @@ class TooltipView extends ComponentView { const markupStyleCreator = new TooltipMarkupStyleCreator(); // Do not check whether `trigger` is 'none' here, because `trigger` - // only works on cooridinate system. In fact, we have not found case + // only works on coordinate system. In fact, we have not found case // that requires setting `trigger` nothing on component yet. this._showOrMove(subTooltipModel, function (this: TooltipView) { diff --git a/test/tooltip-windowResize.html b/test/tooltip-windowResize.html index cdf2492408..809369e0e2 100644 --- a/test/tooltip-windowResize.html +++ b/test/tooltip-windowResize.html @@ -40,6 +40,18 @@ margin: 0 auto; } + .custoized-tooltip-class { + background-color: cyan!important; + text-shadow: 0 0 5px red; + } + .custoized-tooltip-class::after { + content: 'pseudo after'; + display: inline-block; + position: absolute; + left: 110%; + top: 50%; + transform: translateY(-50%); + } @@ -203,12 +215,34 @@ }; var chart = testHelper.create(echarts, 'main0', { - option: option + option: option, + buttons: [ + { + text: 'add class', + onclick: function () { + chart.setOption({ + tooltip: { + className: 'custoized-tooltip-class' + } + }) + } + }, + { + text: 'recovery class', + onclick: function () { + chart.setOption({ + tooltip: { + className: '' + } + }) + } + } + ] }); chart.setOption(option, true); - window.addEventListener('resize',function () { + window.addEventListener('resize', function () { chart.resize(); - }) + }); }); @@ -372,9 +406,9 @@ option: option }); chart.setOption(option, true); - window.addEventListener('resize',function () { + window.addEventListener('resize', function () { chart.resize(); - }) + }); });