SVG Animation - Reverse and stop after 50px from top - svg

How can I reverse the SVG animation ... Need to animate from TOP to BOTTOM?
And I want to stop the round after 50px from top (from 0 to 50px it has to animate and stop)
svg {
border: 3px solid #eee;
display: block;
margin: 1em auto;
}
p {
color: #aaa;
text-align: center;
}
<svg width="100" height="200" viewBox="0 0 200 500">
<path id="motionPath" fill="none" stroke="#ED1E25" stroke-width="4" stroke-miterlimit="10" stroke-dasharray="10,8" d="M53.738,2243.583
c0,0,53.198-53.916,58.558-133.25S64.321,1976.33,49.655,1954.33s-44.331-55.33-44-122.664
c0.111-22.688,9.666-77.666,48.666-129.333c24.376-32.293,40.667-85.68,41.667-118.678c0,0,3.667-63.012-34.333-114.345
c-10.717-14.478-56.003-66.333-47.001-133c3.597-26.633,11.017-64.334,44.509-107s57.491-91.004,53.133-144.337
c-2.348-28.726-11.975-80.665-59.975-133.665C31.307,928.106-6.345,864.978,8.988,791.978c1.793-8.538,15.666-62.331,44.666-95.998
s47.334-113.995,41.334-147.995c-2.515-14.252-5-58.736-54.042-116.589c-16.472-19.432-39.65-81.737-20.958-134.07
c8.677-24.293,20-51.077,26.5-60.577s34-51.25,38-84.25c1.444-11.916,10.5-87-31-144.584"/>
<circle id="circle" r="10" cx="0" cy="0" fill="tomato" />
<animateMotion
xlink:href="#circle"
dur="5s"
begin="0s"
fill="freeze"
repeatCount="1">
<mpath xlink:href="#motionPath" />
</animateMotion>
</svg>

You can reverse the animation with:
keyPoints="1;0" keyTimes="0;1" calcMode="linear"
in the animationMotion definition. With these attributes you can also stop the animation and go back to the start. I just added a black line at ~ 50px (50px + the margin on top) and modified the keyPoints that the circle turns at this line. It's
keyPoints="1;0.952;1" keyTimes="0;0.5;1" calcMode="linear"
in your case. That's not the cleanest way, because it's not exactly after 50px, but if you don't want to add a new path, which has the needed length of your animation path, you have to test a little bit.
Working fiddle: https://jsfiddle.net/df4qt9zz/
Moreover keep in mind that SVG is scalable, so the 50px will be around 100px if the size of the SVG is getting bigger.

Related

Half of line stroke is hidden on the SVG edge

If SVG line touches SVG edge, half of the line stroke will be outside of SVG and will be hidden (see example of line chart below, last tick at the right has half-width tickness).
What are the techincs to avoid it? Is there a way to scale out SVG a little bit, so the SVG image will be smaller and don't touch SVG borders? Something like adding padding?
I'm using non-fixed aspect ratio as height:1rem and width:100%, as it's supposed to take all the place available.
The viewbox scaling doesn't work
svg {
display: block;
}
.chart {
width: 300px;
border: 1px solid #ccc;
}
<div class="chart">
<svg height="1rem" width="100%" class="text-left" viewBox="-5% 0 105% 1rem">
<line x1="25%" y1="5%" x2="25%" y2="25%" stroke="#6B7280" stroke-width="2"></line>
<line x1="50%" y1="5%" x2="50%" y2="25%" stroke="#6B7280" stroke-width="2"></line>
<line x1="100%" y1="5%" x2="100%" y2="25%" stroke="#6B7280" stroke-width="2"></line>
<rect x="0%" y="25%" width="15.138888888888888%" height="50%" fill="#111827"></rect>
</svg>
</div>

Sizing pattern element based on viewport

