Change CSS to allow for control over DIV position using Javascript - javascript

I have adapted code from this page: Filling water animation to suit my needs as you can see below.
CSS
#banner {
width: 150px;
height: 150px;
background:red;
overflow: hidden;
-webkit-backface-visibility: hidden;
}
.rotate {
-ms-transform: rotate(180deg);
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
#banner .fill {
-webkit-transform: translate(0, -75px);
}
#banner #waveShape {
-webkit-animation-name: waveAction;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
-webkit-animation-duration: 1s;
width:300px;
height: 155px;
opacity:0.9;
fill: #fff;
#-webkit-keyframes waveAction {
0% {
-webkit-transform: translate(150px,0);
}
100% {
-webkit-transform: translate(0, 0);
}
}
HTML
<div id="banner">
<div class="fill">
<svg class="rotate" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="300px" height="155px" viewBox="0 0 300 155" enable-background="new 0 0 300 155" xml:space="preserve">
<path fill="#04ACFF" id="waveShape" d="M300,300V2.5c0,0-0.6-0.1-1.1-0.1c0,0-25.5-2.3-40.5-2.4c-15,0-40.6,2.4-40.6,2.4
c-12.3,1.1-30.3,1.8-31.9,1.9c-2-0.1-19.7-0.8-32-1.9c0,0-25.8-2.3-40.8-2.4c-15,0-40.8,2.4-40.8,2.4c-12.3,1.1-30.4,1.8-32,1.9
c-2-0.1-20-0.8-32.2-1.9c0,0-3.1-0.3-8.1-0.7V300H300z"/>
</svg>
</div>
</div>
Also...
Please see a screenshot of the output here.
However, I'd like to go one step further and control the level the 'water' is filled via a javascript function.
Usually, I would just control the X and Y position of the DIV that contains the waving SVG but that doesn't appear to work here.
I'd like to use this as a loading infographic but at the moment I can only control the 'water' level using...
}
#banner .fill {
-webkit-transform: translate(0, -75px);
}
I can use values of 0px (0%) to -155px (100%) but ideally I'd like to be able to set a percentage, perhaps by passing a variable in??
NOTE: I've rotated the original SVG because I was struggling to create a new one that worked correctly.
Any help would be much appreciated, I know I'm going to kick myself when I see the solution!! Thankyou.

Get rid of the .rotate and #banner .fill transforms
If you give the svg an id, you can adjust the top margin of the svg using a %
eg
el.style.marginTop = "75%";
Working example: (tested in chrome)
<style type="text/css">
#banner {
width: 150px;
height: 150px;
background:red;
overflow: hidden;
-webkit-backface-visibility: hidden;
}
#water {
margin-top: 99%;
}
#banner #waveShape {
-webkit-animation-name: waveAction;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
-webkit-animation-duration: 1s;
animation-name: waveAction;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-duration: 1s;
width:300px;
height: 155px;
opacity:0.9;
fill: #fff;
}
#keyframes waveAction {
0% {
-webkit-transform: translate(-150px,0);
transform: translate(-150px,0);
}
100% {
-webkit-transform: translate(150, 0);
transform: translate(150, 0);
}
}
</style>
<script>
function fill(percent) {
var el=document.getElementById("water");
if (el == null) {
alert("missing element");
return;
}
el.style.marginTop = (100-percent)+"%";
}
</script>
<div id="banner">
<div class="fill">
<svg id="water" class="rotate" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="300px" height="155px" viewBox="0 0 300 155" enable-background="new 0 0 300 155" xml:space="preserve">
<path fill="#04ACFF" id="waveShape" d="M300,300V2.5c0,0-0.6-0.1-1.1-0.1c0,0-25.5-2.3-40.5-2.4c-15,0-40.6,2.4-40.6,2.4
c-12.3,1.1-30.3,1.8-31.9,1.9c-2-0.1-19.7-0.8-32-1.9c0,0-25.8-2.3-40.8-2.4c-15,0-40.8,2.4-40.8,2.4c-12.3,1.1-30.4,1.8-32,1.9
c-2-0.1-20-0.8-32.2-1.9c0,0-3.1-0.3-8.1-0.7V300H300z"/>
</svg>
</div>
</div>
<script>
fill(25); //set fill to 25%
</script>
If that doesn't work you could try simply inserting an empty div before the svg and adjusting the height of that.

