UNPKG

apexcharts

Version:

A JavaScript Chart Library

141 lines (119 loc) 3.94 kB
// @ts-check import { Environment } from '../utils/Environment.js' // Install draggable behavior on SVGElement prototype /** * @param {any} ElementClass */ function installDraggable(ElementClass) { /** * @param {any} opts */ ElementClass.prototype.draggable = function (opts) { if (opts === false) { // Disable dragging if (this._dragCleanup) { this._dragCleanup() this._dragCleanup = null } return this } const el = this const constraints = opts || {} /** * @param {any} e */ const onPointerDown = (e) => { // Ignore right-click if (e.button && e.button !== 0) return // Prevent parent handlers (e.g. ZoomPanSelection) from treating this as a new selection e.stopPropagation() const isTouch = e.type === 'touchstart' const ev = isTouch ? e.touches[0] : e const svgEl = el.node const startAttrX = parseFloat(svgEl.getAttribute('x')) || 0 const startAttrY = parseFloat(svgEl.getAttribute('y')) || 0 const startClientX = ev.clientX const startClientY = ev.clientY // We need to convert client px to SVG coordinate space const svgRoot = svgEl.ownerSVGElement /** @type {any} */ let ctm = null if (svgRoot) { ctm = svgRoot.getScreenCTM() } /** * @param {any} me */ const onMove = (me) => { const mev = me.type === 'touchmove' ? me.touches[0] : me let dx = mev.clientX - startClientX let dy = mev.clientY - startClientY // Convert pixel delta to SVG coordinate delta if (ctm) { dx = dx / ctm.a dy = dy / ctm.d } let newX = startAttrX + dx let newY = startAttrY + dy const w = parseFloat(svgEl.getAttribute('width')) || 0 const h = parseFloat(svgEl.getAttribute('height')) || 0 // Apply constraints if (constraints.minX !== undefined && newX < constraints.minX) newX = constraints.minX if (constraints.minY !== undefined && newY < constraints.minY) newY = constraints.minY if (constraints.maxX !== undefined && newX + w > constraints.maxX) newX = constraints.maxX - w if (constraints.maxY !== undefined && newY + h > constraints.maxY) newY = constraints.maxY - h const box = { x: newX, y: newY, w: w, h: h, x2: newX + w, y2: newY + h, } // Fire dragmove event matching SVG.js contract const event = new CustomEvent('dragmove', { detail: { handler: { /** * @param {number} x * @param {number} y */ move: function (x, y) { svgEl.setAttribute('x', x) svgEl.setAttribute('y', y) }, }, box: box, }, }) svgEl.dispatchEvent(event) } const onUp = () => { if (Environment.isBrowser()) { document.removeEventListener('mousemove', onMove) document.removeEventListener('touchmove', onMove) document.removeEventListener('mouseup', onUp) document.removeEventListener('touchend', onUp) } } if (Environment.isBrowser()) { document.addEventListener('mousemove', onMove) document.addEventListener('touchmove', onMove) document.addEventListener('mouseup', onUp) document.addEventListener('touchend', onUp) } } el.node.addEventListener('mousedown', onPointerDown) el.node.addEventListener('touchstart', onPointerDown) el._dragCleanup = () => { el.node.removeEventListener('mousedown', onPointerDown) el.node.removeEventListener('touchstart', onPointerDown) } return el } } export { installDraggable }