I have a large svg image that will be scrolled. I would like to add a tiled background image behind all the elements. This is currently leaving me with two problems:
I haven't found a way to keep a background image fixed, and not scroll it with the svg elements on top of it.
Assuming that's not possible, I wanted to size the tile elements to occupy 20% of the viewable area rather than 20% of the total svg size.
<svg width="3560.00px" height="1350.00px" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<pattern id="G-BG" width="20.00%" height="20.00%">
<image xlink:href="https://static.vecteezy.com/system/resources/thumbnails/000/301/800/small/jfyo_waxi_190121.jpg" x="0" y="0" width="20.00%" height="20.00%"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#G-BG)" fill-opacity="0.20"/>
<circle fill="green" cx="200" cy="200" r="100.00"/>
</svg>
If you run this little example, it sets a background composed of 5 x 5 copies of some arbitrary image, but the repeat interval of the tiling is based on 20% of the full svg size. If I try and use vw/vh units then the pattern size seems to go to zero, and so disappear.
My ideal choice would be to have a fixed 5 x 5 image that doesn't scroll, but the CSS background support doesn't seem to work for for svg.
My second choice would be to have a scrolling background image, but where there are 5 x 5 tiles visible at any one time.
Can either of these goals be achieved?
Not sure if there is anything here that might help?
html,body{
height: 100%;
}
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrapper{
width: 100%;
height: 100%;
}
.wrapper svg{
background-color: 'red';
top: 0;
left:0;
position: fixed;
width: 100%;
height: 100%;
}
<div class="wrapper">
<svg xmlns="http://www.w3.org/2000/svg" >
<pattern id="pattern" width="0.2" height="0.25" viewBox="0 0 1 1" preserveAspectRatio="xMidYMid meet">
<image width="0.5" height="0.5" href="https://static.vecteezy.com/system/resources/thumbnails/000/301/800/small/jfyo_waxi_190121.jpg" />
</pattern>
<rect x="0" y="0" width="100%" height="100%" fill="url(#pattern)"></rect>
</svg>
</div>

Unable to get true white, true balck in stroke

I'm trying to implement a "marching ants" style animated selection box using svg. The scheme of animating the border's dash pattern seems to work great, except for some reason I can't get true black/true white for the colors.
(Using ff 68.0.2 64-bit, in case that matters)
<svg height="110" width="200">
<circle cx="100" cy="50" r="40" stroke="black" stroke-width="3" fill="red" /> <!-- for sample overlay -->
<g fill="none" stroke="#000000" stroke-width="1">
<path id="solid" stroke-dasharray="" d="M5 40 l215 0" />
</g>
<g fill="none" stroke="#ffffff" stroke-width="1">
<path stroke-dasharray="4,8,4,0" d="M5 40 l215 0" />
</g>
<rect x="1" y="1" width="100" height="100" style="fill:rgba(0,0,0,0);stroke-width:1;stroke:rgb(0,0,0)"/>
<rect x="1" y="1" id="ants" width="100" height="100" stroke-dasharray="4,8,4,0" style="fill:rgba(0,0,0,0);stroke-width:1;stroke:#ffffff"/>
Sorry, your browser does not support inline SVG.
</svg>
JsFiddle
After fiddling with this some more I discovered that when increasing the stroke width the colors get closer to desired.
Turns out anti-aliasing is being stupid. If I turn on shape-rendering="crispEdges" then the colors work as expected.
Unfortunately it also leaves the jaggies, which is, of course, why anti-alising exists.
If this is "the solution", I guess I'll settle for it, but if somebody knows how to make anti-aliasing clean up the line edges without dulling the colors so badly, that would be ideal.
UPDATE: I'm going to go ahead and accept this. Once animated, it isn't all that bad.
#keyframes marchingAnts {
0% { stroke-dashoffset: 0 }
100% { stroke-dashoffset: 50 }
}
.ants, .antsBackground {
stroke-width: 1;
fill: none;
shape-rendering: crispEdges;
}
.ants {
stroke: #ffffff;
animation: marchingAnts 2400ms linear infinite;
stroke-dasharray: 5,5,0,0;
}
.antsBackground {
stroke: #000000;
}
Here's a JsFiddle of that with css animation, and for comparison, the 2-pixel width solution from the comments on the OP as well.

