Is it possible to use the <animate> tag in an svg to either make a part of an svg image animation from a value to another, to another. Or even better animate infinitely from and then to and back to from and then to; and, so on?
I want to animate a circle's radius, but in that infinite fashion. If I can't do it with the <animate> tag, how else can I do it?
Here is wha tI have so far for the animation running once.
<svg>
<circle r="100" cx="100" cy="100" fill="slategrey">
<animate attributeName="r" from="0" to="100" dur="1.6s"/>
</circle>
</svg>
Instead of using from and to, use the values attribute to make it cycle back and forth, and the repeatCount attribute to make it repeat forever.
<svg>
<circle r="100" cx="100" cy="100" fill="slategrey">
<animate attributeName="r" values="0;100;0" dur="1.6s"
repeatCount="indefinite"/>
</circle>
</svg>
Demo here
Related
So, I have a simple SVG group:
<g id="interceptor">
<ellipse cx="0" cy="15" rx="6" ry="14" fill="url(#gradient)"/>
<polygon points="0,-20 7,10 0,0 -7,10" fill="blue"/>
<polygon points="0,-20 7,10 0,0" fill="darkblue"/>
</g>
Which I then use like this:
<g class="ship" id="ship3" transform="rotate(-180,480,24) translate(480,24)">
<use xlink:href="#interceptor"/>
</g>
Now, what I would like to do is to add a stroke around the first polygon from the group when the whole group is clicked, but I don't know how to access contents of the interceptor group via jQuery. I was thinking about something like this, but contents() returns nothing:
$(".ship").click(function() {
$(this).find("use").contents().find("polygon").first().attr({"stroke-width":1, stroke:"white"});
});
I can, of course, add a stroke around the entire ".ship" and it works, but it's not what I want because this creates strokes between polygons in the group. Additionally, there can be a number of separate objects that use the #interceptor group, and only the one that is actually clicked should get the stroke. Is that doable?
I have seen transforming the graphic in SVG don't affect the object to be transformed but transform the whole coordinate system and then draw the element in that system.
What does this help to achieve instead calculating the new cordinates for current element in consideration?
I think in canvas and CSS, its same behavior so tagging javascript and CSS also.
I am not sure I understand your question, but let me try:
The transformed element may not be a grafics element, but a container, for example a <g> element. In that case, all child elements inherit the transformed coordinate system.
The element may have associated paint servers (a pattern or a gradient, for example), or filters, masks or clipping paths that have their own sizing and positioning mechanisms. These mechanisms work in the transformed coordinate system.
Here is an example to illustrate. The first rectangle has a linear gradient, whose gradient vector is defined in user space. The second rectangle is identical, but rotated and translated to the side. The gradient is then moved together with the rectangle.
<svg width="200" height="150">
<defs>
<linearGradient id="gradient" gradientUnits="userSpaceOnUse"
x1="0" y1="50" x2="100" y1="50">
<stop stop-color="red" offset="0"/>
<stop stop-color="blue" offset="1"/>
</linearGradient>
</defs>
<rect x="0" y="20" width="100" height="30" fill="url(#gradient)" />
<rect x="0" y="20" width="100" height="30" fill="url(#gradient)" transform="translate(200, 20) rotate(90)" />
</svg>
While the transform attribute only takes userpace coordinates, i. e. unitless numbers, positioning and sizing attributes like x, y, width and height etc. may have unit identifiers like percentage, em or other CSS unit identifiers. That makes it possible to do more versatile positioning.
For example, the following rectangle will always appear at the same size in the middle of the SVG, regardless of it being resized:
<svg width="100%" height="100%">
<rect x="50%" y="50%" width="60" height="60" transform="translate(-30, -30)" />
</svg>
Imagine I have a javascript library that is arbitrarily manipulating the position of two elements. I want to draw a spline (path) that starts at one element and ends on the other one, like:
<circle cx="50" cy="50" r="5" />
<circle cx="100" cy="50" r="5" />
<path d="M 369 320 C 426 320 386 304 444 304"/>
Now, I thought about transforming the origin of the path to match the center of the circle, but that would mean "hardcoding" the coordinates. If I want to move the circle, I would have to recalculate the path data.
So, question (1) how can I do something like that without resorting to javascript? and (2) iff javascript is the sole solution for this problem, then which technique (including libraries) would you recommend that would ease the task of allowing the reference objects to be arbitrarily moved and automate the necessary path recalculations?
I'm trying to create an interactive grid for a web game (HTML, JS, etc.), in which every cell should change it's fill on hover/click. I need both a regular square grid, and a triangular grid. I want it to be vector based so that it will scale nicely to fit different screen sizes. I thought the easiest way would be to create a pattern and fill it on a rectangle. This is the code I have so far:
<pattern id="baseTile" width="10" height="10" patternUnits="userSpaceOnUse">
<path id="tile" d="M 0,0 L 0,10 10,10 10,0 Z" fill="none" stroke="gray" stroke-width="1"/>
</pattern>
For the square, and this for the triangular grid:
<pattern id="baseTile" width="10" height="10" patternUnits="userSpaceOnUse">
<path d="M 5,0 L 10,2.5 10,7.5 5,10 0,7.5 0,2.5 Z" fill="none" stroke="gray" stroke-width=".1" />
<path d="M 5,0 L 5,10" fill="none" stroke="gray" stroke-width=".1" />
<path d="M 0,2.5 L 10,7.5" fill="none" stroke="gray" stroke-width=".1" />
<path d="M 0,7.5 L 10,2.5" fill="none" stroke="gray" stroke-width=".1" />
<path d="M 0,0 L 0,2.5 M 0,7.5 L 0,10" fill="none" stroke="gray" stroke-width=".1" />
<path d="M 10,0 L 10,2.5 M 10,7.5 L 10,10" fill="none" stroke="gray" stroke-width=".1" />
</pattern>
They produce the grids I need, but I don't know how to target each cell individually. I'm guessing since I've found no information on this, it's just not possible, and some other solution other than should be used. Any ideas?
Edit:
I want to be able to cycle through different fills on mouse click. For the square grid, I'm using the code I found here: http://bl.ocks.org/bunkat/2605010 but for the triangular lattice, I have absolutely no idea where to begin. That's why I thought of .
PS: I should probably add I have no programming experience, I'm trying to make a nonogram game to teach myself some Javascript.
Patterns are purely decorative. Targetting a single tile within a pattern would be like targetting a single colour within a gradient. Better not to think about them as distinct "tiles", and instead think of it as a sheet of repeating wallpaper.
So what to do? Well, you are going to need a distinct element for each piece that you want to be able to manipulate. But since they are mostly the same, you'll want to use <use> elements to repeat the graphics. You'll need to do a bit of math to figure out how to position the triangles just right, but no worse than what you had to do to figure out that pattern. It will of course be easiest to create the elements with a loop in your JS script, although you could hard code the original elements in a <defs> section.
Moreover, you don't specify what you want to do with the individual cells. If you are going to be changing their appearance, it might help to remember that you can set styles on the <use> element and these will be inherited by the re-used graphics. So if you don't set fill/stroke directly, you can change them by styling the <use>, instead of having a separate, differently coloured template to swap in.
This question already has answers here:
How to make SVG image pattern fill move with object?
(4 answers)
Closed 1 year ago.
I created the svg pattern seen here:
<pattern id="t" height="20" width="20" patternUnits="userSpaceOnUse" overflow="visible">
<ellipse cx="0" cy="0" rx="20" ry="20" fill="white"/>
<ellipse cx="5" cy="5" rx="15" ry="15" fill="yellow"/>
<ellipse cx="10" cy="10" rx="10" ry="10" fill="blue"/>
<ellipse cx="15" cy="15" rx="5" ry="5" fill="red"/>
</pattern>
Then in my script I created an ellipse that uses the pattern. The problem is, when I move the ellipse around, the pattern stays still behind it instead of moving with the ellipse.
How do I configure the pattern to stay with the element?
You need to use patternContentUnits="objectBoundingBox" click on the rectangle in this example to see: http://jsfiddle.net/longsonr/x8nkz/
Change the patternContentUnits to "objectBoundingBox" (vs. userSpaceOnUse).
More: patternUnits should have no effect on how the pattern is laid out, only its dimensions (userspace units vs. boundingbox units). patternContentUnits is the attribute that you want to set to "objectBoundingBox" - note that that this will then scale your pattern if you change the size of the bounding box. If you don't want this to happen, then you need to use a viewbox attribute on your pattern - which is probably the right way to get the result you're probably looking for (fixed size pattern, positioned relative to its bounding box)
(Also please note that setting overflow to visible results in "undefined" rendering according to the spec aka - not something that you want to do)