I'm working on a rock paper scissors game. When I click a button I have it where two images do a "shake" animation to simulate the hand motions done during a real game. This is all fine, however the image on the right flips horizontally during the animation but flips back at the end. I initially have it flipped so both hands face each other.
I'm wondering if it's possible to prevent that second image from flipping during the animation.
Images before the animation
Images during the animation
HTML
<div class="img-container">
<div class="player-container">
<p class="player-1-text">Player Options: </p>
<div class="player-img-container">
<button onclick="animation()"><img src="img/rock.jpg" alt="Rock Sign" width="100" height="100" class="img-space" id="player-img-main"></button>
<button><img src="img/paper.jpg" alt="Rock Sign" width="100" height="100" class="img-space"></button>
<button><img src="img/scissors.jpg" alt="Rock Sign" width="100" height="100" class="img-space"></button>
</div>
</div>
<div class="computer-container">
<div class="computer-img-container">
<img src="img/rock.jpg" alt="Rock Sign" width="100" height="100" class="img-space" id="computer-img-main">
<img src="img/paper.jpg" alt="Rock Sign" width="100" height="100" class="img-space" id="computer-img">
<img src="img/scissors.jpg" alt="Rock Sign" width="100" height="100" class="img-space" id="computer-img">
</div>
<p class="computer-text"> :Computer Options</p>
</div>
</div>
Javascript
function animation() {
const element = document.getElementById('player-img-main');
const element2 = document.getElementById('computer-img-main');
element.classList.remove('shake'); // reset animation
element2.classList.remove('shake'); // reset animation
void element.offsetWidth; // trigger reflow
void element2.offsetWidth; // trigger reflow
element.classList.add('shake'); // start animation
element2.classList.add('shake'); // start animation
}
CSS
#computer-img-main {
transform: scaleX(-1); /* Flip image horizontally */
}
.shake {
animation-name: shake;
animation-iteration-count: 1;
animation-duration: 2s;
animation-fill-mode: both;
}
#keyframes shake {
3%, 21%, 39%, 57%, 74%, 92% { transform: translateY(5px) }
6%, 24%, 42%, 60%, 77%, 95% { transform: translateY(3px) }
9%, 27%, 45%, 63%, 80%, 98% { transform: translateY(-5px) }
}
You can keep the HTML structure as it is, and share the keyframes, but you need to remember what the scaling is (the flipping of the hand image) and make sure that is in any transform that is done.
You could use a CSS variable for this. e.g. here we set --s to 1 for the player side and to -1 for the computer side. And then in the transforms in the keyframes we add in scaleX(var(--s)).
#player-img-main {
--s: 1;
}
#computer-img-main {
transform: scaleX(-1);
--s: -1;
/* Flip image horizontally */
}
.shake {
animation-name: shake;
animation-iteration-count: 1;
animation-duration: 2s;
animation-fill-mode: both;
}
#keyframes shake {
3%,
21%,
39%,
57%,
74%,
92% {
transform: scaleX(var(--s)) translateY(5px)
}
6%,
24%,
42%,
60%,
77%,
95% {
transform: scaleX(var(--s)) translateY(3px)
}
9%,
27%,
45%,
63%,
80%,
98% {
transform: scaleX(var(--s)) translateY(-5px)
}
}
injection:
If there is some property in the CSS to create such an angle as in the layout
The program itself does not specify this property in the tab
I tried to search there
!:
You can simply use clip-path css property, and here is an example:
.square{
clip-path: polygon(80% 0%, 100% 20%, 100% 80%, 0% 80%, 0 0);
background-color:dodgerblue;
width:200px;
height:200px;
}
<div class="square"></div>
clip-path: polygon(80% 0%, 100% 20%, 100% 80%, 0% 80%, 0 0);
for more info about this property MDN clip-path
I am trying to create a radial-gradient shine affect to a div box and I am unsure whats the best way of doing so. I Have found no resources of achieving what I want to achieve; just shine affects which look like overlay.
Most of the examples I have found looks like this http://jsfiddle.net/nqQc7/512/.
Below I have displayed what I am trying to create.
#shine-div {
height: 30vh;
width: 60vw;
margin-right: auto;
margin-left: auto;
border-radius: 10px;
/*background: radial-gradient(ellipse farthest-corner at right top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%);*/
display: flex;
justify-content: center;
align-items: center;
color: white;
font-weight: bold;
animation: colorChange 5s infinite;
}
#keyframes colorChange {
0% {
background: radial-gradient(ellipse farthest-corner at left top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%)
}
50% {
background: radial-gradient(ellipse farthest-corner at top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%)
}
100% {
background: radial-gradient(ellipse farthest-corner at right top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%)
}
}
<div id="shine-div">
Shine
</div>
Is it possible to do this? I'd also like to make the white shine on top to go from left to right smoothly? Am I even on the right track with my attempt?
You can do the gradient differently and animate the position. The trick is to double the size of the gradient and make the value of color stop half of their actual values so you keep the same visual gradient then you can animate it from left to right.
It won't look exactly the same as the gradient you defined in the animation due to the calculation of farthest-corner.
#shine-div {
height: 30vh;
width: 60vw;
margin-right: auto;
margin-left: auto;
border-radius: 10px;
background: radial-gradient(farthest-corner at top, #FFFFFF 0%, #ffb3ff 4%, #ff33ff 12.25%, #800080 31.25%, #b300b3 50%) top right/200% 200%;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-weight: bold;
animation: colorChange 5s infinite alternate;
}
#keyframes colorChange {
to {
background-position:top left;
}
}
<div id="shine-div">
Shine
</div>
To get more closer to your gradients you have to also animate the background-size (see below for calculation details)
#shine-div {
height: 30vh;
width: 60vw;
margin-right: auto;
margin-left: auto;
border-radius: 10px;
background: radial-gradient(farthest-corner at top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 24.5%, #800080 62.5%, #b300b3 100%);
display: flex;
justify-content: center;
align-items: center;
color: white;
font-weight: bold;
animation: colorChange 5s infinite alternate linear;
}
#keyframes colorChange {
from { /* radial-gradient(farthest-corner at top right, ..) */
background-position:left top;
background-size:200% 100%;
}
49.9% {
background-position:left top;
}
50% { /* radial-gradient(farthest-corner at top center, ..) */
background-size:100% 100%;
}
50.1% {
background-position:right top;
}
to { /* radial-gradient(farthest-corner at top left, ..) */
background-position:right top;
background-size:200% 100%;
}
}
<div id="shine-div">
Shine
</div>
You can also do the same animation considering pseudo element and transformation to have better performance:
#shine-div {
height: 30vh;
width: 60vw;
margin-right: auto;
margin-left: auto;
border-radius: 10px;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-weight: bold;
overflow:hidden;
position:relative;
z-index:0;
}
#shine-div:before {
content:"";
position:absolute;
z-index:-1;
top:0;
left:0;
width:400%;
height:200%;
background: radial-gradient(farthest-corner at top, #FFFFFF 0%, #ffb3ff 4%, #ff33ff 12.25%, #800080 31.25%, #b300b3 50%);
animation: colorChange 5s infinite alternate linear;
}
#keyframes colorChange {
from {
transform:translateX(-50%);
}
50% {
transform:scaleX(0.75) translateX(-50%)
}
to {
transform:translateX(-25%);
}
}
<div id="shine-div">
Shine
</div>
More in-depth
To make the answer more generic, I am going to detail how you can animate any kind of gradient from two different position. The main trick is to write the gradient differently to have its definition a constant ( radial-gradient(<constant_definition>) ) and animate the background-position (and the background-size in some cases)
Let's consider our gradient to be background:radial-gradient(Rh Rv at X Y, color1 p1, color2 p2) where Rh and Ry are respectively the horizontal radius and vertical radius of our ellipse (if both are equal or only one value is used then it's a circle).
First, we double the size of the gradient. This trick will allow us to easily adjust the position of the gradient using percentage value (explained here: Using percentage values with background-position on a linear-gradient)
If the radius is defined with pixel values we keep it but if it's defined with percentage value we divide it by 2 since it's relative to the size that he have increased. If both radius are in percentage we can either divide both by 2 or keep them and divide the color stops by 2.
Second, we remove the at X Y which will bring the gradient in the center thus we need to rectify the position using background-position. It's clear that if the gradient was at 0 0 we need to use background-position:100% 100%
The green box is our background twice bigger than the element (the black box) and the red circle is our gradient. By adjusting the background position we visually position the gradient at 0 0.
For any X, Y values we will logically have background-position:calc(100% - X) calc(100% - Y)
If X,Y are pixel values we can also use background-position: right -X bottom -Y (note that it' -X and not - X, we use the negative value)
Examples:
With pixel values
.box {
height:150px;
width:150px;
border:1px solid;
display:inline-block;
}
<div class="box" style="background:radial-gradient(20% 100px at 20px 30px,red 30%,blue 60%);"></div>
<div class="box" style="background:radial-gradient(10% 100px,red 30%,blue 60%) right -20px bottom -30px/200% 200%;"></div>
<br>
<div class="box" style="background:radial-gradient(40% 40% at 40px 50px,yellow 30%,blue);"></div>
<div class="box" style="background:radial-gradient(40% 40%,yellow 15%,blue 50%) right -40px bottom -50px/200% 200%;"></div>
<div class="box" style="background:radial-gradient(20% 20%,yellow 30%,blue) right -40px bottom -50px/200% 200%;"></div>
With percentage values
.box {
height:150px;
width:150px;
border:1px solid;
display:inline-block;
}
<div class="box" style="background:radial-gradient(20% 100px at 50% 10%,red 30%,blue 60%);"></div>
<div class="box" style="background:radial-gradient(10% 100px,red 30%,blue 60%) calc(100% - 50%) calc(100% - 10%)/200% 200%;"></div>
<br>
<div class="box" style="background:radial-gradient(40% 40% at 30% 70%,yellow 30%,blue);"></div>
<div class="box" style="background:radial-gradient(40% 40%,yellow 15%,blue 50%) calc(100% - 30%) calc(100% - 70%)/200% 200%;"></div>
<div class="box" style="background:radial-gradient(20% 20%,yellow 30%,blue) calc(100% - 30%) calc(100% - 70%)/200% 200%;"></div>
So if we want to animate a gadient from:
radial-gradient(Rh Rv at X Y, color1 p1, color2 p2)
to
radial-gradient(Rh Rv at X1 Y2, color1 p1, color2 p2)
we write it differently and we animate the background-position:
.box {
height:150px;
width:150px;
border:1px solid;
display:inline-block;
}
.first {
background:radial-gradient(10% 100px,red 30%,blue 60%) calc(100% - 50%) calc(100% - 10%)/200% 200%;
animation:change1 2s linear infinite alternate;
}
.second {
background:radial-gradient(20% 20%,yellow 30%,blue)right -50px bottom 0/200% 200%;
animation:change2 2s linear infinite alternate;
}
#keyframes change1 {
to {
background-position:calc(100% + 10%) calc(100% - 80%);
}
}
#keyframes change2 {
to {
background-position:right -100px bottom -100px;
}
}
<div class="box first" ></div>
<div class="box second"></div>
Now let's consider more tricky cases, like our initial example, using farthest-side in order to define the size. We will do the same logic and convert
radial-gradient(farthest-side at X Y, color1 p1, color2 p2);
to
radial-gradient(farthest-side, color1 p1, color2 p2) Px Py/Sx Sy no-repeat;
I will explain for one axis (X) and the same apply to the other
farthest-side define the radius to be the distance from the gradient center to the farthest side of the gradient box (the gradient box is by default the element itself since we didn't define any size). If X is a percentage value then the radius is the max between X and 100% - X and in the transformed gradient the radius will be 50% since we are at the center. So we need to match the first radius with 50%*Sx
If X is 50% then Sx should be 100% and if X is 0 or 100% then Sx should be 200%.
The formula is Sx = max(X,100% - X)*2
The position is easier in this case due to the nature of the gradient where the shape should touch one side
If X within [0 50%[ Px should be 100% (right)
If X is 50% any value for Px will work since Sx=100%
If X within ]50% 100%] Px shoudd be 0% (left)
Related question: Using percentage values with background-position on a linear-gradient
Examples:
.box {
height:150px;
width:150px;
border:1px solid;
display:inline-block;
}
<div class="box" style="background:radial-gradient(farthest-side at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(farthest-side, red 20%, blue 100%, yellow 50%) 100% 0/calc(80%*2) calc(60%*2)"></div>
<br>
<div class="box" style='background:radial-gradient(farthest-side at 22% 100%,red 40%, blue 100%,yellow 100%)'></div>
<div class="box" style="background:radial-gradient(farthest-side,red 40%, blue 100%,yellow 100%) 100% 0/calc(78%*2) calc(100%*2)"></div>
For the farthest-corner we do exactly the same:
.box {
height:150px;
width:150px;
border:1px solid;
display:inline-block;
}
<div class="box" style="background:radial-gradient(farthest-corner at 20% 60%, red 20%, blue 50%, yellow 60%)" ></div>
<div class="box" style="background:radial-gradient(farthest-corner, red 20%, blue 50%, yellow 60%) 100% 0%/calc(80%*2) calc(60%*2)"></div>
<br>
<div class="box" style="background:radial-gradient(farthest-corner at 40% 100%, red 20%, blue 50%, yellow 60%)" ></div>
<div class="box" style="background:radial-gradient(farthest-corner, red 20%, blue 50%, yellow 60%) 100% 0%/calc(60%*2) calc(100%*2)"></div>
We can also transform farthest-side (or farthest-corner) to Rh Rv and do the previous calculation but it won't be useful for the animation since we will have two gradient with different radius whereas we need the same gradient.
.box {
height:150px;
width:150px;
border:1px solid;
display:inline-block;
}
<div class="box" style="background:radial-gradient(farthest-side at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(80% 60% at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(80% 60%, red 10%, blue 50%, yellow 50%) 80% 40%/200% 200%"></div>
If X is a pixel value we have two cases:
The element has a fixed width: In this case we can simply convert the pixel value of X as a percentage of the width and we do the same logic as above.
The element has a variable width: In this case it would be tricky to convert the gradient (probably impossible) because the shape will change based on the width. When width-X > X we will have a variable radius and when width-X < X we will have a fixed radius. I don't think we can express this using background-size and background-position. Example:
body {
margin:0;
height:100vh;
background:radial-gradient(farthest-side at 400px 200px,blue 40%,yellow 50%);
}
For the closest-side will do the same logic considering Sx=min(X,100% - X)*2 BUT we should add no-repeat and a background-color equal to the last color in the gradient since the size is less than 100%
.box {
height:150px;
width:150px;
border:1px solid;
display:inline-block;
}
<div class="box" style="background:radial-gradient(closest-side at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(closest-side, red 20%, blue 100%, yellow 100%) 0 100%/calc(20%*2) calc(40%*2)"></div>
<div class="box" style="background:radial-gradient(closest-side, red 20%, blue 100%, yellow 100%) 0 100%/calc(20%*2) calc(40%*2) no-repeat,yellow"></div>
<br>
<div class="box" style='background:radial-gradient(closest-side at 22% 10%,red 40%, blue 100%,yellow 100%)'></div>
<div class="box" style="background:radial-gradient(closest-side,red 40%, blue 100%,yellow 100%) 0 0/calc(22%*2) calc(10%*2)"></div>
<div class="box" style="background:radial-gradient(closest-side,red 40%, blue 100%,yellow 100%) 0 0/calc(22%*2) calc(10%*2) no-repeat,yellow"></div>
We can do the same for closest-corner but we will have some issue due the fact that the gradient can overflow the gradient box.
.box {
height:150px;
width:150px;
border:1px solid;
display:inline-block;
}
<div class="box" style="background:radial-gradient(closest-corner at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(closest-corner, red 20%, blue 100%, yellow 100%) 0 100%/calc(20%*2) calc(40%*2)"></div>
<div class="box" style="background:radial-gradient(closest-corner, red 20%, blue 100%, yellow 100%) 0 100%/calc(20%*2) calc(40%*2) no-repeat,yellow"></div>
To rectify this we can divide the color stop by 2 to make sure we keep the whole gradient inside. Then we make the size twice bigger and we rectify the position
.box {
height:150px;
width:150px;
border:1px solid;
display:inline-block;
}
<div class="box" style="background:radial-gradient(closest-corner at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(closest-corner, red 10%, blue 50%, yellow 50%) -100% 33%/calc(20%*4) calc(40%*4)"></div>
<div class="box" style="background:radial-gradient(closest-corner, red 10%, blue 50%, yellow 50%) -100% 33%/calc(20%*4) calc(40%*4) no-repeat,yellow"></div>
<br>
<div class="box" style='background:radial-gradient(closest-corner at 22% 10%,red 40%, blue 100%,yellow 100%)'></div>
<div class="box" style="background:radial-gradient(closest-corner,red 20%, blue 50%,yellow 50%) -100% 0%/calc(22%*4) calc(10%*4)"></div>
<div class="box" style="background:radial-gradient(closest-corner,red 20%, blue 50%,yellow 50%) -164% -18%/calc(22%*4) calc(10%*4) no-repeat,yellow"></div>
Even without animation, the syntax of the gradient without the at X Y is more supported. Some browser like Safari doesn't support the at (How to make radial gradients work in Safari?)
Using CSS variables and with the new #property we can easily animate radial-gradient (or any kind of gradient). The support cover only Chrome and Edge for now.
#property --x {
syntax: '<percentage>';
inherits: false;
initial-value: 0%;
}
#shine-div {
height: 30vh;
width: 60vw;
margin: auto;
border-radius: 10px;
background: radial-gradient(ellipse farthest-corner at var(--x) 0%, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%);
animation: colorChange 5s infinite alternate;
}
#keyframes colorChange {
0% {
--x:0%;
}
50% {
--x:50%;
}
100% {
--x:100%;
}
}
<div id="shine-div"></div>
All we have to do is to define the position using a variable --x that will use percentage values and we animation that variable. As simple as that!
SVG solution
The author did not ask for a solution to his problem using SVG. But it will probably be useful to solve one issue in several ways.
Gradient attribute values were taken from the #Temani Afif response.
The SVG radial gradient formula for this question:
<radialGradient id="radGrad" fx="0%" fy="5%" r="200%">
<stop offset="0%" stop-color ="#FFFFFF" />
<stop offset="4%" stop-color ="#ffb3ff" />
<stop offset="12.25%" stop-color ="#ff33ff" />
<stop offset="31.25%" stop-color ="#800080" />
<stop offset="50%" stop-color ="#b300b3" />
</radialGradient>
To animate the gradient, you can use any attribute included in the formula.
The examples below will use the attributes fx andfy
Animation of horizontal gradient movement
Animation starts after clicking on a rectangle
svg {
width:50%;
height:50%;
}
.txt {
font-family:sans-serif;
font-size:28px;
font-weight:bold;
text-anchor:middle;
fill:#FFDD00;
}
<div id="shine-div">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 100">
<defs>
<radialGradient id="radGrad" fx="0%" fy="0%" r="200%">
<stop offset="0%" stop-color ="#FFFFFF" />
<stop offset="4%" stop-color ="#ffb3ff" />
<stop offset="12.25%" stop-color ="#ff33ff" />
<stop offset="31.25%" stop-color ="#800080" />
<stop offset="50%" stop-color ="#b300b3" />
</radialGradient>
</defs>
<g id="gr1" >
<rect id="rect1" fill="url(#radGrad)" x="5%" y="5%" width="95%" height="95%" rx="10%"/>
<text class="txt" x="50%" y="60%"> Sun shine </text>
</g>
<animate xlink:href="#radGrad"
attributeName="fx"
dur="3s"begin="gr1.click"
values="0%;100%;0%"
repeatCount="1"
restart="whenNotActive" />
</svg>
</div>
An animation of the vertical gradient movement.
svg {
width:50%;
height:50%;
}
.txt {
font-family:sans-serif;
font-size:28px;
font-weight:bold;
text-anchor:middle;
fill:#FFDD00;
}
<div id="shine-div">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 100">
<defs>
<radialGradient id="radGrad" fx="48%" fy="0%" r="200%">
<stop offset="0%" stop-color ="#FFFFFF" />
<stop offset="4%" stop-color ="#ffb3ff" />
<stop offset="12.25%" stop-color ="#ff33ff" />
<stop offset="31.25%" stop-color ="#800080" />
<stop offset="50%" stop-color ="#b300b3" />
</radialGradient>
</defs>
<g id="gr1" >
<rect id="rect1" fill="url(#radGrad)" x="5%" y="5%" width="95%" height="95%" rx="10%"/>
<text class="txt" x="50%" y="60%"> Sun shine </text>
</g>
<animate xlink:href="#radGrad"
attributeName="fy"
dur="2s"begin="gr1.click"
values="0%;50%;50%;100%;50%;50%;0%"
keyTimes="0;0.1;0.5;0.6;0.7;0.9;1"
repeatCount="1"
restart="whenNotActive" />
</svg>
</div>
Moving the gradient diagonally
Two attributes are simultaneously animated: fx andfy
svg {
width:50%;
height:50%;
}
.txt {
font-family:sans-serif;
font-size:28px;
font-weight:bold;
text-anchor:middle;
fill:#FFDD00;
}
<div id="shine-div">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 100">
<defs>
<radialGradient id="radGrad" fx="0%" fy="0%" r="200%">
<stop offset="0%" stop-color ="#FFFFFF" />
<stop offset="4%" stop-color ="#ffb3ff" />
<stop offset="12.25%" stop-color ="#ff33ff" />
<stop offset="31.25%" stop-color ="#800080" />
<stop offset="50%" stop-color ="#b300b3" />
</radialGradient>
</defs>
<g id="gr1" >
<rect id="rect1" fill="url(#radGrad)" x="5%" y="5%" width="95%" height="95%" rx="10%"/>
<text class="txt" x="50%" y="60%"> Sun shine </text>
</g>
<animate xlink:href="#radGrad"
attributeName="fy"
dur="2s"begin="gr1.click"
values="0%;50%;50%;100%;0%"
keyTimes="0;0.1;0.5;0.9;1"
repeatCount="1"
restart="whenNotActive" />
<animate xlink:href="#radGrad"
attributeName="fx"
dur="2s"begin="gr1.click"
values="0%;50%;50%;100%;0%"
keyTimes="0;0.1;0.5;0.9;1"
repeatCount="1"
restart="whenNotActive" />
</svg>
</div>
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.