SVG Use -- Unable to repostion polygon after rotation

I am trying to create a 16 point star inside a circle using SVG and pure CSS -- no JS!
My strategy is to create 16 equilateral triangles (via Defs and Use, to keep it DRY), rotating each Use iteration by 22.5 degrees.
My problem is that when I apply the rotate() transform to the second triangle, SVG changes the center point of the triangle -- which CSS3 does not (it rotates around a fixed axis).
I have tried adding x and y parameters, adding a class and doing a translate() transform, doing that inline... nothing works -- I just cant figure out how to move the triangle back into position (with a rotation) inside the circle (centered at 150, 150 I reckon).
Any help would be appreciated. Here is the SVG line of code that I am having trouble with.
<use xlink:href="#triangle" style="transform: rotate(22.5deg);" />
You can see it in action here.
<style > .toile {
display: flex;
flex-direction: column;
max-width: 400px;
max-height: 800px;
justify-content: center;
align-items: center;
/* centers outer containing element (the circle) horizontally & vertically */
border: 5px #009000;
/* green */
border-style: groove;
background-color: #f9e4b7;
margin: 0 auto;
/* centers surface on a page */
}
<div class="toile">
<svg>
<defs>
<pattern id="grid" width="15" height="15" patternUnits="userSpaceOnUse">
<rect fill="white" x="0" y="0" width="14" height="14"/>
<rect fill="#009000" x="14" y="0" width="1" height="14"/>
<rect fill="#009000" x="0" y="14" width="14" height="5"/>
</pattern>
<g id="triangle">
<svg>
<polygon points="150,18 200,100 100,100"
style="stroke:#009000;stroke-width:1; fill:#afeeee; opacity:.7" />
</svg>
</g>
</defs>
<rect fill="url(#grid)" x="0" y="0" width="100%" height="100%" />
<svg viewBox="0 100 400 400" stroke="#009000" stroke-width=".5" width="300" height="300" class="cercle">
<circle cx="50%" cy="50%" r="75" fill="transparent" /> </svg>
<svg viewBox="0 100 400 400" stroke="#ce2029" stroke-width=".5" width="300" height="300">
<circle cx="50%" cy="50%" r="2" fill="#ce2029" /> </svg>
<use xlink:href="#triangle" />
<use xlink:href="#triangle" style="transform: rotate(22.5deg);" />
</svg>
</div>
Thank you for any solution to this problem; I just can't figure it out! Please no JS solutions!
UPDATE:
I've changed the 16-point gon to a 15 point one, as for some reason a series of 22.5 degree rotations create an unbalanced hexadecagon. I got rid of the red circle center point, and the background grid, and added SVG animation. Here is the (final) working example.
Sorry about the CodePen but I am trying to figure out how to make snippets work for an entire HTML/CSS/SVG program.
This is one way of doing it:
First I simplified your code. Unless you have a good reason to do it like this, it's always better to keep things simple.
I calculated the points tor the triangle around the center of the svg canvas:
<polygon id="triangle" points="200,125 264.95,237.5 135.05,237.5"
I rotate the triangle using svg transforms: transform="rotate(22.5,200,200)"
The first value is the rotation in degs and next you have the x and y of the rotation center.
As it comes out with SVG transforms you don't have IE issues. Please read this article about Transforms on SVG Elements
.toile {
display: flex;
flex-direction: column;
max-width: 400px;
max-height: 800px;
justify-content: center;
align-items: center;
/* centers outer containing element (the circle) horizontally & vertically */
border: 5px #009000;
/* green */
border-style: groove;
background-color: #f9e4b7;
margin: 0 auto;
/* centers surface on a page */
}
<div class="toile">
<svg viewBox="0 0 400 400" stroke="#009000" stroke-width=".5" width="300" height="300" >
<defs>
<pattern id="grid" width="15" height="15" patternUnits="userSpaceOnUse">
<rect fill="white" x="0" y="0" width="14" height="14"/>
<rect fill="#009000" x="14" y="0" width="1" height="14"/>
<rect fill="#009000" x="0" y="14" width="14" height="5"/>
</pattern>
<polygon id="triangle" points="200,125 264.95,237.5 135.05,237.5"
style="stroke:#009000;stroke-width:1; fill:#afeeee; opacity:.7" />
</defs>
<rect fill="url(#grid)" x="0" y="0" width="100%" height="100%" />
<circle class="cercle" cx="50%" cy="50%" r="75" fill="transparent" />
<circle cx="50%" cy="50%" r="2" fill="#ce2029" />
<use xlink:href="#triangle" />
<use xlink:href="#triangle" transform="rotate(22.5,200,200)" />
</svg>
</div>
UPDATE
To calculate the points for the triangle you may use javascript. In the case of a regular polygon like a triangle all 3 vertices are on a circumscribed circle at a 2*Math.PI/3 angle one from each other. I'm starting with an offset of -Math.PI/2 (-90 degs) for the first vertex.
// the center of the SVG canvas calculated from the values of the viewBox attribute. Alternatively you can choose a different point
let c = {x:200,y:200}
let radius = 75;
let points = [];
for(let a = -Math.PI/2; a < 3*Math.PI/2; a+= 2*Math.PI/3){
let x = c.x + radius*Math.cos(a);
let y = c.y + radius*Math.sin(a);
points.push(x);
points.push(y);
}
tri.setAttributeNS(null, "points", points.join());
svg{border:1px solid;height:90vh}
<svg viewBox="0 0 400 400">
<polygon id="tri" />
</svg>