Related

offset-path leaving a fading trail

what do I need to include to make a white trail following it? I tried adding 10 spans and giving them the same path and delaying each one but it looked so off.
.container{
width: 100vw;
height: 100vh;
background: gray;
}
.orb{
background: #00fff9;
offset-path: path(
"M257.004 129.794C321.128 129.794 380.697 139.056 425.611 154.622C479.727 173.378 513 201.806 513 227.548C513 254.373 477.738 284.575 419.624 303.958C375.689 318.612 317.874 326.262 257.004 326.262C194.596 326.262 135.5 319.081 91.0694 303.797C34.8572 284.455 1 253.863 1 227.548C1 202.015 32.7685 173.806 86.1237 155.079C131.206 139.257 192.246 129.794 256.996 129.794H257.004Z"
);
box-shadow: 0 0 10px #00fff9,
0 0 20px #00fff9,
0 0 30px #00fff9,
0 0 40px #00fff9,
0 0 50px #00fff9,
0 0 60px #00fff9,
0 0 70px #00fff9,
0 0 80px #00fff9,
0 0 90px #00fff9;
border-radius: 50%;
width: 20px;
height: 20px;
animation: move 10s linear infinite;
}
#keyframes move {
100% {
offset-distance: 100%;
}
}
<div class="container">
<div class="orb">
</div>
</div>
Here's an implementation that uses SVG <animateMotion> instead of CSS offset-path. (The path data might look a bit different, but they are basically the same.)
The trail is done with a stroke-dashoffset animation. The path gets the pathLength="100", and is then drawn ten times, each with a stroke-dasharray="2 98". That way, only a dash with a length of 2 of 100 along the path is drawn.
Then, each of the ten copies of the path gets a fading opacity, and its stroke-dashoffset is animated such that they are positioned one behind the other and moving behind the glowing orb. That part gets admitedly a bit verbose, as you need to write an individual animation rule for each of the copies. The combination of them all is then blured to smooth it.
For the orb, a custom SVG filter is used, since the drop-shadow property can't be used directly for SVG grafics.
svg {
background-color: grey;
overflow: visible;
width: 100vw;
height: 100vh;
}
.orb {
fill: #00fff9;
}
.orb :first-child {
filter: url(#glow);
}
.trail {
filter: blur(4px);
}
.trail use {
fill: none;
stroke: white;
stroke-width: 10;
stroke-dasharray: 2 98;
}
.trail :nth-child(1) {
animation: trail1 10s linear infinite;
stroke-opacity: 0.5;
}
#keyframes trail1 {
from {stroke-dashoffset: 2}
to {stroke-dashoffset: -98}
}
.trail :nth-child(2) {
animation: trail2 10s linear infinite;
stroke-opacity: 0.45;
}
#keyframes trail2 {
from {stroke-dashoffset: 4}
to {stroke-dashoffset: -96}
}
.trail :nth-child(3) {
animation: trail3 10s linear infinite;
stroke-opacity: 0.4;
}
#keyframes trail3 {
from {stroke-dashoffset: 6}
to {stroke-dashoffset: -94}
}
.trail :nth-child(4) {
animation: trail4 10s linear infinite;
stroke-opacity: 0.35;
}
#keyframes trail4 {
from {stroke-dashoffset: 8}
to {stroke-dashoffset: -92}
}
.trail :nth-child(5) {
animation: trail5 10s linear infinite;
stroke-opacity: 0.3;
}
#keyframes trail5 {
from {stroke-dashoffset: 10}
to {stroke-dashoffset: -90}
}
.trail :nth-child(6) {
animation: trail6 10s linear infinite;
stroke-opacity: 0.25;
}
#keyframes trail6 {
from {stroke-dashoffset: 12}
to {stroke-dashoffset: -88}
}
.trail :nth-child(7) {
animation: trail7 10s linear infinite;
stroke-opacity: 0.2;
}
#keyframes trail7 {
from {stroke-dashoffset: 14}
to {stroke-dashoffset: -86}
}
.trail :nth-child(8) {
animation: trail8 10s linear infinite;
stroke-opacity: 0.15;
}
#keyframes trail8 {
from {stroke-dashoffset: 16}
to {stroke-dashoffset: -84}
}
.trail :nth-child(9) {
animation: trail9 10s linear infinite;
stroke-opacity: 0.1;
}
#keyframes trail9 {
from {stroke-dashoffset: 18}
to {stroke-dashoffset: -82}
}
.trail :nth-child(10) {
animation: trail10 10s linear infinite;
stroke-opacity: 0.05;
}
#keyframes trail10 {
from {stroke-dashoffset: 20}
to {stroke-dashoffset: -80}
}
<svg viewBox="-10 110 550 240">
<defs>
<filter id="glow" x="-1" y="-1" width="3" height="3">
<feGaussianBlur stdDeviation="12"/><!-- defines how blured the glow is -->
<feComponentTransfer>
<feFuncA type="linear" slope="3"/><!-- defines how bright the glow is -->
</feComponentTransfer>
</filter>
<path id="ellipse" pathLength="100" d="M257 130A256 98 0 1 1 257 326 256 98 0 1 1 257 130Z" />
</defs>
<g class="trail">
<use href="#ellipse"/>
<use href="#ellipse"/>
<use href="#ellipse"/>
<use href="#ellipse"/>
<use href="#ellipse"/>
<use href="#ellipse"/>
<use href="#ellipse"/>
<use href="#ellipse"/>
<use href="#ellipse"/>
<use href="#ellipse"/>
</g>
<g class="orb">
<circle r="12"/><!-- defines how wide the glow is -->
<circle r="10"/>
<animateMotion dur="10s" repeatCount="indefinite">
<mpath href="#ellipse"/>
</animateMotion>
</g>
</svg>
You could write the trail animation also with <animate>. It would look like this:
<use href="#ellipse">
<animate attributeName="stroke-dashoffset"
dur="10s" repeatCount="indefinite"
from="2" to="-98" />
</use>
Which variant you use is a matter of taste.
Edit: Generalization
The above code depends on a linear movement of the orb along the path. How would you solve this with different easings? I started to explore that and found the only realistic approach is to draw the trail frame-by-frame from Javascript. An example can be found in this Codepen.

