I have a simple animation that fills an svg from the bottom up and then fades out. The filling is done using a clipPath along with using a path with a stroke-dasharray & stroke-dashoffset.
The problem is the clipPath seems to be completely ignored on Safari. I've seen many other examples and questions answered that make use of the clip-path property in Safari successfully, but not in this case.
Any ideas of what specifically is stopping Safari from rendering this correctly?
Link to JSFiddle: https://jsfiddle.net/7qzf4c4j/1/
.pen {
-webkit-clip-path: url(#logoclip);
clip-path: url(#logoclip);
stroke-dasharray: 60 60;
stroke-dashoffset: 60;
-webkit-animation: fill-logo 2.7s infinite linear;
animation: fill-logo 2.7s infinite linear;
}
#keyframes fill-logo {
0% {
stroke-dashoffset: 60;
opacity: 1;
}
50% {
stroke-dashoffset: 0;
opacity: 1;
}
75% {
stroke-dashoffset: 0;
opacity: 1;
}
90% {
stroke-dashoffset: 0;
opacity: 0;
}
100% {
stroke-dashoffset: 0;
opacity: 0;
}
}
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-305 397.9 70 60.1" enable-background="new -305 397.9 70 60.1">
<defs>
<clipPath id="logoclip">
<path d="m-270 397.9c-22.9 11.5-35 25.4-35 40.3 0 5.9 1.8 10.9 5.3 14.4 3.4 3.5 11-3.7 2.7-2.3 4.2-5.6 4.2-9.1v-8.6c0-1-.3-2.1-.9-3-1 .5-2 .8-2.9.8-1.4 0-2.4-.8-2.4-1.8 0-1 .9-1.7 2.3-1.7 1.2 0 2.3.6 3.2 1.7.3-.2.6-.4.9-.6-1.5-1.4-2.3-2.9-2.3-4.1 0-1.1.7-1.8 1.7-1.8.4 0 .8.2 1.2.5.3-.3.7-.5 2.7-2.3 4.1.3.2.6.4.9.6.9-1.1 2.1-1.7 3.2-1.7 1.3 0 2.3.7 2.3 1.7 0 1-1 1.8-2.4 1.8-1 0-1.9-.3-2.9-.8-.6.9-.9 2-.9 3v8.6c0 7.2 6.7 12.8 15.2 12.8 5.6 0 10.3-1.9 13.7-5.4 3.4-3.5 5.3-8.5 5.3-14.4 0-14.8-12.1-28.8-35-40.3"/>
</clipPath>
</defs>
<path class="pen" d="m-270,458 l0,-60.1" stroke="black" stroke-width="100" />
</svg>
Ben, my suggestion probably looks funny, but remove -webkit-clip-path:url(#logoclip); from your .pen. Keep clip-path:url(#logoclip); (without -webkit-) only.
In my Safari 10.1.1 it does the trick.
Kosh pointed out the main issue with this code but another thing that gave me a major headache was the project I'm working on has a base tag which is treated differently in Safari when referencing urls for clip-paths.
This SO question covers it well: Using base tag on a page that contains SVG marker elements fails to render marker
As a reference the way I fixed this was to use an existing Angular.js directive already encapsulating the svg to watch the location and update the url between navigations, like this:
// manually replace url of svg to circumvent base href
var pen = element.find('.pen')[0];
scope.$watch(function() {
return location.href;
}, function(newVal, oldVal) {
pen.style.clipPath = 'url('+newVal+'#logoclip)';
});
The output then becomes something like this:
clip-path: url(http://localhost:3000/page#logoclip);
EDIT: I also thought that maybe the reason -webkit-clip-path wasn't working was because it required a full path, but I tried setting the property using the code above and it still doesn't render the clip-path properly. I assume this is a bug specifically with -webkit-clip-path although if anyone has any info I'd be interested in knowing why this happens.
Related
I am working on a project with a lot of SVG-animation. I have no experience in this. I have Googled extensively without finding the solution to my problem.
The problem is that when animating certain shapes, the animation leaves a gap in the shape. This is most prevalent on shapes with angles, like a triangle.
I have seen this done successfully around the web, I just don't understand how. I have made a simple animation using Vivus Instant that you can see in this CodePen: Link to CodePen
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 242.89 367.25" class="start" style=""><title>triangeltest</title><path style="fill:#fff;stroke:#1d1d1b;stroke-miterlimit:10;stroke-width:15px" d="M121.44,23.89L10.38,359.75L232.51,359.75L121.44,23.89Z" class="fTJakOHn_0"></path><style data-made-with="vivus-instant">.fTJakOHn_0{stroke-dasharray:930 932;stroke-dashoffset:931;}.start .fTJakOHn_0{animation:fTJakOHn_draw 3000ms ease-in 0ms forwards;}#keyframes fTJakOHn_draw{100%{stroke-dashoffset:0;}}#keyframes fTJakOHn_fade{0%{stroke-opacity:1;}94.44444444444444%{stroke-opacity:1;}100%{stroke-opacity:0;}}</style></svg>
Are there any libraries I can use that automatically avoids this problem? Do I have to export the shapes from Illustrator in a specific way?
What I would do is just disable the dash array once the animation completes.
#keyframes fTJakOHn_draw {
99.9% { stroke-dashoffset:0; stroke-dasharray:930 932; }
100% { stroke-dasharray: none; }
}
If the animation needs to be able to restart after the fade animation, you might also need to put the dash pattern back afterwards.
#keyframes fTJakOHn_fade {
0% { stroke-opacity:1; }
94.44444444444444% { stroke-opacity:1; stroke-dasharray: none; }
100% { stroke-opacity:0; stroke-dasharray:930 932; }
}
Example:
.fTJakOHn_0 {
stroke-dasharray:930 932;
stroke-dashoffset:931;
}
.start .fTJakOHn_0 {
animation:fTJakOHn_draw 3000ms ease-in 0ms forwards;
}
#keyframes fTJakOHn_draw {
99.9% { stroke-dashoffset:0; stroke-dasharray:930 932; }
100% { stroke-dasharray: none; }
}
#keyframes fTJakOHn_fade {
0% { stroke-opacity:1; }
94.44444444444444% { stroke-opacity:1; stroke-dasharray: none; }
100% { stroke-opacity:0; stroke-dasharray:930 932; }
}
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 242.89 367.25" class="start" style=""><title>triangeltest</title>
<path style="fill:#fff;stroke:#1d1d1b;stroke-miterlimit:10;stroke-width:15px" d="M121.44,23.89L10.38,359.75L232.51,359.75L121.44,23.89Z" class="fTJakOHn_0"></path>
</svg>
Not sure if there's any easier way of doing this, the closest solution I found recently was using a clip path on the SVG itself. I've just stuck this on your codepen example as a tester:
svg {
clip-path: polygon(50% 6.4%, 0 100%, 100% 100%);
}
You may want to increase the stroke width if needed? It's not pretty, but it gets the result.
One possible solution would be adding stroke-linecap:round; stroke-linejoin:round; for the triangle:
Layer_1.addEventListener("click",()=>{Layer_1.classList.toggle("start")})
svg{border:1px solid;width:200px;}
<svg id="Layer_1" viewBox="0 0 242.89 367.25" class="start" ><title>triangeltest</title>
<path style="fill:#fff;stroke:#1d1d1b;stroke-miterlimit:10;stroke-width:15px" d="M121.44,23.89L10.38,359.75L232.51,359.75L121.44,23.89Z" class="fTJakOHn_0"></path>
<style data-made-with="vivus-instant">
.fTJakOHn_0{
stroke-dasharray:930;
stroke-dashoffset:930;
stroke-linecap:round;
stroke-linejoin:round;
}
.start .fTJakOHn_0{
animation:fTJakOHn_draw 3000ms ease-in 0ms forwards;
}
#keyframes fTJakOHn_draw{
100%{stroke-dashoffset:0;}
}</style>
</svg>
I have this SVG that I want to smoothly fill from left to right. How can I do that using CSS?
I don't want the line to be moving, i want it filling smoothly from left to right while staying in the same place, that's why i'm using svg.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="324" height="25" viewBox="0 0 324 25">
<g id="btn_underline">
<path id="V" d="M88.029,0.613 C58.722,-0.156 29.992,3.400 1.839,11.183 C-1.140,12.047 0.205,16.660 3.184,15.795 C28.262,8.781 54.014,5.321 80.438,5.321 C83.801,5.321 86.203,5.321 87.836,5.417 C96.196,5.610 105.324,6.282 115.413,7.339 C125.503,8.396 133.958,9.453 140.588,10.510 C147.218,11.471 156.346,12.912 167.781,14.834 C182.098,17.236 194.397,19.158 204.582,20.599 C223.511,23.194 240.519,24.443 255.412,24.443 C259.256,24.443 262.138,24.443 264.060,24.347 C274.726,23.962 284.623,23.001 293.655,21.368 C303.936,19.542 313.449,17.044 322.385,13.873 C323.634,13.489 324.307,12.047 323.826,10.798 C323.250,9.357 322.193,8.877 320.751,9.357 C311.815,12.624 302.495,15.026 292.790,16.660 C283.758,18.197 274.149,19.158 263.868,19.542 C246.668,20.023 227.066,18.774 205.159,15.795 C195.742,14.546 183.539,12.624 168.549,10.126 C156.635,8.108 147.506,6.667 141.069,5.706 C134.631,4.745 126.271,3.688 115.990,2.631 C105.709,1.478 96.388,0.805 88.029,0.613 z" fill="#00363B" />
</g>
</svg>
http://codepen.io/anon/pen/GrQPvK
You can indeed do this in CSS with the stroke property.
I'm sorry by advance, I can't use your SVG because it's a shape and in order to make your effect you only need a path without fill. So I take this SVG for the example (from this article : https://jakearchibald.com/2013/animated-line-drawing-svg/):
<svg xmlns="http://www.w3.org/2000/svg" height="98" width="581" viewBox="0 0 581 98">
<path
class="path"
d="M62.9 14.9c-25-7.74-56.6 4.8-60.4 24.3-3.73 19.6 21.6 35 39.6 37.6 42.8 6.2 72.9-53.4 116-58.9 65-18.2 191 101 215 28.8 5-16.7-7-49.1-34-44-34 11.5-31 46.5-14 69.3 9.38 12.6 24.2 20.6 39.8 22.9 91.4 9.05 102-98.9 176-86.7 18.8 3.81 33 17.3 36.7 34.6 2.01 10.2.124 21.1-5.18 30.1"
stroke="#000"
stroke-width="4.3"
fill="none">
</path>
</svg>
Notice the stroke and stroke-width properties. It's the beginning of the trick ;). Then you need to add some CSS :
.path {
//we divide the line in multiple dashes (some full and other empty)
//these dashes have 1000px in length
//so there are one dash full of 1000px of length and then one dash empty of 1000px of length and so on and so forth
stroke-dasharray: 1000;
//we change the position of the dashes
stroke-dashoffset: 1000;
//now we animate the dashoffset
//we reduce the offset of each dash so we have the impression that the dashes are moving
animation: dash 5s linear forwards;
}
#keyframes dash {
to {
stroke-dashoffset: 0;
}
}
And that's it !
For more information, you can read this article too : https://css-tricks.com/svg-line-animation-works/
You could work from this.
svg {
left: -400px;
position:absolute;
}
#keyframes example {
from {left: -400px;}
to {left: 200px;}
}
#-webkit-keyframes example {
from {left: -400px;}
to {left: 200px;}
}
svg {
animation-name: example;
animation-duration: 4s;
animation-delay: 2s;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
}
ccodepen: http://codepen.io/anon/pen/egVbMV
Try this
.fadeIn {
animation-name: fade-in-left;
animation-duration: 1s;
}
#keyframes fade-in-left {
0% {
opacity: 0;
transform: translate3d(-100%, 0, 0);
}
100% {
opacity: 1;
transform: none;
}
}
Live demo - http://codepen.io/anon/pen/MJQLgG
I am trying to show animated dashed lines in an SVG path.
Path is generated dynamically using d3 and animation can be in both the directions. Its working in all browsers except in IE. Fiddle Link
My issue is similar to SVG animation is not working on IE11 . But I couldn't get the solution from there.
<path id="pathOriginal" class="animation" style="animation-direction:reverse" d="M535,73C33.75,73 33.75,-20 -467.5,-20" stroke="red" stroke-width="1.5px" fill="none">
#keyframes dash {
from {
stroke-dashoffset: 1000;
}
to {
stroke-dashoffset: 0;
}
}
#-webkit-keyframes dash {
from {
stroke-dashoffset: 1000;
}
to {
stroke-dashoffset: 0;
}
}
.animation {
stroke-dasharray: 4;
stroke-dashoffset: 4;
animation: dash 50s linear infinite;
-webkit-animation: dash 2s linear infinite;
}
Last resort is to use some javascript magic!
var myPath = document.getElementById('pathOriginal');
var i = 1000;
var intervalID = window.setInterval(myCallback, 20);
function myCallback() {
// Your code here
if (i == 0) { i = 1000}
myPath.setAttribute('stroke-dashoffset', i);
--i;
}
<svg width="500" height="500" id="svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g transform="translate(200,200)">
<path id="pathOriginal" class="animation" style="animation-direction:reverse" d="M535,73C33.75,73 33.75,-20 -467.5,-20" stroke="red" stroke-width="1.5px" fill="none" stroke-dasharray="4">
</path>
</g>
</svg>
IE don't support CSS animations on all SVG elements.
you have to modify the inline attributes of the SVG elements
I'm trying to work on a SVG handwriting animation. I've already researched some tutorials but all them are using SVG stroke properties and it's not quite working for me, because in my situation the animation should be on the fill, not the stroke.
I've found things like that:
svg path {
fill: none;
stroke: #000;
stroke-width: 1;
stroke-linecap: round;
stroke-linejoin: round;
stroke-dasharray: 1700;
stroke-dashoffset: 1700;
-webkit-animation: dash 5s linear forwards;
animation: dash 5s linear forwards;
}
#-webkit-keyframes dash {
to {
stroke-dashoffset: 0;
}
}
#keyframes dash {
to {
stroke-dashoffset: 0;
}
}
Here's the SVG I'm working on: http://codepen.io/boyporreta/pen/BNewgG
Is there a way to create this animation using fill instead of stroke?
Thanks in advance.
I thought I'd have a go at Erik's suggested method. Combining the stroke animating technique from here with his suggestion to clip I came up with this
.pentip {
stroke-linecap:round;
stroke-linejoin:round;
fill:none;
stroke:#e21b1b;
stroke-width:15;
stroke-dasharray: 1454;
stroke-dashoffset: 1454;
animation: dash 5s linear forwards;
}
#keyframes dash {
to {
stroke-dashoffset: 0;
}
}
<link href="https://fonts.googleapis.com/css?family=Pacifico" rel="stylesheet">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 341.61432 138.25008">
<defs>
<clipPath id="svgTextPath">
<text x="10" y="94"
font-family='Pacifico'
font-size="95">Monkey</text>
</clipPath>
</defs>
<g clip-path="url(#svgTextPath)">
<path class="pentip" d="M7.6 39.8l17.5-22 5.6 5.7-3.4 52-3 17.2L46.5 30s9.2-13.3 15-11c10.2 4.2-1.3 74-1.3 74S82 16 93.6 19.6c20.2 6-6 64 6.3 67.4 12.2 3.4 21-15 21-15l6.4-16.2 15.2-1s-19.4 5.7-19.4 6.7l-1 21.5 10.7 6.3L144 73l-8-20.4L164.5 69l2-17.7L163 90l22-36.3-.2 33.5 20.2-8.4 3-42.7 14.3-28.5 8.5 4.5s-13 46.4-14.2 47.2c-1 .7-12 28-12 28l15.2-19.6s13.6-18 17.8-12.6c4.2 5.2-11.8 28.3-11.8 28.3s-1 5.8 8 5.5c8.8-.3 19.3-14.4 25.3-16.3 6-1.8 17.6-11.2 11.5-16.7-6-5.6-21.2-1-21 8 .3 9.3 0 24.7 11.3 24.7s21.3-3 23.6-10.7c2.4-8 9.5-28.3 7-25.7-2.3 2.7-11.7 15-8.8 24.7 3 9.7 9 16.6 16 10.3 7-6.3 17.3-35.4 14.7-33.6-2.6 1.8-12 61.6-12 61.6l-12.8 15.8-12-2.7s2-4 7.2-12.2c5.3-8 32-24 36-27.3 4-3 14.6-17.3 14.6-17.3"/>
</g>
</svg>
You'd obviously be a bit more careful with your stroke creation!
The svg engine doesn't know that the path fill in your example is handwriting, and there's no defined direction for the handwriting motion.
Calligraphy makes it a little harder to accomplish since there's no built-in support for variable stroke widths in svg. However, it might be passable to do a clip-path animation, using the animation code you quoted, but on a "crude copy" of the original path which has been converted to just a thick stroke, without fill. That clip-path can then be applied to the original path in your example to give an impression of the calligraphic stroke being drawn.
Another option is to not use a path, but to draw the whole thing with lots of small rectangles along the path. This implies using javascript instead of css animation.
I saw this SVG animation and I'm wondering how to alter the direction that the line is erased in; currently the line retracts from the last point it is drawn, however I want the reverse; for the line to erase itself from the point where it first started to draw (so that it looks more like a loading animation).
I see that the animation property on .path has a value of infinite, but I'm not sure how the direction is specified.
The HTML is
<div class="bg">
<svg xmlns="http://www.w3.org/2000/svg" width="670" height="236" viewBox="0 0 670 236">
<path class="path" stroke="#4CADC1" stroke-width="4" stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="300" stroke-dashoffset="300" fill="none" d="M343.6 75.9v20.3l23.1 21.8-23.1 21.8v20.3l44.6-42.1zM326.4 139.8l-23.1-21.8 23.1-21.8v-20.3l-44.6 42.1 44.6 42.1z"/>
<path class="path" stroke="#4CADC1" stroke-width="4" stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="500" stroke-dashoffset="500" fill="none" d="M335 38.9c-43.7 0-79.1 35.4-79.1 79.1s35.4 79.1 79.1 79.1 79.1-35.4 79.1-79.1-35.4-79.1-79.1-79.1zM335 182.9c-35.8 0-64.9-29.1-64.9-64.9s29.1-64.9 64.9-64.9 64.9 29.1 64.9 64.9-29.1 64.9-64.9 64.9z"/>
</svg>
</div>
And the CSS is
body {
background-color: #fff;
}
.bg {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.path {
animation: draw 3.5s infinite;
}
#keyframes draw {
50% {
stroke-dashoffset: 0;
}
}
I like your idea of making this an loading animation:
CODEPEN
Now what i did:
changed the animation start stop point
#keyframes draw {
100% {
stroke-dashoffset: -500;
}
}
Why -500?
Because this is the value of the dash-array.
This is defined in the <svg>: dasharray="500"
Changed this value in the inner most path. It was only 300
I added a linear animation
animation: draw 5s infinite linear;
The default is ease. I found the animation has better consistency with a linear animation.
NOTE
dashoffset=500 <- makes the animation start without the dash/stroke
I used the negative value for stroke-dashoffset that Persijn recommended. This worked great in Chrome and FF, but it didn't work properly in Safari.
I've found that if you open the SVG in Illustrator, you can reverse the direction of the path, by opening the Attributes panel (you might have to click the "show more" in the top right) and literally clicking the "reverse path" button.
stroke-dasharray can be a list of white space separated dashes and gaps, so you could do something like this:
var svgPath = document.getElementById('svgPath');
var pathLength = svgPath.getTotalLength();
var offset = 0;
function offsetPath() {
requestAnimationFrame(offsetPath);
offset += 0.1;
var dasharray = 0 + ' ' + offset + ' ' + (pathLength - offset);
svgPath.setAttribute('stroke-dasharray', dasharray);
}
requestAnimationFrame(offsetPath);
<svg xmlns="http://www.w3.org/2000/svg" width="670" height="236" viewBox="0 0 670 236">
<path id="svgPath" class="path" stroke="#4CADC1" stroke-width="4" stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="100 100 100" fill="none" d="M343.6 75.9v20.3l23.1 21.8-23.1 21.8v20.3l44.6-42.1zM326.4 139.8l-23.1-21.8 23.1-21.8v-20.3l-44.6 42.1 44.6 42.1z"
/>
</svg>
Changing SVG Line Animation Direction
Add KeyFrames and Classes for Both Directions:
.dash {
stroke-dasharray : 10 5;
animation : dash 4s linear infinite;
}
.dash_reverse {
stroke-dasharray : 10 5;
animation : dash_reverse 4s linear infinite;
}
#keyframes dash {
to {
stroke-dashoffset: 100;
}
}
#keyframes dash_reverse {
to {
stroke-dashoffset: -100;
}
}
Use JavaScript to Toggle Animation:
function animate_line_forward(id) {
$("#" + id).removeClass("dash_reverse");
$("#" + id).addClass("dash");
}
function animate_line_reverse(id) {
$("#" + id).removeClass("dash");
$("#" + id).addClass("dash_reverse");
}
Call functions as needed (pass the SVG line id into the above functions:
Calling animate_line_forward:
Calling animate_line_reverse: