2

I'm not very familiar working with svgs in js but here is something that is definitely strange. I'm having an arrow and then a path that is supposed to fill that arrow to a certain extend. looks like this: image 1 Now my aim is to be able to scale the white part but it should still stay inside that arrowimage 2. Now the weird thing is that I cannot figure out how move the white part back into the right place. I've tried different attempts. here is my current code (it works for scaleFactor 1 but not for any other):

var draw = SVG('arrow').size(500, 500);
    var arrowPath=draw.polyline('10,243.495 202.918,15.482 397.199,245.107').fill('none').stroke({ width: 20 });

    var arrow=draw.group();
    arrow.add(arrowPath.clone());

    var scaleFactor=0.5;

    var fillArrow=draw.path('M357.669,198.387c-41.747,35.357-95.759,56.678-154.751,56.678c-58.991,0-113.003-21.32-154.75-56.676l154.75-182.907  L357.669,198.387z');
    fillArrow.fill('#ffffee');
    var moveX=(arrowPath.width()/2-fillArrow.width()/2)/scaleFactor+9.5;
    console.log(moveX);
    fillArrow.center(arrowPath.cx(), arrowPath.cy()).scale(scaleFactor);
//another attempt was
fillArrow.move(moveX,0);
suMi
  • 1,536
  • 1
  • 17
  • 30

1 Answers1

4

When you are scaling, rotating and translating in SVG you are doing coordinate transforms. That is, you are actually not changing the object you are drawing but the coordinate system that you are drawing the object in. Think of it as pixel has a certain size on your screen, and if your do svgObject.scale(0.5) the pixel becomes half the size.

So if you draw a square by path('M10,10 L20,10 L20,20 L10,20 z') and then apply scale(0.5) it will look like you have drawn a path that looks like path('M5,5 L10,5 L10,10 L5,10 Z')

This might sound strange at first but, but alot of geometrical calculations becomes much simpler when you can do this.

You want to scale around the tip of the arrow (make sure that does not move). Then you should place that point in the origo (0,0) and draw the object around that point. Do that in a group. Because then you can translate the group coordinate system to the correct position.

var draw = SVG('arrow').size(600, 600);

// create a group
var arrow = draw.group();

// Draw the arrow path in the group
// I have placed the "tip" of the arrow in (0,0)
var arrowPath = arrow.polyline('-250,250 0,0 250,250').fill('none').stroke({
    width: 20
});

// Draw the fill arrow in the group. Again, the point 
// I which to scale around is placed at (0,0)
var fillArrow = arrow.path('M0,0L150,150,-150,150z').fill('#ffffee');

// Move the group to the position we like to display it in the SVG
arrow.move(260, 20);

var scaleFactor = 0.5
fillArrow.scale(scaleFactor);

And here is a working example where you can test and change the scale factor. http://jsfiddle.net/ZmGQk/1/

And here is a good explanation on how the translate, rotate and scale works. http://commons.oreilly.com/wiki/index.php/SVG_Essentials/Transforming_the_Coordinate_System

Nils
  • 2,041
  • 1
  • 15
  • 20
  • thanks! I have figured out that in my case it is easier not to use the scale function but just multiply width + height by the scale factor. that way it's actually scaling linear also. this is what I need. – suMi Mar 20 '14 at 15:05