https://jsfiddle.net/foreyez/mfcqx7vw/
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.animate({ transform: "T0,0" }, 200);
I'm trying to translate this box to 0,0 - which would be the upper left side of the screen. But it doesn't move. So it's treating my capital T as lowercase t and using local coordinates. How do I get it to use absolute?
Snap is transforming absolutely already. It's just that the current SVG hasn't been moved by a transform, it's been set with x,y.
So you have 2 choices, animate the x,y or animate the transform and leave x,y alone.
Behind the scenes in the DOM, a transform does NOT change the x,y. It has a separate transform attribute. The two are not linked in any way.
block.animate({ transform: "t-100,-100", 200 );
jsfiddle
or
block.animate({ x: 0, y: 0 }, 200 );
jsfiddle
It depends really what you are trying to achive, there's no right or wrong way, but if you wanted a solution that will work for circles and groups for example (as a circle doesn't have an x,y it has cx, cy) then a transform may be the way to go.
Think about the svg elements as being on graph paper. You can either reposition the element on the graph paper, or move the whole graph paper.
Now, if you really wanted to do a relative transform, you would have to have a transform on it in the first place for it to be relative to (otherwise its relative to default of 0,0 top left).
So if we start off by creating a rect without using x,y and using a transform of t100,100 to move it into the same place
var block = s.rect(0, 0, 100, 100, 20, 20).transform('t100,100');
jsfiddle
You could then move it relative to that initial transform positioning, by including the existing transform first. So it would look like...
block.animate({ transform: block.transform() + "t-100,-100" }, 200);
jsfiddle
This will relatively will move it -100,-100 more to the left, and up.
If you wanted absolute, it would be..
block.animate({ transform: "t0,0", 200 );
Related
I'm using Velocity.js for animation.
What's the proper way to move an SVG image, while rotating it around the center at the same time?
You do not need to do per frame animation if you can define the motion using combination of rotations and linear movements.
As it comes out, your issue is that you are not able to fully manage the origin of rotation.
NOTE : The following is applicable to not only velocity but all css transformations in general.
The origin of rotation is the top-left corner of the item to be rotated
Now, if you want to move the object without moving the origin, you can use the translateX, translateY properties. eg
.velocity({ translateX: "+=200", translateY: "25%"})
In order to move the object as well as the origin, you need to set or move its x and y position parameters. eg
.velocity({ x: "+=200", y: "25%" })
Rotation around center
As an example, if you want to rotate an object on its center,you need to
Translate the object by -w/2 and -h/2 where the width and height is w and h.
Rotate the object
Rotation around an external point
In case where you need to rotate the object around an item, simply first translate the object away from its origin by a suitable distance and then rotate it.
This PEN shows both examples where the green rectangle is rotated around its center and the blue one around an external point by combining translation and position correctly.
Velocity.js uses CSS transforms to do it's rotation. Because of this, all you actually need to do is set transform-origin: center; in your CSS. This changes the point around which all actions will happen.
Trying to match the rotational movement and shifting your X and Y accordingly will be a slower animation and more prone to bugs.
More information about transform-origin can be found here.
I am looking for a way to achieve only an inner glow or shadow on a raphael path. Unfortunately, you can only do radial gradients on an ellipse or a circle.
One idea may be to create a series of paths which are slightly smaller and fit inside the original path and then to give them different stroke colors, but I have no idea how I would approach that. Some function that takes the path and subtracts or adds values to the numbers depending on where they are... Anyway, if anyone has any ideas, or maybe another javascript library that does this, that would be great.
Ok here is how you can achieve that. It is pretty straightforward I think. I know it is hard to manually create a shadow path from your original. But there is a trick called scale() function. Steps to how you can get inner shadow or inner glow effect:
Create your path
Clone it into another path
Set the scale() of cloned path to be 0.9*original
Then hide the cloned path, but apply glow() function on it
The code:
var paper = Raphael("notepad", 500, 500);
var path = paper.path("M 50 200 L 120 100 200 190 80 250z");
var shadow = path.clone().scale(0.9).hide();
shadow.glow();
path.attr({stroke: "darkred"});
Look at the DEMO, this is not perfect but with minor changes, yo can get what you want.
Also as a side note:
glow() function has attributes like offsetx, offsety, opacity... Changing those attributes will give you your preferred shadow/glow.
UPDATED CODE http://jsfiddle.net/jUTFm/41/
Look here. You could try animating the width of the path and darkening the color gradually to give some kinda glowing effect.
check out the bottom part
brain = paper.add(brain);
brain.attr('stroke', '#ff0');
brain.transform('s 0.5, 0.5 0 0');
glow = brain.glow({
color: '#ff0',
width: 5
});
anim = Raphael.animation({
"stroke-width": 15,
opacity: 1
}, 500);
anim = anim.repeat(Infinity);
glow.animate(anim);
I am using a Kinetic.image object like this:
this.icon = new Kinetic.Image({
x: self.x,
y: self.y,
offset: [32,32],
image: self.imageItem.image,
width: self.size,
height: self.size,
scale: self.scale,
rotationDeg: self.angle,
draggable: true
});
The image is a PNG with transparent pixels. I also create a image hit region:
self.icon.createImageHitRegion(function() {
self.icon.getLayer().drawHit();
});
However, the hit region is wrong when I use the mouseover event. I suspect the hitregion is not scaled. Note that I also use offset so that the image rotates around it's center.
Am I doing something wrong of am I dealing with a bug here?
I had the same problem when the image is created passing width and height.
The library uses the width and height of the image to create the canvas to draw the hit region but the width and height is not used to scale the image that is drawn on the canvas.
If you search the kineticjs source you will see that inside createImageHitRegion there is a line that looks something like:
_context.drawImage(image, 0, 0);
Add the width and height for the image and it should work as expected:
_context.drawImage(image, 0, 0, this.getWidth(), this.getHeight());
In my case I didn't have to pass the scale attribute while creating the image, please verify if this is working when you provide the scale attribute otherwise you will have to tweak createImageHitRegion to account for that.
When I draw a simple rectangle using the following code the bottom and right edge borders are thicker that the top and left edge borders. Why is this and can I stop it?
var paper = Raphael(10, 50, 500, 500);
var rect = paper.rect(100, 100, 100, 100);
Your rectangle's top and left borders, which are using the default 1 pixel stroke-width, are falling exactly on the top and left borders of your SVG element (as represented by a Raphael paper object. As opposed to pixel based drawing solutions, this means the line is essentially straddling the element's border, resulting in 0.5 pixels of your border stroke being clipped.
To solve, you simply need to shift your drawing over or shift the beginning offset of your SVG element's coordinates.
Here's a fiddle that shows one solution.
The square looks fine to me: http://jsfiddle.net/cMXBC/2/
Could you have some rogue css somewhere that is modifying the stroke of the rect? Try right-clicking the square and inspecting the rectangle in Firebug or with the Chrome inspector to see if there is any style that has been added.
I've looked around the internet and found nothing, I've looked on other KineticJS examples that use a strokeWidth of 1 on their rectangles and they all appear to have a semi-opaque 2 pixel line rather than a nice sharp 1px opaque black line.
Now, I am guessing that as Google has nothing that the solution is either really simple or impossible, but.. do you know how I can get a one px border using KineticJS?
$(window).load(function(){
var stage = new Kinetic.Stage({container: "kineticdiv", width: 700, height: 400});
var layer = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x: stage.attrs.width/2, y: stage.attrs.height/2,
width: 100, height: 100,
fill: "#eee", stroke: "black", strokeWidth: 1
});
layer.add(rect);
stage.add(layer);
});
Anyone got any ideas?
when you draw a line from (x,y1) to (x,y2) (say; the same is true for horizontal lines) you need to worry about whether x is "in the middle of a pixel". if the line is "between pixels" then it will be half in one and half in another. the result will look blurred (it's basically anti-aliasing).
graphics systems vary on whether coordinates are for corners or centres, but you can fix the issue by experimenting a little - you just need to add half a pixel width to the coord and try again.
in the case of an html5 canvas (0,0) is the top left corner, so if you have no transform i guess the top left pixel centre is at (0.5, 0.5).
Another approach: if you use Integer numbers as coordinates and ortogonal 1px weight lines, then you can move the whole stage by [0.5, 0.5] and you dont have to add the half of a pixel to each coordinate, you can then use Integer numbers as coordinate as your whole stage will be moved half of pixel to right and the same to down.
There is a cool approach to get exactly what you want: group two similar shapes. The one at the lower level is one pixel larger then the one at the top. Fill the bottom one with the color you want your border (in your case: Black). works fine for me and has the precision and quality of CSS
The easiest way of solving this with Kinetic is to use the offset properties. So, rather than shifting individual coordinates of what you're drawing, your entire line/shape/group/layer/stage is offset by that much, theoretically getting it where you want it with minimum fuss:
var rect = new Kinetic.Rect({
x: stage.attrs.width/2, y: stage.attrs.height/2,
width: 100, height: 100,
fill: "#eee", stroke: "black", strokeWidth: 1,
offsetX: 0.5,
offsetY: 0.5
});
or, to get a whole bunch of stuff at once:
var layer = new Kinetic.Layer({
offsetX: 0.5,
offsetY: 0.5
});
That said, not all items benefit from this trick. Some, in fact, get fuzzier. So, make sure to apply the offset at the most atomic level that avoids contaminating shapes that don't benefit from it.