path
element - can be found under the cat. path
element is possible thanks to the stroke-dasharray property of the path
element. This property allows you to set the parameters of the dotted line, namely the length of the stroke and the gap between the strokes. If we set the length of the stroke equal to the entire length of the line, we get an ordinary solid line. If we set the stroke length equal to zero, and the gap length is again equal to the entire length of the line, then we get an invisible line. And gradually increasing the length of the stroke with the length of the gap equal to the length of the entire line, we can imitate its drawing. With this approach, drawing will occur from the beginning of the line. If you suddenly need to draw from the end, then you need to use another property: stroke-dashoffset . This property defines the offset for the first stroke. Thus, reducing the offset and increasing the length of the stroke, we get the drawing from the end of the line.requestAnimationFrame
for smooth animation, but we have slightly different goals, so we will go more simply by using the D3.js library and the duration-based animation implemented in it. queue() .defer(d3.xml, "PS4.svg", "image/svg+xml") .await(ready); function ready(error, xml) { //Adding our svg file to HTML document var importedNode = document.importNode(xml.documentElement, true); d3.select("#pathAnimation").node().appendChild(importedNode); var svg = d3.select("svg"), svgWidth = svg.attr("width"), svgHeight = svg.attr("height"); var paths = svg.selectAll("path") .call(transition); function transition(path) { path.transition() .duration(5000) .attrTween("stroke-dasharray", tweenDash) .each("end", function() { d3.select(this).call(transition); }); // infinite loop } function tweenDash() { var l = this.getTotalLength(), i = d3.interpolateString("0," + l, l + "," + l); // interpolation of stroke-dasharray attr return function(t) { return i(t); }; } }
transition(path)
function, we use transition.attrTween (name, tween) , which calls the interpolator defined in the tweenDash()
function. To calculate the length, use the getTotalLength () method defined for the SVG path
elements. Then, using the d3.interpolateString (a, b), the interpolator of the property stroke-dasharray
, which interpolates the values ​​from the stroke-dasharray: 0,l;
before stroke-dasharray: l,l;
(here the first value specifies the length of the stroke, and the second length of the gap). You can see how this works on bl.ocks.org : PlayStation 4: SVG animation .path
. In general, the preparation and optimization of vector images for the web is a rather extensive topic with a lot of nuances pulling on a separate article.path
has another very useful method - getPointAtLength (distance in float) . It allows you to get the coordinates of a point located at a given distance from the beginning of the line. With it, you can realize the movement of any marker along the line, and, importantly, a smooth rotation by calculating the tangent to the existing line. queue() .defer(d3.xml, "wiggle.svg", "image/svg+xml") .await(ready); function ready(error, xml) { //Adding our svg file to HTML document var importedNode = document.importNode(xml.documentElement, true); d3.select("#pathAnimation").node().appendChild(importedNode); var svg = d3.select("svg"); var path = svg.select("path#wiggle"), startPoint = pathStartPoint(path); var marker = svg.append("circle"); marker.attr("r", 7) .attr("transform", "translate(" + startPoint + ")"); transition(); //Get path start point for placing marker function pathStartPoint(path) { var d = path.attr("d"), dsplitted = d.split(" "); return dsplitted[1].split(","); } function transition() { marker.transition() .duration(7500) .attrTween("transform", translateAlong(path.node())) .each("end", transition);// infinite loop } function translateAlong(path) { var l = path.getTotalLength(); return function(i) { return function(t) { var p = path.getPointAtLength(t * l); return "translate(" + px + "," + py + ")";//Move marker } } } }
pathStartPoint(path)
pulls the coordinates of the beginning of the line from the attribute d of the path
element. In translateAlong(path)
, using the interpolator, we set the coordinates of our marker. An example can be found here: Marker animation along SVG path element with D3.js. You can also combine line drawing animation and marker movement, it can look like this: Marker animation along SVG path element with D3.js II .48
and a length of 24
. Since by default the marker's snap point is the upper left corner, we need to shift it so that the snap is to the center of the marker. It is also necessary to take this into account when rotating, because it also occurs by default around the upper left corner. With an offset sort of sorted out. Now let's proceed directly to the rotation, here the tangent definition will help us, the angle will be determined using the arctangent.translateAlong(path)
function that defines the interpolator will look like this: function translateAlong(path) { var l = path.getTotalLength(); var t0 = 0; return function(i) { return function(t) { var p0 = path.getPointAtLength(t0 * l);//previous point var p = path.getPointAtLength(t * l);////current point var angle = Math.atan2(py - p0.y, px - p0.x) * 180 / Math.PI;//angle for tangent t0 = t; //Shifting center to center of rocket var centerX = px - 24, centerY = py - 12; return "translate(" + centerX + "," + centerY + ")rotate(" + angle + " 24" + " 12" +")"; } } }
path
, and there is a lot to come up with.Source: https://habr.com/ru/post/207908/
All Articles