// const UI = {} // SVG.Point = ( x, y )=> Object.assign( document.documentElement.createSVGPoint(), {x,y} ) Symbol.Draggable = Symbol`Draggable` var Draggable = obj=> { if( Symbol.Draggable in obj ) return obj obj[Symbol.Draggable] = true obj.startDrag = e=> { let mouse = new DOMPoint( e.clientX , e.clientY )//.matrixTransform( obj.getCTM().inverse() ) mouse.x /= obj.ownerSVGElement.currentScale mouse.y /= obj.ownerSVGElement.currentScale obj.drag.offset = new DOMPoint( mouse.x - obj.x, mouse.y - obj.y ) obj.setAttribute( 'dragged', true ) console.log(e, mouse, obj.drag.offset) } obj.drag = function(e) {//debugger; if(e.buttons === 1) { let mouse = new DOMPoint( e.clientX / obj.ownerSVGElement.currentScale, e.clientY / obj.ownerSVGElement.currentScale )//.matrixTransform( obj.getScreenCTM().inverse() ) , pos = new DOMPoint( mouse.x - obj.drag.offset.x, mouse.y - obj.drag.offset.y) // pos.x /= obj.ownerSVGElement.currentScale // pos.y /= obj.ownerSVGElement.currentScale this.moveTo( pos ) this.dispatchEvent( new Event('move') ) } } obj.stopDrag = e=> obj.removeAttribute('dragged') obj.on`mousedown`( obj.startDrag ) // ,onmousemove:e=> e.buttons === 1 && e.target.drag(e) //obj.onmouseup = e=> e.currentTarget.setAttribute(' dragged', false ) return obj } Draggable.startGlobalDrag = e=> e.target.$$`[dragged]`.filter(el=>el.draggable).map( el=> el.drag(e) ) Draggable.stopGlobalDrag = e=> e.target.$$`[dragged]`.map( el=> el.removeAttribute('dragged') ) // $$`[draggable]` // .map( Draggable ) // document.documentElement.on`mousemove`( e=> $$`[dragged]`.filter(el=>el.draggable).map( el=> el.drag(e) ) , true ) // document.documentElement.onmouseup = e=> $$`[dragged]`.map( el=> el.removeAttribute('dragged') ) // Makes an element in an SVG document draggable. // Fires custom `dragstart`, `drag`, and `dragend` events on the // element with the `detail` property of the event carrying XY // coordinates for the location of the element. function makeDraggable(el) { if (!el) return console.error('makeDraggable() needs an element') let svg, pt, doc, root //var svg = el; //while (svg && svg.tagName!='svg') svg=svg.parentNode; //if (!svg) return console.error(el,'must be inside an SVG wrapper'); //var pt=svg.createSVGPoint(), doc=svg.ownerDocument; //var root = doc.rootElement || doc.body || svg; let xlate, txStartX, txStartY, mouseStart let xforms = el.transform.baseVal el.addEventListener('mousedown', e=> e.which == 1 && startMove(e), false ) function startMove(evt) { svg = el.ownerSVGElement pt = svg.createSVGPoint() doc = svg.ownerDocument root = doc.rootElement || doc.body || svg // We listen for mousemove/up on the root-most // element in case the mouse is not over el. root.addEventListener('mousemove',handleMove,false) root.addEventListener('mouseup', finishMove,false) // Ensure that the first transform is a translate() xlate = xforms.numberOfItems>0 && xforms.getItem(0) if (!xlate || xlate.type != SVGTransform.SVG_TRANSFORM_TRANSLATE){ xlate = xforms.createSVGTransformFromMatrix( svg.createSVGMatrix() ) xforms.insertItemBefore( xlate, 0 ) } txStartX = xlate.matrix.e txStartY = xlate.matrix.f mouseStart = inElementSpace(evt) fireEvent('dragstart') } function handleMove(evt) { var point = inElementSpace(evt) xlate.setTranslate( txStartX + point.x - mouseStart.x, txStartY + point.y - mouseStart.y ) fireEvent('drag') } function finishMove(evt) { root.removeEventListener('mousemove',handleMove,false) root.removeEventListener('mouseup', finishMove,false) fireEvent('dragend') } function fireEvent(eventName) { var event = new Event(eventName) event.detail = { x:xlate.matrix.e, y:xlate.matrix.f } return el.dispatchEvent(event) } // Convert mouse position from screen space to coordinates of el function inElementSpace(evt) { pt.x = evt.clientX pt.y = evt.clientY return pt.matrixTransform( el.parentNode.getScreenCTM().inverse() ) } return el } export { Draggable, makeDraggable }