How to scale and rotate svg image elements with snap.

1,930 views
Skip to first unread message

Kim Hovorka

unread,
Apr 24, 2015, 12:15:05 AM4/24/15
to sna...@googlegroups.com


Hello,

I want to try and make this clear to understand hopefully not lengthy.
What I need to do is to select and SVG element (say a image) with the mouse and without
knowing what type of svg element it is to scale or rotate the selected element in place.
I can use jQuery to get the element Id or class and that helps me to know if I have say
a an image element. I will mostly work with image elements in this case. So I
need to then know how to I guess clone the image element with snap.svg or use the existing
element in snap to rotate and/or scale the size of the image using a transform. I am not
having success with this. If anyone would be will to share code on how to dynamically do that
for an SVG element I would be thankful. The other issue with this would be that I will be opening
exising SVG files and need to do the rotating and scaling. Just another consideration why this
needs to be dynamic.

Thank you all.
Kim

Ian

unread,
Apr 24, 2015, 2:49:45 AM4/24/15
to sna...@googlegroups.com
I would imagine these are the key bits..

1) If you put a click handler on the element, 'this' will refer to the Snap object. You can also do something like Snap( ev.target ), if its not already a Snap object.
2) You can transform with el.transform(), and your rotate/scale string.
3) clone, you can use clone()
4) You can use load(), be aware you can't really transform an svg, but if you put it into something like a group() you can then transform the group.

As you are not having success, you will get a lot more help if you send a jsfiddle of the problem, so we can take a look and probably spot the bit you haven't understood quite right in the code.

Ian

Kim Hovorka

unread,
Apr 24, 2015, 9:09:40 AM4/24/15
to sna...@googlegroups.com
Ian,

I am using the following code and each item works with temporatily, however, not the way I need it to.
The imgrotate and imgscale actually do rotate and scale the image I click on.
However, If I do a imgscale and then do an imgrotate, the imgscale change was not saved or gets reset and
goes back to the original scale and vice-versa for doing and imgrotate and then an imgscale. There are changes
to the transform in the SVG elements. Again, however, switching the function on the image messes up the original
change. I was expecting to see another attribute added to the svg element (like transform:rotate(45)) or something
like that for the rotate. Any way to get each change to save permanently once the action is performed? Below is my
jQuery / Snap.svg code and what the contents of the SVG looks like before and after a Rotate was done.

  $('body').on('change', '#imgopacity, #imgrotate, #imgscale', function() {
    switch ($(this).prop('id')) {
      case 'imgopacity':
        $('#'+currentselecteditem).css('opacity',$("#imgopacity").val());
        break;
      case 'imgrotate':
        var s = Snap("#svgmain");
        var sitem = s.select('#'+currentselecteditem);
        sitem.transform( 'r'+$("#imgrotate").val(),$('#'+currentselecteditem).attr('x')+($('#'+currentselecteditem).attr('width')/2),$('#'+currentselecteditem).attr('y')+($('#'+currentselecteditem).attr('height')/2));
        break;
      case 'imgscale':
        var s = Snap("#svgmain");
        var sitem = s.select('#'+currentselecteditem);
        sitem.transform( 's'+$("#imgscale").val()/100);
        break;
    }    
  });

/***************************** BEFORE ROTATE ******************************/
<svg id="svgmain" class="" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" style="width: 1187px; height: 681px; bottom: 40px; position: absolute; top: 0px; left: 0px;">
<g id="snapsvg-zpd" transform="matrix(1,0,0,1,0,0)">
<rect id="chartbkgrnd" x="211" y="-154.5" width="765" height="990" style="position: absolute; top: 0px; left: 211px;" fill="#f6e1ff">
<image id="flag_1" class="imgclass" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAcMAAAE6CAYAAABqGzkPAAAgAElEQVR4nO3deVhUZ4I/egqKEgUUkX2TpVBWRVHECAZRlKhBVNwQBRMk7iJR0QRxAVyQCG6EsIOo7EsV6fl1T/ft3J47v6f7/p6Znt+d23OfmV9P356Z290zSafTk07y7/f+4VBNSS3nVJ2qU1Dffp7PPx3OOe+pOuf9+r71Li4uLi4gIiJyYp+5OEAhiIiI5PSZiwMUgoiISE6fuUz/Pya1k0RERHPendt3GIZEROTcGIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZER...XJXk6iuYhhSOQgtBotli1bZjQI09LSZC8j0VzFMCRyIHfv3DUYhB4eHmhubpa9fERzFcOQyMFs3LhRLwjT09PR29Mre7mI5jKGIZGD6X/Zj6bGJjQ1NuHRw0fQarSyl4lormMYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR0zMZhklJSURERHNeVFSU8TAkIiJyQp+5OEAhiIiI5PTZ/w9biCLgEd3qIAAAAABJRU5ErkJggg==" preserveAspectRatio="true" x="211" y="-154.5" width="451" height="314" style="opacity: 1; position: absolute; top: 183.5px; left: 368px;" transform="matrix(1,0,0,1,160,315)">
</g>
</svg>

