nouilles/Draggable.js

135 lines
4.0 KiB
JavaScript

// 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 }