How to stop SVG animation on click?

I have an svg animation, I want to be able to stop/pause the animation on click but I can't figure out how and I need help, I tried to toggle but I think I have to toggle each line which I don't know how to.
<div class="loader">
<svg id="wave" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 38.05">
<path id="Line_1" class="t" data-name="Line 1" d="M0.91,15L0.78,15A1,1,0,0,0,0,16v6a1,1,0,1,0,2,0s0,0,0,0V16a1,1,0,0,0-1-1H0.91Z"/>
<path id="Line_1" class="t" data-name="Line 2" d="M6.91,9L6.78,9A1,1,0,0,0,6,10V28a1,1,0,1,0,2,0s0,0,0,0V10A1,1,0,0,0,7,9H6.91Z"/>
<path id="Line_1" class="t" data-name="Line 3" d="M12.91,0L12.78,0A1,1,0,0,0,12,1V37a1,1,0,1,0,2,0s0,0,0,0V1a1,1,0,0,0-1-1H12.91Z"/>
<path id="Line_1" class="t" data-name="Line 4" d="M18.91,10l-0.12,0A1,1,0,0,0,18,11V27a1,1,0,1,0,2,0s0,0,0,0V11a1,1,0,0,0-1-1H18.91Z"/>
<path id="Line_1" class="t" data-name="Line 5" d="M24.91,15l-0.12,0A1,1,0,0,0,24,16v6a1,1,0,0,0,2,0s0,0,0,0V16a1,1,0,0,0-1-1H24.91Z"/>
<path id="Line_1" class="t" data-name="Line 6" d="M30.91,10l-0.12,0A1,1,0,0,0,30,11V27a1,1,0,1,0,2,0s0,0,0,0V11a1,1,0,0,0-1-1H30.91Z"/>
<path id="Line_1" class="t" data-name="Line 7" d="M36.91,0L36.78,0A1,1,0,0,0,36,1V37a1,1,0,1,0,2,0s0,0,0,0V1a1,1,0,0,0-1-1H36.91Z"/>
<path id="Line_1" class="t" data-name="Line 8" d="M42.91,9L42.78,9A1,1,0,0,0,42,10V28a1,1,0,1,0,2,0s0,0,0,0V10a1,1,0,0,0-1-1H42.91Z"/>
<path id="Line_1" class="t" data-name="Line 9" d="M48.91,15l-0.12,0A1,1,0,0,0,48,16v6a1,1,0,1,0,2,0s0,0,0,0V16a1,1,0,0,0-1-1H48.91Z"/>
</svg>
</div>
css
.loader {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
#wave {
height: 70px;
width: 70px;
fill: black;
}
#wave.stop {
animation-play-state: paused;
}
#Line_1 {
animation: pulse 1s infinite;
animation-delay: 0.15s;
}
#Line_2 {
animation: pulse 1s infinite;
animation-delay: 0.3s;
}
#Line_3 {
animation: pulse 1s infinite;
animation-delay: 0.45s;
}
#Line_4 {
animation: pulse 1s infinite;
animation-delay: 0.6s;
}
#Line_5 {
animation: pulse 1s infinite;
animation-delay: 0.75s;
}
#Line_6 {
animation: pulse 1s infinite;
animation-delay: 0.9s;
}
#Line_7 {
animation: pulse 1s infinite;
animation-delay: 1.05s;
}
#Line_8 {
animation: pulse 1s infinite;
animation-delay: 1.2s;
}
#Line_9 {
animation: pulse 1s infinite;
animation-delay: 1.35s;
}
js
var vawe = document.getElementById("vawe")
vawe.addEventListener('click',function() {
vawe.classList.toggle('stop');
})
when I click on the svg I want to stop pause the animation, so that the music stop, and then click again the animation starts again.
#wave.stop {
animation-play-state: paused;
}
Doesn't apply the animation-play-state to the actually animated (line) elements.
The css rule should rather look something like this:
#wave.stop .t {
animation-play-state: paused;
}
I also recommend to use class selectors to avoid unnecessarily high specificity
(introduced by id selectors in your css rules).
var wave = document.getElementById("wave")
wave.addEventListener('click', function(e) {
e.currentTarget.classList.toggle('stop');
})
.loader {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
#wave {
height: 10em;
fill: black;
}
.stop {
border: 1px solid red;
}
.stop .t {
animation-play-state: paused;
}
.t {
transform-origin: center;
animation: pulse 1s infinite forwards;
transform: scale(1, 0.5)
}
.Line_1 {
animation-delay: 0.15s;
}
.Line_2 {
animation-delay: 0.3s;
}
.Line_3 {
animation-delay: 0.45s;
}
.Line_4 {
animation-delay: 0.6s;
}
.Line_5 {
animation-delay: 0.75s;
}
.Line_6 {
animation-delay: 0.9s;
}
.Line_7 {
animation-delay: 1.05s;
}
.Line_8 {
animation-delay: 1.2s;
}
.Line_9 {
animation-delay: 1.35s;
}
#keyframes pulse {
0% {
transform: scale(1, 0.5)
}
50% {
transform: scale(1, 1)
}
100% {
transform: scale(1, 0.5)
}
}
<div class="loader">
<svg class="wave" id="wave" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 38.05">
<path id="Line_1" class="t Line_1" data-name="Line 1" d="M0.91,15L0.78,15A1,1,0,0,0,0,16v6a1,1,0,1,0,2,0s0,0,0,0V16a1,1,0,0,0-1-1H0.91Z"/>
<path id="Line_2" class="t Line_2" data-name="Line 2" d="M6.91,9L6.78,9A1,1,0,0,0,6,10V28a1,1,0,1,0,2,0s0,0,0,0V10A1,1,0,0,0,7,9H6.91Z"/>
<path id="Line_3" class="t Line_3" data-name="Line 3" d="M12.91,0L12.78,0A1,1,0,0,0,12,1V37a1,1,0,1,0,2,0s0,0,0,0V1a1,1,0,0,0-1-1H12.91Z"/>
<path id="Line_4" class="t Line_4" data-name="Line 4" d="M18.91,10l-0.12,0A1,1,0,0,0,18,11V27a1,1,0,1,0,2,0s0,0,0,0V11a1,1,0,0,0-1-1H18.91Z"/>
<path id="Line_5" class="t Line_5" data-name="Line 5" d="M24.91,15l-0.12,0A1,1,0,0,0,24,16v6a1,1,0,0,0,2,0s0,0,0,0V16a1,1,0,0,0-1-1H24.91Z"/>
<path id="Line_6" class="t Line_6" data-name="Line 6" d="M30.91,10l-0.12,0A1,1,0,0,0,30,11V27a1,1,0,1,0,2,0s0,0,0,0V11a1,1,0,0,0-1-1H30.91Z"/>
<path id="Line_7" class="t Line_7" data-name="Line 7" d="M36.91,0L36.78,0A1,1,0,0,0,36,1V37a1,1,0,1,0,2,0s0,0,0,0V1a1,1,0,0,0-1-1H36.91Z"/>
<path id="Line_8" class="t Line_8" data-name="Line 8" d="M42.91,9L42.78,9A1,1,0,0,0,42,10V28a1,1,0,1,0,2,0s0,0,0,0V10a1,1,0,0,0-1-1H42.91Z"/>
<path id="Line_9" class="t Line_9" data-name="Line 9" d="M48.91,15l-0.12,0A1,1,0,0,0,48,16v6a1,1,0,1,0,2,0s0,0,0,0V16a1,1,0,0,0-1-1H48.91Z"/>
</svg>
</div>
Since the delay is required on resume, try this JavaScript alternative. The animation property of the element is individually set or unset depending upon the state.
let el = document.getElementById("vawe")
el.addEventListener('click', (e) => {
let value = 'unset';
if ( e.currentTarget.classList.contains('stop') ) {
e.currentTarget.classList.remove('stop');
value = 'pulse 1s infinite';
} else {
e.currentTarget.classList.add('stop');
}
e.currentTarget.childNodes.forEach(child => {
child.style.setProperty('animation-name', value);
});
});