/***************************** AFTER ROTATE ******************************/
<svg id="svgmain" class="" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" style="width: 1187px; height: 681px; bottom: 40px; position: absolute; top: 0px; left: 0px;">
<g id="snapsvg-zpd" transform="matrix(1,0,0,1,0,0)">
<rect id="chartbkgrnd" x="211" y="-154.5" width="765" height="990" style="position: absolute; top: 0px; left: 211px;" fill="#f6e1ff">
<image id="flag_1" class="imgclass" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAcMAAAE6CAYAAABqGzkPAAAgAElEQVR4nO3deVhUZ4I/egqKEgUUkX2TpVBWRVHECAZRlKhBVNwQBRMk7iJR0QRxAVyQCG6EsIOo7EsV6fl1T/ft3J47v6f7/p6Znt+d23OfmV9P356Z290zSafTk07y7/f+4VBNSS3nVJ2qU1Dffp7PPx3OOe+pOuf9+r71Li4uLi4gIiJyYp+5OEAhiIiI5PSZiwMUgoiISE6fuUz/Pya1k0RERHPendt3GIZEROTcGIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZEROT0GIZER...XJXk6iuYhhSOQgtBotli1bZjQI09LSZC8j0VzFMCRyIHfv3DUYhB4eHmhubpa9fERzFcOQyMFs3LhRLwjT09PR29Mre7mI5jKGIZGD6X/Zj6bGJjQ1NuHRw0fQarSyl4lormMYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR02MYEhGR0zMZhklJSURERHNeVFSU8TAkIiJyQp+5OEAhiIiI5PTZ/w9biCLgEd3qIAAAAABJRU5ErkJggg==" preserveAspectRatio="true" x="211" y="-154.5" width="451" height="314" style="opacity: 1; position: absolute; top: 183.5px; left: 368px;" transform="matrix(0.7193,0.6947,-0.6947,0.7193,124.2448,-302.5167)">
</g>
</svg>

Thanks to anyone on help with figuring this out.
Kim

Ian

unread,
Apr 24, 2015, 9:21:57 AM4/24/15
to sna...@googlegroups.com
It would be helpful to normally post examples on a jsfiddle, so we can erm fiddle with it :).

I'm guessing from your description, what you really need is a transform taking into consideration the previous one, as currently you are just setting a brand new transform if I read it right.
Raphael used to have this, but I'm not aware that Snap has it...so I'd probably roll my own something like this...

Snap.plugin( function( Snap, Element, Paper, global ) {
        Element.prototype.addTransform = function( t ) {
                return this.transform( this.transform().localMatrix.toTransformString() + t );
        };
});

var r = s.rect(0,0,100,100).transform('t100,100');
r.addTransform('r45,50,50')
 .addTransform('s0.5');




I 'think' that may help in your case, but hard to be sure without a fiddle.

This also crops up a bit, so I wonder if some similar robust feature is worth being added to the core.


Ian

unread,
Apr 24, 2015, 9:24:46 AM4/24/15
to sna...@googlegroups.com
Or, depending how you are implementing it...just store the scale/translate/rotation and then build up the string of combined transformations each time...

eg build up your string, 't200,200r45s20t45s22,2' or whatever, you just need to make sure you understand the order of matrices and whats happening with coordinate spaces when combining them.
Reply all
Reply to author
Forward
0 new messages