diff --git a/draftlogs/5916_fix.md b/draftlogs/5916_fix.md new file mode 100644 index 00000000000..72684e453e2 --- /dev/null +++ b/draftlogs/5916_fix.md @@ -0,0 +1 @@ + - Adjust position of hover in respect to CSS transform [[#5916](https://github.com/plotly/plotly.js/pull/5916)] diff --git a/src/components/fx/hover.js b/src/components/fx/hover.js index 6b54858ddc5..c6c51e5cd60 100644 --- a/src/components/fx/hover.js +++ b/src/components/fx/hover.js @@ -891,7 +891,7 @@ function createHoverText(hoverData, opts) { var ya = c0.ya; var axLetter = hovermode.charAt(0); var t0 = c0[axLetter + 'Label']; - var outerContainerBB = outerContainer.getBoundingClientRect(); + var outerContainerBB = getBoundingClientRect(gd, outerContainer); var outerTop = outerContainerBB.top; var outerWidth = outerContainerBB.width; var outerHeight = outerContainerBB.height; @@ -966,7 +966,7 @@ function createHoverText(hoverData, opts) { label.attr('transform', ''); - var tbb = ltext.node().getBoundingClientRect(); + var tbb = getBoundingClientRect(gd, ltext.node()); var lx, ly; if(hovermode === 'x') { @@ -1059,7 +1059,7 @@ function createHoverText(hoverData, opts) { var dummy = Drawing.tester.append('text') .text(s.text()) .call(Drawing.font, commonLabelFont); - var dummyBB = dummy.node().getBoundingClientRect(); + var dummyBB = getBoundingClientRect(gd, dummy.node()); if(Math.round(dummyBB.width) < Math.round(tbb.width)) { s.attr('x', ltx - dummyBB.width); } @@ -1148,7 +1148,7 @@ function createHoverText(hoverData, opts) { // Position the hover var legendContainer = container.select('g.legend'); - var tbb = legendContainer.node().getBoundingClientRect(); + var tbb = getBoundingClientRect(gd, legendContainer.node()); var tWidth = tbb.width + 2 * HOVERTEXTPAD; var tHeight = tbb.height + 2 * HOVERTEXTPAD; var winningPoint = hoverData[0]; @@ -1313,7 +1313,7 @@ function createHoverText(hoverData, opts) { .call(svgTextUtils.positionText, 0, 0) .call(svgTextUtils.convertToTspans, gd); - var t2bb = tx2.node().getBoundingClientRect(); + var t2bb = getBoundingClientRect(gd, tx2.node()); tx2width = t2bb.width + 2 * HOVERTEXTPAD; tx2height = t2bb.height + 2 * HOVERTEXTPAD; } else { @@ -1326,22 +1326,26 @@ function createHoverText(hoverData, opts) { stroke: contrastColor }); - var tbb = tx.node().getBoundingClientRect(); var htx = d.xa._offset + (d.x0 + d.x1) / 2; var hty = d.ya._offset + (d.y0 + d.y1) / 2; var dx = Math.abs(d.x1 - d.x0); var dy = Math.abs(d.y1 - d.y0); - var txTotalWidth = tbb.width + HOVERARROWSIZE + HOVERTEXTPAD + tx2width; - var anchorStartOK, anchorEndOK; - d.ty0 = outerTop - tbb.top; - d.bx = tbb.width + 2 * HOVERTEXTPAD; - d.by = Math.max(tbb.height + 2 * HOVERTEXTPAD, tx2height); + var tbb = getBoundingClientRect(gd, tx.node()); + var tbbWidth = tbb.width / fullLayout._invScaleX; + var tbbHeight = tbb.height / fullLayout._invScaleY; + + d.ty0 = (outerTop - tbb.top) / fullLayout._invScaleY; + d.bx = tbbWidth + 2 * HOVERTEXTPAD; + d.by = Math.max(tbbHeight + 2 * HOVERTEXTPAD, tx2height); d.anchor = 'start'; - d.txwidth = tbb.width; + d.txwidth = tbbWidth; d.tx2width = tx2width; d.offset = 0; + var txTotalWidth = (tbbWidth + HOVERARROWSIZE + HOVERTEXTPAD + tx2width) * fullLayout._invScaleX; + var anchorStartOK, anchorEndOK; + if(rotateLabels) { d.pos = htx; anchorStartOK = hty + dy / 2 + txTotalWidth <= outerHeight; @@ -2100,3 +2104,33 @@ function getCoord(axLetter, winningPoint, fullLayout) { // the offset parent, whatever that may be. function getTopOffset(gd) { return gd.offsetTop + gd.clientTop; } function getLeftOffset(gd) { return gd.offsetLeft + gd.clientLeft; } + +function getBoundingClientRect(gd, node) { + var fullLayout = gd._fullLayout; + + var rect = node.getBoundingClientRect(); + + var x0 = rect.x; + var y0 = rect.y; + var x1 = x0 + rect.width; + var y1 = y0 + rect.height; + + var A = Lib.apply3DTransform(fullLayout._invTransform)(x0, y0); + var B = Lib.apply3DTransform(fullLayout._invTransform)(x1, y1); + + var Ax = A[0]; + var Ay = A[1]; + var Bx = B[0]; + var By = B[1]; + + return { + x: Ax, + y: Ay, + width: Bx - Ax, + height: By - Ay, + top: Math.min(Ay, By), + left: Math.min(Ax, Bx), + right: Math.max(Ax, Bx), + bottom: Math.max(Ay, By), + }; +}