From 1cc8d50bc9ee012e4b587e7b70c78ad1fb4812a5 Mon Sep 17 00:00:00 2001 From: Jukka Kurkela Date: Mon, 14 Sep 2020 00:20:14 +0300 Subject: [PATCH] Fix: relative position in FF (#7792) * Fix: relative position in FF * Add tests --- src/helpers/helpers.dom.js | 24 +++++++--- test/specs/helpers.dom.tests.js | 79 +++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 6 deletions(-) diff --git a/src/helpers/helpers.dom.js b/src/helpers/helpers.dom.js index 1a2376a05..34052002a 100644 --- a/src/helpers/helpers.dom.js +++ b/src/helpers/helpers.dom.js @@ -93,16 +93,28 @@ export function getRelativePosition(evt, chart) { const e = evt.originalEvent || evt; const touches = e.touches; const source = touches && touches.length ? touches[0] : e; - const clientX = source.clientX; - const clientY = source.clientY; + const {offsetX, offsetY, layerX, layerY, target} = source; - const x = source.offsetX || source.layerX || clientX; - const y = source.offsetY || source.layerY || clientY; + if (offsetX > 0 || offsetY > 0) { + return { + x: offsetX, + y: offsetY + }; + } - if (x !== clientX && y !== clientY) { - return {x, y}; + if (layerX > 0 || layerY > 0) { + return { + x: layerX - target.offsetLeft, + y: layerY - target.offsetTop + }; } + return calculateRelativePositionFromClientXY(source, chart); +} + +function calculateRelativePositionFromClientXY(source, chart) { + const {clientX: x, clientY: y} = source; + const canvasElement = chart.canvas; const devicePixelRatio = chart.currentDevicePixelRatio; const boundingRect = canvasElement.getBoundingClientRect(); diff --git a/test/specs/helpers.dom.tests.js b/test/specs/helpers.dom.tests.js index ab614deee..454322dbe 100644 --- a/test/specs/helpers.dom.tests.js +++ b/test/specs/helpers.dom.tests.js @@ -256,4 +256,83 @@ describe('DOM helpers tests', function() { expect(canvas.style.width).toBe('400px'); }); + describe('getRelativePosition', function() { + it('should use offsetX/Y when available', function() { + const event = {offsetX: 0, offsetY: 10}; + const chart = undefined; + expect(helpers.getRelativePosition(event, chart)).toEqual({x: 0, y: 10}); + }); + + it('should use layerX/Y - target offsets when available', function() { + const chart = undefined; + + const event1 = { + layerX: 0, + layerY: 10, + target: { + offsetLeft: 0, + offsetTop: 5 + } + }; + expect(helpers.getRelativePosition(event1, chart)).toEqual({x: 0, y: 5}); + + const event2 = { + offsetX: 0, + offsetY: 0, + layerX: 10, + layerY: 10, + target: { + offsetLeft: 0, + offsetTop: 5 + } + }; + expect(helpers.getRelativePosition(event2, chart)).toEqual({x: 10, y: 5}); + }); + + it('should calculate from clientX/Y if offset/layer coords are not available', function() { + const chart = window.acquireChart({}, { + canvas: { + height: 200, + width: 200, + } + }); + + const event = { + clientX: 50, + clientY: 100 + }; + + const rect = chart.canvas.getBoundingClientRect(); + expect(helpers.getRelativePosition(event, chart)).toEqual({ + x: Math.round(event.clientX - rect.x), + y: Math.round(event.clientY - rect.y) + }); + + const chart2 = window.acquireChart({}, { + canvas: { + height: 200, + width: 200, + style: 'padding: 10px' + } + }); + const rect2 = chart2.canvas.getBoundingClientRect(); + expect(helpers.getRelativePosition(event, chart2)).toEqual({ + x: Math.round((event.clientX - rect2.x - 10) / 180 * 200), + y: Math.round((event.clientY - rect2.y - 10) / 180 * 200) + }); + + const chart3 = window.acquireChart({}, { + canvas: { + height: 200, + width: 200, + style: 'width: 400px, height: 400px; padding: 10px' + } + }); + const rect3 = chart3.canvas.getBoundingClientRect(); + expect(helpers.getRelativePosition(event, chart3)).toEqual({ + x: Math.round((event.clientX - rect3.x - 10) / 360 * 400), + y: Math.round((event.clientY - rect3.y - 10) / 360 * 400) + }); + }); + }); }); -- 2.47.2