Basic Dragging
The first task is to create a square and make it draggable. In Snap, that's very simple:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<script src="//cdn.jsdelivr.net/snap.svg/0.1.0/snap.svg-min.js"></script> | |
<script> | |
var s = Snap("#svg"); | |
var block = s.rect(100, 100, 100, 100, 20, 20); | |
block.attr({ | |
fill: "rgb(236, 240, 241)", | |
stroke: "#1f2c39", | |
strokeWidth: 3 | |
}); | |
block.drag(); | |
</script> | |
</head> | |
<body> | |
<svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg"></svg> | |
</body> | |
</html> |
Snapping to Grid
The next task is to make the box snap to a grid:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<script src="//cdn.jsdelivr.net/snap.svg/0.1.0/snap.svg-min.js"></script> | |
<script> | |
var s = Snap("#svg"); | |
var gridSize = 50; | |
var orig = { | |
x: 0, | |
y: 0 | |
}; | |
var block = s.rect(100, 100, 100, 100, 20, 20); | |
block.attr({ | |
fill: "rgb(236, 240, 241)", | |
stroke: "#1f2c39", | |
strokeWidth: 3 | |
}); | |
block.drag( | |
function (dx, dy, x, y, e) { | |
var xSnap = Snap.snapTo(gridSize, orig.x + dx, 100000000); | |
var ySnap = Snap.snapTo(gridSize, orig.y + dy, 100000000); | |
this.attr({ | |
x: xSnap, | |
y: ySnap | |
}); | |
}, | |
function (x, y, e) { | |
orig.x = e.toElement.x.baseVal.value; | |
orig.y = e.toElement.y.baseVal.value; | |
}); | |
</script> | |
</head> | |
<body> | |
<svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg"></svg> | |
</body> | |
</html> |
The drag function is passed two handler functions, the first is called when dragging is happening and the second when drag starts. We use the Snap function snapto to work out the new x and y position of the box. We have to store the original position of the box because it is not passed into the method anywhere.
I do not like having the orig global variable to store the location of the box. I appreciate that this is used temporarily but global scope variables feel dirty. One solution to this is to wrap the whole lot in a function so that the scope of the orig variable would only be in that scope. I would prefer Snap to store the origin and pass it to me.
Dragging with the transform method
SVG elements have a transform attribute that take the original description of the SVG object and transforms it automatically. I needed the original x and y to change, so rejected the transform method. Perhaps this could still be performed with a "drag stop" method that takes the transform and applies it to the original but for simplicity, I will leave it as-is. The transform method looks like this:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<script src="//cdn.jsdelivr.net/snap.svg/0.1.0/snap.svg-min.js"></script> | |
<script> | |
var s = Snap("#svg"); | |
var origTransform = {}; | |
var block = s.rect(100, 100, 100, 100, 20, 20); | |
block.attr({ | |
fill: "rgb(236, 240, 241)", | |
stroke: "#1f2c39", | |
strokeWidth: 3 | |
}); | |
block.drag( | |
function(dx, dy, x, y, e) { | |
// Do your custom work here | |
this.attr({ | |
transform: origTransform + (origTransform ? "T" : "t") + [dx, dy] | |
}); | |
}, | |
function (x,y,e) { | |
origTransform = this.transform().local; | |
} | |
); | |
</script> | |
</head> | |
<body> | |
<svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg"></svg> | |
</body> | |
</html> |
The problem with drag
I would prefer that drag accepted a context object that had named methods, rather than relying on the order of parameters. Drag would look more like this:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is how I would like to use snap.svg's drag method: | |
var block = s.rect(x, y, 100, 100, 20, 20); | |
block.drag({ | |
ondrag: function(dragContext, event) { | |
// drag method here | |
} | |
onstart: function(dragContext, event) { | |
// drag start here | |
} | |
}); |
0 comments:
Post a Comment