Why does Chrome run transform animation on the main thread in some cases, and not in others?

What is the criteria?
In the following example, I am animating CSS transform, and when you click anywhere (while in Google Chrome) the animation is blocked by a 2-second-long while loop.
Why is the CSS transform animation blocked?
EDIT: Lately Chrome no longer blocks the transform while the main thread is blocked, indicating that they have moved the sort of animation in the following example off main thread.
Animating transform can happen on a separate thread, but it isn't clear exactly when. Sometimes it works.
In this first example, separate-thread transform animation does not happen (click on it to block the main thread and therefore pause the animation):
window.addEventListener('click', kill)
function kill() {
var start = +new Date;
while (+new Date - start < 2000){}
}
html, body, div {
width: 100%; height: 100%;
margin: 0; padding: 0;
/* background: #364659; */
/* background: #293442; */
background: #1E2630;
overflow: hidden;
}
#keyframes ShimmerEffect {
0% { transform: translate3d(-15%, -15%, 0) }
100% { transform: translate3d(-60%, -60%, 0) }
}
.shimmerSurface {
/* overflow: hidden; */
/* perspective: 100000px */
}
.shimmerSurfaceContent {
transform-style: preserve-3d;
background: linear-gradient(
-45deg,
rgba(0,0,0,0) 40%,
rgba(244,196,48,0.6) 50%,
rgba(0,0,0,0) 60%
);
background-repeat: repeat;
background-size: 100% 100%;
width: 400%; height: 400%;
animation: ShimmerEffect 1.8s cubic-bezier(0.75, 0.000, 0.25, 1.000) infinite;
}
<div class="shimmerSurface">
<div class="shimmerSurfaceContent"></div>
</div>
(codepen link)
EDIT: seems the example's animation is not blocked in Safari (though it chops the gradient), but is blocked only in Chrome and Firefox. How can we unblock the animation in Chrome and Firefox?
In next example, when you click anywhere to block the main thread (in Chrome), you will see that transform is animated on a separate thread because it continues to animate, while the stroke-offset animation is frozen because apparently stroke-offset animation is happening on the main thread:
window.addEventListener('click', kill)
function kill() {
var start = +new Date;
while (+new Date - start < 2000){}
}
.loader {
--path: #2F3545;
--dot: #5628EE;
--duration: 3s;
width: 44px;
height: 44px;
position: relative;
}
.loader:before {
content: "";
width: 6px;
height: 6px;
border-radius: 50%;
position: absolute;
display: block;
background: var(--dot);
top: 37px;
left: 19px;
transform: translate(-18px, -18px);
-webkit-animation: dotRect var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
animation: dotRect var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
}
.loader svg {
display: block;
width: 100%;
height: 100%;
}
.loader svg rect,
.loader svg polygon,
.loader svg circle {
fill: none;
stroke: var(--path);
stroke-width: 10px;
stroke-linejoin: round;
stroke-linecap: round;
}
.loader svg polygon {
stroke-dasharray: 145 76 145 76;
stroke-dashoffset: 0;
-webkit-animation: pathTriangle var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
animation: pathTriangle var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
}
.loader svg rect {
stroke-dasharray: 192 64 192 64;
stroke-dashoffset: 0;
-webkit-animation: pathRect 3s cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
animation: pathRect 3s cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
}
.loader svg circle {
stroke-dasharray: 150 50 150 50;
stroke-dashoffset: 75;
-webkit-animation: pathCircle var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
animation: pathCircle var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
}
.loader.triangle {
width: 48px;
}
.loader.triangle:before {
left: 21px;
transform: translate(-10px, -18px);
-webkit-animation: dotTriangle var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
animation: dotTriangle var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
}
#-webkit-keyframes pathTriangle {
33% {
stroke-dashoffset: 74;
}
66% {
stroke-dashoffset: 147;
}
100% {
stroke-dashoffset: 221;
}
}
#keyframes pathTriangle {
33% {
stroke-dashoffset: 74;
}
66% {
stroke-dashoffset: 147;
}
100% {
stroke-dashoffset: 221;
}
}
#-webkit-keyframes dotTriangle {
33% {
transform: translate(0, 0);
}
66% {
transform: translate(10px, -18px);
}
100% {
transform: translate(-10px, -18px);
}
}
#keyframes dotTriangle {
33% {
transform: translate(0, 0);
}
66% {
transform: translate(10px, -18px);
}
100% {
transform: translate(-10px, -18px);
}
}
#-webkit-keyframes pathRect {
25% {
stroke-dashoffset: 64;
}
50% {
stroke-dashoffset: 128;
}
75% {
stroke-dashoffset: 192;
}
100% {
stroke-dashoffset: 256;
}
}
#keyframes pathRect {
25% {
stroke-dashoffset: 64;
}
50% {
stroke-dashoffset: 128;
}
75% {
stroke-dashoffset: 192;
}
100% {
stroke-dashoffset: 256;
}
}
#-webkit-keyframes dotRect {
25% {
transform: translate(0, 0);
}
50% {
transform: translate(18px, -18px);
}
75% {
transform: translate(0, -36px);
}
100% {
transform: translate(-18px, -18px);
}
}
#keyframes dotRect {
25% {
transform: translate(0, 0);
}
50% {
transform: translate(18px, -18px);
}
75% {
transform: translate(0, -36px);
}
100% {
transform: translate(-18px, -18px);
}
}
#-webkit-keyframes pathCircle {
25% {
stroke-dashoffset: 125;
}
50% {
stroke-dashoffset: 175;
}
75% {
stroke-dashoffset: 225;
}
100% {
stroke-dashoffset: 275;
}
}
#keyframes pathCircle {
25% {
stroke-dashoffset: 125;
}
50% {
stroke-dashoffset: 175;
}
75% {
stroke-dashoffset: 225;
}
100% {
stroke-dashoffset: 275;
}
}
.loader {
display: inline-block;
margin: 0 16px;
}
html {
-webkit-font-smoothing: antialiased;
}
* {
box-sizing: border-box;
}
*:before, *:after {
box-sizing: border-box;
}
body {
min-height: 100vh;
background: #F5F9FF;
display: flex;
justify-content: center;
align-items: center;
}
body .dribbble {
position: fixed;
display: block;
right: 20px;
bottom: 20px;
}
body .dribbble img {
display: block;
height: 28px;
}
<div class="loader">
<svg viewBox="0 0 80 80">
<circle id="test" cx="40" cy="40" r="32"></circle>
</svg>
</div>
<div class="loader triangle">
<svg viewBox="0 0 86 80">
<polygon points="43 8 79 72 7 72"></polygon>
</svg>
</div>
<div class="loader">
<svg viewBox="0 0 80 80">
<rect x="8" y="8" width="64" height="64"></rect>
</svg>
</div>
Why does the first example's transform animation run on the main thread, while the second example's transform animation runs on a separate thread?
What are the criteria under which a transform is guaranteed to run in a separate thread (at least, in Chrome)?
Browser Threads
Each browser has at least three threads; precisely what is run on each depends on the browser. Modern browsers all have more than three now, but they still have three categories of threads that will always be separate. Why?
One will always be entirely separate and only accessible by the browser to handle things like scrolling, opening a new tab etc... At least one will always be for things like calculating and parsing and so will be run on the CPU. And at least one thread will run on the GPU as it is required for something to be shown on your screen.
Layers
For the GPU to know what it's showing on the screen it needs the layout rasterised in a bitmap format. But as things move around the screen it's best if we send the GPU a few bitmaps that can move around. We call these layers.
as #irdkwmnsb has pointed out we can use the layers tab in the developer tools to see exactly which elements have been split into separate bitmaps.
Explicitly Creating A Layer
For any HTML or SVG element that we know will transform, we can add the following CSS rule to ensure the element is separated into a separate bitmap layer and the transition shouldn't be blocked by other activity on the main thread:
will-change: transform
so adding the CSS rule
.shimmerSurfaceContent {
will-change: transform;
}
should stop the transition from being blocked in your first example.
Why Only In Some Browsers?
The reason some browsers may not automatically split this element into a separate layer is that there is a performance issue with creating too many bitmap layers so they are careful not to create too many. Also, some things don't look good when created as separate bitmaps and moved around so the browser may avoid it.
But for this example specifically, we can see from the two bitmap layers in this image that the top one has a semi-transparent edge. Things like this have previously caused aliasing problems for the GPU as it calculates the various shaded of yellow.
This may have been a reason for chrome to previously avoid separating it into a new bitmap layer.

