I want to draw a triangle in a triangle with Animejs. The triangle should be drawn very slow. Sadly I get a long delay, before the triangle starts to be drawn and on side of the triangle is missing.
My triangle svg:
<div id="lineDrawing"> <svg viewBox="0 0 280 100">
<g fill="none" fill-rule="evenodd" stroke="currentColor" stroke-width="8" class="lines">
<path d="m 29.188247,410.49128 338.094613,0 L 198.23555,47.968205 29.188247,410.49128 Z" stroke-dasharray="300" style="stroke-dashoffset: 316.855px;">
</g>
</svg> </div>
My js:
anime({
targets: '#lineDrawing path',
strokeDashoffset: [anime.setDashoffset, 0],
duration: 80000,
delay: 0,
direction: 'alternate',
loop: true
});
In the end I want to make it look like one of the cornor triangles.
Sorry for any bad js,css or html errors. I'am new to webdesign.
https://youtu.be/JTNgpQWcDIA?t=1m1s
Your SVG triangle seems way out of the viewBox for the most part. The invisible part is also animated, so it seems like nothing is happening.
Related
I have a bunch of <circle> elements, and I want to zoom in on them.
I want to go from this:
To this:
Notice that I'm not enlarging the circles, only the distance between them.
How can I efficiently do this? What I'm doing right now is to setting the cx and cy coordinates individually on each circle. This works, but is slow when I've got thousands of circles.
I can put them all in a <g> and scale that with transform: scale(x);. This is a lot faster, but it will scale both the distances and the size of the circles.
Is there any way to scale the coordinates independently of the circle radius? Can I specify the circle radius in units that relative to screen size, for instance?
I'm using d3 for this, but any solution is appreciated.
The simplest approach IMO is to use zero-length lines, with rounded end caps, to form your circles. You set their diameter using stroke-width. Then you can use vector-effect: non-scaling-stroke to prevent them from scaling when you enlarge the SVG.
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/vector-effect
vector-effect is supported by most modern browsers.
svg {
background-color: black;
}
path {
fill: none;
stroke: #ccc;
stroke-width: 5;
stroke-linecap: round;
vector-effect: non-scaling-stroke;
}
path:nth-child(3) {
stroke: plum;
}
<svg width="100" viewBox="0 0 100 100">
<path d="M 20,20 h 0"/>
<path d="M 20,40 h 0"/>
<path d="M 30,50 h 0"/>
</svg>
<svg width="200" viewBox="0 0 100 100">
<path d="M 20,20 h 0"/>
<path d="M 20,40 h 0"/>
<path d="M 30,50 h 0"/>
</svg>
I have this animation that is made up of lots of rectangles 5px wide.
https://codepen.io/guanzo/pen/rmGqNP
You can see it exhibits wave like behavior. This tells me there must be a way to represent this motion with a single curved line, instead of hundreds of rectangles. Most likely using an svg element like <path> or <polyline>? I think i need to use some modified sine wave function, but i can't wrap my head around the math.
EDIT:
Managed to get a polyline to go up and down with cubicInOut easing.
https://codepen.io/guanzo/pen/vmeoXw
Still no idea how to program the wave like behavior.
EDIT:
My attempt with a path and bezier curve transition. Close, but no cigar.
https://codepen.io/guanzo/pen/XRevME?editors=1010
Instead of animating the line's control points, it would be easier to apply a linear transform to the entire line. Here's a simple example:
<svg width="100%" viewBox="0 0 100 40">
<rect x="0" y="0" width="100" height="40" fill="#fa0" stroke="none"/>
<path d="M0 0V10H0C20 10 50 30 80 30H120C150 30 150 10 180 10 H220C250 10 250 30 280 30H320C350 30 350 10 380 10H400V-10Z" fill="#c00" stroke="none">
<animateTransform attributeName="transform" attributeType="XML" type="translate" from="-300 0" to="-100 0" dur="5s" repeatCount="indefinite"/>
</path>
</svg>
I have a path with an arc that points to a circle:
<svg xmlns="http://www.w3.org/2000/svg" width="300" height="200">
<path d="M10,10 A120,120 0 0,0 200,100" stroke="green" stroke-width="5" fill="none" />
<circle cx="200" cy="100" r="10" stroke="black" stroke-width="5" fill="none" />
</svg>
Now I want that the path ends e.g. 20 pixel (or a few degree, if simpler) before the border of the circle:
How can I archive this? How can I calculate the differing X and Y as target for the arc drawing (in my example the 200,100 in the d argument)?
In the end I will do this with D3, so I need an algorithm.
This could easily be done by applying a variation of the stroke-dasharray trick. You can obtain the total length of the path by calling .getTotalLength(), subtract the length you want the path to end before this calculated length, and set the stroke-dasharray attribute accordingly:
var path = d3.select("path")
.attr("stroke-dasharray", function() {
return this.getTotalLength() - 20;
});
<script src="https://d3js.org/d3.v4.js"></script>
<svg xmlns="http://www.w3.org/2000/svg" width="300" height="200">
<path d="M10,10 A120,120 0 0,0 200,100" stroke="green" stroke-width="5" fill="none" stroke-dasharray="100"/>
<circle cx="200" cy="100" r="10" stroke="black" stroke-width="5" fill="none" />
</svg>
If you want to do this via a geometric algorithm, you will have to first compute the arc's properties such as center (cx, cy), start angle, sweeping angle,...etc from the current available data: radius = 120, start point (10, 10), end point (200, 100) and the two flags (large arc flag and sweep flag). Please refer to section F6.5 in this link for details. Once you have these information, you can compute the new end point easily.
I'm trying to pulsate a star by using animateTransform with type="scale", but instead of scaling around a center of the star, it scales to left and down. How to scale the star around the center?
Svg code:
<svg version="1.1" id="star" xmlns="http://www.w3.org/2000/svg" x="170px" y="385px" width="100px" height="100px" viewBox="0 0 60 60" xml:space="preserve">
<g>
<polygon fill="#DAC978" points="18.832,36.694 5.903,25.156 23.146,23.419 30.125,7.557 37.104,23.419 54.347,25.155 41.417,36.694 45.095,53.629 30.125,44.898 15.155,53.63" />
<path fill="#A58144" d="M30.125,13.765l4.104,9.327l1.175,2.669l2.901,0.292l10.139,1.021l-7.603,6.785L38.665,35.8l0.618,2.851 l2.162,9.957l-8.801-5.134l-2.519-1.469l-2.52,1.469l-8.803,5.134l2.162-9.957l0.619-2.85l-2.175-1.942l-7.603-6.785l10.139-1.021 l2.901-0.292l1.174-2.669L30.125,13.765 M30.125,1.35l-8.681,19.729L0,23.237l16.08,14.352l-4.574,21.063l18.62-10.858 l18.618,10.858L44.17,37.589l16.081-14.352l-21.445-2.159L30.125,1.35L30.125,1.35z" />
<animateTransform
attributeType="xml"
attributeName="transform"
type="scale"
from="0"
by="1"
dur="1s"
repeatCount="10"
/>
</g>
</svg>
jsFiddle with working code.
animateTransform type scale seems to scale always from origin at (0, 0). One possible solution can be in translating your polygon so that its center is in (0, 0).
Here is working jsFiddle example.
Changes made to your original code:
The viewbox is changed from viewBox="0 0 60 60" to viewBox="-30 -30 60 60" in order to have center of the viewBox at (0, 0) (for more on viewBoxes you can see this tutorial)
polygon and path are grouped and then translated so that their center is at (0, 0) too:
<g transform="translate(-30,-30)">
<polygon ... />
<path ... />
</g>
I want to use animateTransform to rotate an SVG image continuously. So here we go:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="1024px" height="768px" enable-background="new 0 0 100 100" xml:space="preserve">
<g transform="translate(100, 100)">
<rect fill="#FE9FFF" width="100px" height="100px">
<animateTransform attributeName="transform" type="rotate"
from="0" to="360" dur="20s" repeatDur="indefinite"/>
</rect>
</g>
</svg>
This works.
Now: I would like to change the above, so that the block rotates around its center and not its top left corner. I know that if I want to rotate the block statically around its center, I can do this:
<g transform="rotate(30, 50, 50)">
<rect fill="#FE9FFF" width="100px" height="100px">
</rect>
</g>
My question is - how do I manage a continuous animated rotation around the block's center? I have looked at the spec and a couple of other related questions on SO, but I'm having trouble implementing the explanations supplied.
Thanks in advance.
http://www.w3.org/TR/SVG/animate.html#AnimateTransformElement
The ‘from’, ‘by’ and ‘to’ attributes take a value expressed using the same syntax that is available for the given transformation type:
(...)
For a type="rotate", each individual value is expressed as <rotate-angle> [<cx> <cy>]
You can specify the center for the rotation if you provide 2 additional values, cx and cy.
So, for your piece of code, I add "50 50" in the "from" and "to" attribute :
<rect fill="#FE9FFF" width="100px" height="100px">
<animateTransform attributeName="transform" type="rotate"
from="0 50 50" to="360 50 50" dur="20s" repeatDur="indefinite"/>
</rect>
It work with latest version of Opera, Safari and Chrome, also Firefrox 4 Beta and Batik.
To be clear: what we are trying to achieve is rotation around a center which is itself being translated. I find that if I have an <animateTransform type=rotate>, I cannot use <animateMotion>, nor <animateTransform type=translate> to perform simultaneous translation. It (latest Chrome or Firefox) does not interpolate the center of rotation as desired, resulting in a "loop de loop" instead. However, using a simple <animate> for each of the x,y coordinates does work as desired; in this case, <animateTransform type=rotate> interpolates the center along the x,y path, as long as you set the from= parameter to the start angle, start x and start y position, and set the to= parameter to the ending values.