Rotate, Drag, Rotate - moving and interacting with elements after transfroms

1,260 views
Skip to first unread message

Jared Thompson

unread,
May 19, 2014, 11:32:43 AM5/19/14
to sna...@googlegroups.com
I've hit a bit of a wall with my development with snap.svg and svg in general. I have been trying to learn from the Snap.svg Examples, http://svg.dabbles.info/ along with various posts and examples around the internet. As a result some of the code might look familiar.

Everything works fine (other than the white dot jumping) until I have to drag the group of elements vertically and then try and interact with elements after the drag. I know this is the result of the transforms (translate) that are being applied to the group of elements. What I'm having trouble with is adjusting for the transforms that are being applied to the group. The best example would be to plot a white dot on the blue circle and rotate it by dragging on the green ring. Now drag the elements vertically with the red ring. After dragging vertically try rotating again with the green ring. You can also try re-plotting the white dot on the blue circle (after dragging vertically) and you can see that it jumps outside of the blue circle.

I can see that after dragging the group the rotation of the white dot is based on the original rotation point [250,375]. I've been able to adjust the rotation point with the yStart ( [250,yStart] ) variable but the results are not great, see here: http://jsfiddle.net/hungerstar/AP6e9/2/.

When re-plotting the white dot after a vertical drag the dot is offset from the point you click by the same distance you dragged the group. I kind of get what is going on here. The blue circle allows the area, after transform, to be clickable and moves the white dot. The white dot itself is being position prior to the transform, hence the shift when you click. I believe that I can adjust it's cx and cy attributes to adjust for this.

What should I be tracking in the coordinate system after/prior the transform so my rotation will work properly post transform? Do I need to be grouping my SVG elements differently?

Here is my JSFiddle, http://jsfiddle.net/hungerstar/AP6e9/1/.

Red ring = vertical drag.
Green ring = rotation drag of white dot plotted in blue circle.
Blue circle = plot area, area where a white dot should be plot where user click. Elements inside/on blue circle must rotate when green ring is dragged.

Any help and direction will be greatly appreciated! Thanks!

Ian

unread,
May 19, 2014, 2:46:22 PM5/19/14
to sna...@googlegroups.com
Welcome to the club :). I find all of this stuff quite difficult, and always gets me head scratching.

I think its quite important to understand what the end aim is for the project, is it learning some aspect, or is it a particular thing you are achieve ? Will the end result be moving a dot, or could it be moving any svg image (like a freetransform), which already has existing transforms applied to it, and possibly has users zoomed or panned at different levels ? This possibly can affect how easy or difficult the solution is (I always find there's lots of gotchyas keep popping up).

I initially tried to do it all with matrices, but found it a bit too confusing to fix problems logically like that. In the end for a possibly similar problem, I ended up storing any existing initial matrix, and then adjusting/storing translation, rotation and scale for the element (as a data property). (You could also put the element in a group element and apply transforms to that).

If you haven't already, it may be worth looking at http://svg.dabbles.info/snaptut-freetransform.html (js source http://svg.dabbles.info/snaptut-freetransform.js )...then look at

Element.prototype.ftTransformedPoint and Element.prototype.ftUpdateTransform you may be able to spot some ideas. I don't think this is necessarily the best way (I wanted to do it just with matrices rather than the strings), but it may give some pointers.

Ian






Jared Thompson

unread,
May 21, 2014, 10:41:55 AM5/21/14
to sna...@googlegroups.com
Thanks for the reply Ian, much appreciated.

At first I didn't see it but your suggestion of storing the previous transformations got me on the right path. It looks like the transfrom() method allows you to "chain" or "stack" your various transformations and it will create the proper matrix.

For example:

var gCircle = s.circle(100,100,25).attr({fill:'green'});
var bCircle = s.circle(100,100,25).attr({fill:'black'});
var rCircle = s.circle(100,100,25).attr({fill:'red'});

var t10    = 't10,10';
var t50    = 't50,50';
var tChain = '';

for ( var i=0; i<5; i++ ) {
     tChain
+= t10;
}

// tChain = 't10,10t10,10t10,10t10,10t10,10'

gCircle
.transform( t10 ); // result, matrix(1,0,0,1,10,10)
bCircle
.transform( t50 ); // result, matrix(1,0,0,1,50,50)
rCircle
.transform( tChain ); // result, matrix(1,0,0,1,50,50)

The blue circle and the red circle end up in the same position even though they were given different transformation strings. Contrary to my example above I'm not chaining that many translations or any other type of transformation together but appending the new transformation to the previous one as obtained from the transfrom() method.

Here is my updated JSFiddle with the desired results: http://jsfiddle.net/hungerstar/AP6e9/3/

Thanks again Ian.

Now to work in some mousewheel and zoom. 

Jared Thompson

unread,
May 21, 2014, 10:48:54 AM5/21/14
to sna...@googlegroups.com
Though it now looks IE and Firefox don't want to play nice, especially IE.
Reply all
Reply to author
Forward
0 new messages