How to show a tooltip after clicking an SVG?

I have an SVG circle, it has a small svg circle inside it and a polygon inside the small circle, when i click on the polygon it should rotate and it's working fine, but after rotation a tool-tip should appear above the polygon and i don't know how to show it, i put it in a div above my svg, here is my code:
document.querySelector('polygon').addEventListener('click', function() {
this.classList.toggle('rotated');
});
.rotated {
transform: rotate(-90deg);
}
polygon {
transition: all 1s;
}
<div class="marker marker-index-0" style="display: none;">
<h3>I should be a tooltip</h3>
</div>
<svg>
<circle cx="40" cy="122.5" r="26" fill="red"></circle>
<g class="markerG" transform="matrix(1,0,0,1,40,122.5)"><circle cx="0" cy="0" r="14" fill="#000000" style="cursor: pointer;"></circle><polygon points="1 -1 1 -7 -1 -7 -1 -1 -7 -1 -7 1 -1 1 -1 7 1 7 1 1 7 1 7 -1" fill="#ffffff"></polygon></g>
</svg>
Looks to me like you never specified to show the tool-tip ;)
document.querySelector('svg').addEventListener('click', function() {
document.querySelector('polygon').classList.toggle('rotated');
document.getElementById('marker').classList.toggle('show');
});
.rotated {
transform: rotate(-90deg);
}
polygon {
transition: all 1s;
}
.show {
display: block !important;
}
<div class="marker marker-index-0" id="marker" style="display: none;">
<h3>I should be a tooltip</h3>
</div>
<svg>
<circle cx="40" cy="122.5" r="26" fill="red"></circle>
<g class="markerG" transform="matrix(1,0,0,1,40,122.5)"><circle cx="0" cy="0" r="14" fill="#000000" style="cursor: pointer;"></circle><polygon points="1 -1 1 -7 -1 -7 -1 -1 -7 -1 -7 1 -1 1 -1 7 1 7 1 1 7 1 7 -1" fill="#ffffff"></polygon></g>
</svg>
Hope this helps!
A transition alone won't do it, because you can't do anything after it's done.
Instead, it would be a good time for you to learn CSS Animations.
Note that I applied the classes to a container involving both the polygon and the tooltip, in order to avoid synchronization errors.
document.querySelector('polygon').addEventListener('click', function() {
if(!document.getElementById('animationContainer').classList.contains("animated")) {
document.getElementById('animationContainer').classList.add("animated");
document.getElementById('animationContainer').classList.add("rotated");
} else {
document.getElementById('animationContainer').classList.toggle('rotated');
document.getElementById('animationContainer').classList.toggle('faded');
}
});
#keyframes polygonAnimation {
0% { transform: rotate(0deg); }
50% { transform: rotate(-90deg); }
100% { transform: rotate(-90deg); }
}
#keyframes polygonReverseAnimation {
0% { transform: rotate(-90deg); }
50% { transform: rotate(0deg); }
100% { transform: rotate(0deg); }
}
#keyframes markerAnimation {
0% { display: none; opacity: 0; }
50% { display: block; opacity: 0; }
100% { display: block; opacity: 1; }
}
#keyframes markerReverseAnimation {
0% { display: block; opacity: 1; }
50% { display: block; opacity: 0; }
100% { display: none; opacity: 0; }
}
#animationContainer .marker {
opacity: 0;
position: absolute;
z-index: 10;
}
.rotated polygon {
animation-name: polygonAnimation;
animation-duration: 2s;
animation-fill-mode: both;
}
.rotated .marker {
animation-name: markerAnimation;
animation-duration: 2s;
animation-fill-mode: both;
}
.faded polygon {
animation-name: polygonReverseAnimation;
animation-duration: 2s;
animation-fill-mode: both;
}
.faded .marker {
animation-name: markerReverseAnimation;
animation-duration: 2s;
animation-fill-mode: both;
}
<div id="animationContainer">
<div class="marker marker-index-0">
<h3>I should be a tooltip</h3>
</div>
<svg>
<circle cx="40" cy="122.5" r="26" fill="red"></circle>
<g class="markerG" transform="matrix(1,0,0,1,40,122.5)"><circle cx="0" cy="0" r="14" fill="#000000" style="cursor: pointer;"></circle><polygon points="1 -1 1 -7 -1 -7 -1 -1 -7 -1 -7 1 -1 1 -1 7 1 7 1 1 7 1 7 -1" fill="#ffffff"></polygon></g>
</svg>
</div>
Just add the following to your event listener that rotates the svg. The rest is just css.
$('.marker-index-0').show();
Btw you have cursor pointer on the inner circle, but it only works on clicking the polygon. That's not intuitive design.

