I'm trying to animate the filling of a blood drop, with svg for the first time :
Animated drop
The animations runs fine on most navigators (with a static fallback on IE11 which doesn't support SVG animation), but Firefox displays some bad glitches on the mask. The bug is visible with the last version of Firefox on Windows, though there's no problems on the Mac version.
You can see a screenshot of the glitch here :
Firefox Glitch
The "wave" is a rectangle with a fill pattern and an horizontal repeating animation, within 2 nested , the first being the mask, the second one the vertical animation.
.vagueContainer-5 {
-moz-animation: fillup-5 10s 1 ease-out forwards;
-webkit-animation: fillup-5 10s 1 ease-out forwards;
animation: fillup-5 10s 1 ease-out forwards;
}
#keyframes fillup-5 {
0% { transform: translateY(470px); }
100% { transform: translateY(224px); }
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 540 528">
<defs>
<pattern id="water" width=".25" height="1.1">
<path fill="#E20020" d="M300 740V0c-75 0-75 14.4-150 14.4S75 0 0 0v740h300z"></path>
</pattern>
<path id="drop" fill="#FFF" d="M388.9 417.6c-33.3 33.3-79.8 49.1-119.7 49.1s-85.4-15.8-118.8-49.1-45.1-69.7-45.1-104.7 14.5-78 31.1-101.2c16.6-23.3 64-78 93.3-116.6s39.9-67.2 39.9-67.2S283 57 312.3 95.6s67.7 83.8 90.5 116.2C419.4 235.1 434 277.9 434 313s-11.8 71.3-45.1 104.6z"/>
<mask id="drop_mask">
<use xlink:href="#drop"/>
</mask>
</defs>
<g mask="url(#drop_mask)" class="vagueMask">
<g class="vagueContainer vagueContainer-5" transform="translate(0, 224)">
<path class="vague vague-5" fill="url(#water)" d="M0 0h1200v740H0z"></path>
</g>
</g>
</svg>
Any idea how I could resolve that, or should I set a static fallback ?
P.S. : It's my first time here, please tell me if I should include other elements ! Thanks in advance.
I had a more precise look at the <g> element and seem to have found a workaround : instead of <g> as a mask, I referenced the contents inside within <defs> and applied the mask on a <use> tag.
$(document).ready(function(){
var vagueContainer= SVG.get('vagueContainer');
var vague= SVG.get('vague');
vagueContainer.move(0, 470);
var fromTop=444-niveau*44;
vague.move(-600, 0);
vagueContainer.animate('10s','>','1s').move(0, fromTop);
vague.animate('1s','-','1s').move(0, 0).after(function(){
vague.move(-600, 0);
vague.animate('1.5s').move(0, 0).after(function(){
vague.move(-600, 0);
vague.animate('2s').move(0, 0).after(function(){
vague.move(-600, 0);
vague.animate('2.5s').move(0, 0).after(function(){
vague.move(-600, 0);
vague.animate('3s').move(0, 0).after(function(){
vague.move(-600, 0);
vague.animate('3.5s').move(0, 0).loop();
});
});
});
});
});
});
#vagueMask{
visibility: hidden;
-moz-animation: show 1s 1 forwards;
-webkit-animation: show 1s 1 forwards;
animation: show 1s 1 forwards;
}
#keyframes show{
100% {
visibility:visible;
}
}
<defs>
<g id="vagueContainer" x="0" y="0" transform ="matrix(1,0,0,1,0,<?php echo $transform; ?>)">
<rect id="vague" x="-600" y="0" fill="url(#water)" width="1200" height="740"/>
</g>
</defs>
<use mask="url(#drop_mask)" class="vagueMask" xlink:href="#vagueContainer" x="0" y="0" width="329" height="439"></use>
I also got this element to appear for positions reasons (the element is already placed at the right level if there is no .js but otherwise goes down for the filling up animation) : I had to use "visibility", because "opacity" caused the same bug.
Animation working fine on Firefox
Seems to work but I'm still not really sure why...
Related
Included here is an image of the svg file (could not upload svg file)
I would like to hover mouse over, and radiantly change background (to blue) only of the circle, from the inner circle to the edges, as an animation.
Even better if the animation was kind of wobbling effect from the middle of the circle and outwards. Nice if it was kind of "random" looking, the blue wobbling effect. Important it's animating from the middle of the circle, out towards the edge until the whole circle is blue.
When mouse/hover is removed then the animation is backwards.
Is that possible in svg/css land and can someone point towards the right direction?
This is a slightly hacky way to do it, using a blue circle with a black stroke that starts so thick it fills its interior. Hovering over the circle causes the stroke to shrink to nothing.
.logo-background {
fill: blue;
stroke: black;
stroke-width: 200;
transition: stroke-width 500ms;
}
.logo-background:hover {
stroke-width: 0;
}
.logo {
fill: none;
stroke: white;
stroke-width: 5;
pointer-events: none;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 200" height="100px">
<defs>
<clipPath id="circle-clip">
<circle cx="100" cy="100" r="100" />
</clipPath>
</defs>
<circle class="logo-background" cx="100" cy="100" r="100" clip-path="url(#circle-clip)" />
<rect class="logo" x="60" y="60" width="80" height="80" rx="5" ry="5"/>
</svg>
I am currently trying to stop the animation of a single child in a group g that has an animation.
So I tried to isolate the child and give him a class css to stop the animation, but he seems to ignore it and privilege his father's classes.
Is it possible to force a child not to apply a specific class of his father?
.pulsBlockly {
animation: pulsBlockly 1s ease-out 0s infinite alternate;
opacity: 1.0;
}
#keyframes pulsBlockly {
0% { opacity: 0.4; }
100% { opacity: 0.1 }
}
.nopulsBlockly {
animation: none !important;
-webkit-animation: none !important;
-moz-animation: none !important;
-o-animation: none !important;
-ms-animation: none !important;
}
<svg>
<g class="pulsBlockly">
<g class="nopulsBlockly">
<rect rx="4" ry="4" x="-5" y="0" height="16" width="27.35" fill="gold"></rect>
<text class="blocklyText" y="12.5"> ∅ </text>
</g>
</g>
<svg>
As expected, the first group g is animated as I wish, but the second group g flashes when I do not wish.
The opacity property is different from most other properties. It does not inherit down to child elements. Instead, it causes the creation of an isolated layer which is drawn at the specified opacity. Anything in that layer - for example all of the group's children - will be affected by that opacity. There isn't anything you can do to get around that.
If you have a group of animated things, and you want some of them to be animated, and some not. Then you will need to apply the animation to each child individually.
For example, you could move the animation to each child using the CSS > (direct child) combinator.
/* Applies to any direct child of `pulsBlockly` */
.pulsBlockly > * {
animation: pulsBlockly 1s ease-out 0s infinite alternate;
opacity: 1.0;
}
If you do this, the nopulsBlockly class on a child will cancel it's animation.
.pulsBlockly > * {
animation: pulsBlockly 1s ease-out 0s infinite alternate;
opacity: 1.0;
}
#keyframes pulsBlockly {
0% { opacity: 0.4; }
100% { opacity: 0.1 }
}
.nopulsBlockly {
animation: none !important;
-webkit-animation: none !important;
-moz-animation: none !important;
-o-animation: none !important;
-ms-animation: none !important;
}
<svg>
<g class="pulsBlockly">
<g><!-- gets animated -->
<rect rx="4" ry="4" x="-5" y="0" height="16" width="27.35" fill="gold"></rect>
<text class="blocklyText" y="12.5"> ∅ </text>
</g>
<g class="nopulsBlockly" transform="translate(40,0)"> <!-- nopulsBlockly blocks the animation this time -->
<rect rx="4" ry="4" x="-5" y="0" height="16" width="27.35" fill="gold"></rect>
<text class="blocklyText" y="12.5"> ∅ </text>
</g>
</g>
<svg>
Imagine a progress-bar like this one, which creates a sensation of motion towards the left:
Note: the thin bright-green line on top of the animation is a compression artifact.
I am looking for a way to implement something similar, but in an arbitrary SVG path, such as this one:
I am trying to understand what is really going on there, e.g.:
Is it a gradient with many stops, and the stops keep moving?
Are these many adjacent, skewed rectangles moving in unison?
Is it one long sequence of skewed adjacent rectangles, with a "sliding window" moving along it?
How can such animations be conceptualized? And what would be the best practice to implement it using SVG primitives?
I am using a path twice:#a and #b. Both #a and #b have stroke-dasharray: 1 but #b id offset stroke-dashoffset: 1;
I'm animating the stroke-dashoffset for both #a and #b.
use {
stroke-dasharray: 1;
}
#a {
stroke: green;
animation: dasha 5s linear infinite;
}
#b {
stroke: DarkSeaGreen;
stroke-dashoffset: 1;
animation: dashb 5s linear infinite;
}
#keyframes dasha {
to {
stroke-dashoffset: -54.66;
}
}
#keyframes dashb {
to {
stroke-dashoffset: -53.66;
}
}
<svg viewBox='0 0 24 24' width="200"><title>gesture</title>
<defs><path id="thePath" fill="none" d='M4.59 6.89c.7-.71 1.4-1.35 1.71-1.22.5.2 0 1.03-.3 1.52-.25.42-2.86 3.89-2.86 6.31 0 1.28.48 2.34 1.34 2.98.75.56 1.74.73 2.64.46 1.07-.31 1.95-1.4 3.06-2.77 1.21-1.49 2.83-3.44 4.08-3.44 1.63 0 1.65 1.01 1.76 1.79-3.78.64-5.38 3.67-5.38 5.37 0 1.7 1.44 3.09 3.21 3.09 1.63 0 4.29-1.33 4.69-6.1h2.46'></path>
</defs>
<use id="a" xlink:href="#thePath" />
<use id="b" xlink:href="#thePath" />
</svg>
UPDATE
If you use css variables you can use only one animation:
use {
stroke-dasharray: 1;
}
#a {
--offset:0;
stroke: green;
stroke-dashoffset: 53.66;
animation: dash 5s linear infinite;
}
#b {
--offset:1;
stroke: DarkSeaGreen;
stroke-dashoffset: 54.66;
animation: dash 5s linear infinite;
}
#keyframes dash {
to {
stroke-dashoffset: var(--offset)
}
}
<svg viewBox='0 0 24 24' width="200"><title>gesture</title>
<defs><path id="thePath" fill="none" d='M4.59 6.89c.7-.71 1.4-1.35 1.71-1.22.5.2 0 1.03-.3 1.52-.25.42-2.86 3.89-2.86 6.31 0 1.28.48 2.34 1.34 2.98.75.56 1.74.73 2.64.46 1.07-.31 1.95-1.4 3.06-2.77 1.21-1.49 2.83-3.44 4.08-3.44 1.63 0 1.65 1.01 1.76 1.79-3.78.64-5.38 3.67-5.38 5.37 0 1.7 1.44 3.09 3.21 3.09 1.63 0 4.29-1.33 4.69-6.1h2.46'></path>
</defs>
<use id="a" xlink:href="#thePath" />
<use id="b" xlink:href="#thePath" />
</svg>
Well one way of doing it is with an animated pattern. Something like this:
<svg width="800px" height="600px">
<defs>
<pattern id="skewrect" x="0%" y="0%" width="20%" height="100%" patternTransform="skewX(30)" viewBox="-7 160 60 60">
<animate attributeName="x" from="20%" to="0%" dur="2s" repeatCount="indefinite"/>
<polygon points="0,0 0,600 20,600 20,0" fill="green"/>
<polygon points="20,40 20,600 40,600 40,20" fill="grey"/>
</pattern>
</defs>
<path d="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80" stroke="url(#skewrect)" fill="none" stroke-width="10"/>
</svg>
You can also do it with a gradient, or a filter.
I have a svg with some circles that should get bigger on hover, here is a snippet
!This will not work in Firefox
var svgRoot = $('.svg-root')[0];
$('.bubble').mouseover(function (e) {
svgRoot.append(e.currentTarget);
});
circle{
transition: all 200ms;
}
circle:hover{
stroke: black;
fill: white;
transform: scale(3);
}
.svg-root svg{
overflow: visible;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg class="svg-root">
<svg class="bubble" x="50" y="50">
<circle r="10"></circle>
</svg>
<svg class="bubble" x="70" y="70">
<circle r="10"></circle>
</svg>
<svg class="bubble" x="90" y="50">
<circle r="10"></circle>
</svg>
</svg>
To avoid the other circles overlapping the one the mouse is currently hovering over, I used the append trick. That solves the z-index Problem, but it causes a different one. It seems that after appending the node, Firefox does not recognize the hover state of the cursor. The circles will not scale on hover in Firefox, but they will in Chrome.
I need them to scale on hover and to have the highest z-index while doing so.
Any solutions?
I'm trying to animate a circle when an SVG is loaded. It should:
Initially load at a set, small size (radius of 1)
Begin after the set amount of seconds
Increase size to the set size (radius of 17)
Stay at this radius forever
Here is what I'm doing:
<svg width="36px" height="36px">
<circle r="1" cy="18" cx="18">
<animate attributeName="r" from="1" to="17" dur="1s" begin="1s"></animate>
</circle>
</svg>
But if you look at the result (and another option, included in the link) you can see it isn't working in either of them:
http://codepen.io/sheepysheep60/pen/Hjfdo
Can anyone shed any light on how to play the animation up until the end, then pause the animation, or is there a setting I'm missing?
Use fill="freeze":
<svg width="36px" height="36px">
<circle r="1" cy="18" cx="18">
<animate attributeName="r" from="1" to="17" dur="1s" begin="1s" fill="freeze"></animate>
</circle>
</svg>
See here for more information.
James' answer is totally correct, and answered my question – however 6 years later it isn't how I'd accomplish this at all. CSS animations seem to gradually be the preferred route compared to
<animation />
tags. The same example would look something like this:
https://codepen.io/EightArmsHQ/pen/bGbvaxx
#keyframes grow{
to{
r: 16;
}
}
circle{
animation: grow 3s forwards;
svg:nth-child(2) &{
animation-delay: 1s;
}
svg:nth-child(3) &{
animation-delay: 2s;
}
}