Box shadow animation on SVG element

Is there any option to animate CSS box-shadow effect on SVG element?
I have this markup:
<g id="g-svg_el_obj921" style="top: 300px; left: 550px;">
<circle r="95.12" fill="rgb(50, 149, 196)" class="some_class" id="svg_el_obj921" priority="4" position="300_550" cx="550" cy="300"></circle>
</g>
and this animation setup:
circle {
cursor: pointer;
-webkit-animation: shadow_fly 310ms infinite ease-in-out;
#-webkit-keyframes shadow_fly {
0% {-webkit-svg-shadow: 0 0 7px #53BE12;}
50% {-webkit-svg-shadow: 0 0 30px #53BE12;}
99% {-webkit-svg-shadow: 0 0 7px #53BE12;}
}
&:hover {
}
}
Thx for help.
Yes filters can be animated:
Here is how to create shadow/inset/blur filters on svg
<svg id="obj921">
<filter id="imagenconturbulencias" x="0" y="0" width="100%" height="100%">
<feTurbulence result="cloud" baseFrequency=".01" seed="1" stitchTiles="nostitch" type="fractalNoise" numOctaves="2">
<animate attributeName="baseFrequency" calcMode="paced" begin="0s" dur="12s" values=".01;.13;.01;" repeatCount="indefinite"/>
</feTurbulence>
<feComposite operator="in" in="cloud" in2="SourceGraphic"/></filter>
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
<svg>
<use filter="url(#imagenconturbulencias)" xlink:href="#obj921"></use>
</svg>
run this snippet!
animate/> tag goes inside filter/> description tag /look closely
The circle in < use > tag is the animated one, you have to hide the original sprite as smart as you can. That is common task in using sprites - advantage for this approach is, you can reference {use} this sprite in many places over your page, but it's vector values are loaded once (that saves space)
There is not, at least with css-animation, it's only possible for html elements, not svg elements.

Resources