CSS animation for SVG in IE10/IE11

I have this code:
<svg height="100" width="100">
<style>
.svg-circle {
-webkit-transform-origin: 50% 0;
transform-origin: 50% 0;
-webkit-transform: rotateY(0);
transform: rotateY(0);
}
.svg-circle:hover {
-webkit-transform: rotateY(360deg);
transform: rotateY(360deg);
-webkit-transition: all 0.7s;
transition: all 0.7s;
}
</style>
<circle class="svg-circle" cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
It works well in modern browsers. Can I make it works in IE10/IE11? Or I need to use only Javascript?
After long researching I came to the conclusion the best way for cross-browser support — put image in <div> as background-image and apply CSS to it.
JSFiddle
.circle {
width: 100px;
height: 100px;
background: url(http://imgh.us/circle_5.svg) no-repeat;
background-size: 100px 100px;
-webkit-transform: rotateY(0);
transform: rotateY(0);
}
.circle:hover {
-webkit-transform: rotateY(360deg);
transform: rotateY(360deg);
-webkit-transition: all 0.7s;
transition: all 0.7s;
}
<div class="circle"></div>
Well, is it force on rotating the <circle/>?
Because you can easily rotate <svg></svg> in all browsers!
If yes, so you are in big trouble because in IE your problem is not only CSS3 support, you going to have some problem with JS, and that's because of rotateX or rotateY!
And even worst, you going to have some problem with animating it in jQuery!
So I used VELOCITY.JS to animating it and you can see this [ SAMPLE ] on IE and change rotateZ by rotateY! (to see rotateY is not working on SVG childs like path, circle, etc)
It seems you have to change your plan!
Hope to help! And by the way! by puting transition on hover state, you don't have it on hover-back!

Categories

Resources