I have created a svg image animation. I am trying to make some nice effects with mouseover. I want to move the svg depending on mouse position. The rotate part works fine so far. But I also want to move the <g>
inside the svg in z-axis (popout) so they comes out in "different layers". Should be possible with translateZ()
. But I can not get it to work.
const container = document.querySelector('.container');
const image = document.querySelector('.image');
const sun = document.querySelector('.sun');
const cloudBehind = document.querySelector('.cloud-center');
const cloudLeft = document.querySelector('.cloud-left');
const cloudRight = document.querySelector('.cloud-right');
const devideAxis = 10;
container.addEventListener('mousemove', e => {
let xAxis = ~(window.innerWidth / 2 - e.pageX) / devideAxis;
let yAxis = (window.innerHeight / 2 - e.pageY) / devideAxis;
image.style.transform = `rotateY(${xAxis}deg) rotateX(${yAxis}deg)`;
});
container.addEventListener('mouseenter', e => {
image.style.transition = 'none';
//popout
cloudLeft.style.transform = 'translateZ(400px)'
})
container.addEventListener('mouseleave', e => {
image.style.transition = 'all 0.5s ease';
image.style.transform = `rotateY(0deg) rotateX(0deg)`
cloudLeft.style.transform = 'translateZ(0)'
})
body,html {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
perspective: 300px;
}
.container {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.image {
width: 50%;
transform-style: preserve-3d;
}
.cloud-left {
transition: all .5s ease-out
}
.cloud-left,
.cloud-right,
.cloud-center {
transition: transform .5s;
}
.cloud-center{
fill:url(#CLOUD-CENTER);
}
.cloud-right{
fill:url(#CLOUD-FRONT);
}
.cloud-left{
fill:url(#CLOUD-FRONT);
}
.sun{
fill:url(#SUN);
}
.shine{
fill:url(#SHINE);
}
<div class="container">
<div class="image">
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 500 250" >
<g id="wheather">
<radialGradient id="SHINE" cx="100" cy="100" r="100" gradientUnits="userSpaceOnUse">
<stop offset="0.7568" style="stop-color:#FFFFFF"/>
<stop offset="1" style="stop-color:#FFF3AB"/>
</radialGradient>
<linearGradient id="SUN" gradientUnits="userSpaceOnUse" x1="27.6083" y1="98.0519" x2="169.5758" y2="98.0519">
<stop offset="0" style="stop-color:#FFF3AB"/>
<stop offset="1" style="stop-color:#FFF2C0"/>
</linearGradient>
<linearGradient id="CLOUD-CENTER" gradientUnits="userSpaceOnUse" x1="0" y1="66.2549" x2="288.0558" y2="66.2549">
<stop offset="0" style="stop-color:#8EABBF"/>
<stop offset="1" style="stop-color:#ECF1F7"/>
</linearGradient>
<linearGradient id="CLOUD-FRONT" gradientUnits="userSpaceOnUse" x1="0" y1="62.1091" x2="294.4617" y2="62.1091">
<stop offset="5.759445e-07" style="stop-color:#FFFFFF"/>
<stop offset="1" style="stop-color:#C5D6E5"/>
</linearGradient>
<!-- SUN -->
<g transform="translate(250 0)" class="sun">
<path class="shine" d="M162.4,147.8l22,0.9l-9.8-15.5c-0.2-0.5-0.5-1-0.8-1.5v0c-3.1-4.9-1.6-11.1,3-14.2l20.3-8.1l-14.9-9.9
c-0.5-0.5-1-0.9-1.5-1.3h0c-4.9-3.3-6-9.8-2.8-14.5l15-15.3l-17.3-2.9c-0.7-0.3-1.4-0.5-2.2-0.6h0c-6-1-9.7-6.9-8.4-12.6l7.3-19.6
l-16.9,4.3c-0.7,0-1.5,0.1-2.2,0.3h0c-6.3,1.6-12.5-2.9-12.9-9.4v0c0-0.2,0-0.3,0-0.4l-1.2-19.1l-13.8,10.9
c-0.6,0.3-1.1,0.7-1.7,1.1c-5.1,4-12.6,2.4-15.6-3.3l0,0c-0.2-0.5-0.5-0.9-0.8-1.3L98.6,0l-8.4,16c-0.3,0.4-0.6,0.9-0.8,1.3v0
c-3,5.8-10.5,7.4-15.6,3.3h0c-0.5-0.4-1.1-0.8-1.7-1.1L58.3,8.6l-1.2,19.1c0,0.1,0,0.3,0,0.4v0c-0.4,6.5-6.6,11-12.9,9.4h0
c-0.8-0.2-1.5-0.3-2.2-0.3l-16.9-4.3l7.3,19.6c1.3,5.7-2.4,11.6-8.4,12.6h0c-0.8,0.1-1.5,0.3-2.2,0.6L4.3,68.5l15,15.3
c3.2,4.7,2.1,11.2-2.8,14.5c-0.6,0.4-1.1,0.8-1.5,1.3L0,109.5l20.3,8.1c4.6,3,6.1,9.3,3,14.2l0,0c-0.3,0.5-0.6,1-0.8,1.5l-9.8,15.5
l22-0.9c5.4,0.9,9.3,6,8.4,11.7v0c0,0.3-0.1,0.6-0.1,0.9l-2.8,19l19.7-9.8c5-1.3,10.3,1.3,12.2,6.1l5.7,20.4l13.8-16.7
c3.9-3.4,9.7-3.4,13.5,0l13.8,16.7l5.7-20.4c2-4.9,7.3-7.4,12.2-6.1l19.7,9.8l-2.8-19c0-0.3,0-0.6-0.1-0.9v0
C153.2,153.8,157,148.7,162.4,147.8z">
<animateTransform
attributeName="transform"
attributeType="XML"
type="rotate"
from="0 100 100"
to="360 100 100"
dur="80s"
repeatCount="indefinite"
/>
</path>
<circle class="sun-inside" cx="98.6" cy="98.1" r="71"/>
</g>
<!-- / SUN -->
<!-- CLOUD BEHIND -->
<g transform="translate(70 70)">
<path class="cloud-center" style="transform: " d="M261.5,79.4c-3.4,0-6.6,0.6-9.6,1.8c-1.9-5.5-6-10-11.3-12.5c0-0.2,0-0.3,0-0.5c0-27.1-21.9-49-49-49
c-0.6,0-1.2,0-1.8,0c-9-11.7-23.1-19.2-39-19.2c-18,0-33.8,9.7-42.3,24.1c-3.8-3.1-8.6-5-13.8-5c-11.1,0-20.3,8.4-21.6,19.2
c-3.7-1.1-7.7-1.7-11.7-1.7C39,36.6,21,54.6,21,76.9c0,2.8,0.3,5.6,0.9,8.3C9.6,86.1,0,96.3,0,108.8c0,13.1,10.6,23.7,23.7,23.7
h237.8c14.7,0,26.6-11.9,26.6-26.6S276.2,79.4,261.5,79.4z">
<animateMotion
path="M50,0 -50,0 50,0 z"
dur="80s"
repeatCount="indefinite"
/>
</path>
</g>
<!-- / CLOUD BEHIND -->
<!-- CLOUD LEFT -->
<g transform="translate(10 126)">
<path class="cloud-left" d="M270.4,76.2C270.4,76.2,270.4,76.2,270.4,76.2c-1.1-22-19.3-39.6-41.6-39.6c-5.1,0-9.9,0.9-14.4,2.6
C206.9,16.4,185.5,0,160.2,0c-20.6,0-38.6,10.9-48.6,27.3c-4.6-1.5-9.4-2.3-14.5-2.3c-23.4,0-42.8,16.9-46.7,39.1
c-5.1-3.3-11.2-5.2-17.7-5.2C14.6,58.9,0,73.5,0,91.6c0,18,14.6,32.7,32.7,32.7h237.8c13.3,0,24-10.8,24-24
C294.5,86.9,283.7,76.2,270.4,76.2z M194.9,102.4h-0.2c0.1,0,0.1-0.1,0.2-0.1C194.9,102.4,194.9,102.4,194.9,102.4z">
<animateMotion
path="M30,0 0,0 00,0 30,0 z"
dur="15s"
repeatCount="indefinite"
/>
</path>
</g>
<!-- / CLOUD LEFT -->
<!-- CLOUD RIGHT -->
<g transform="translate(260 140)">
<path class="cloud-right" d="M228.8,73.7c0-19.9-16.1-36-36-36c-3.5,0-6.8,0.5-10,1.4c-4.4-18.7-21.2-32.7-41.3-32.7c-10.7,0-20.5,4-28,10.6
C104.6,6.6,91.4,0,76.7,0C49.9,0,28.3,21.7,28.3,48.4c0,1.6,0.1,3.2,0.2,4.8c-0.1,0-0.2,0-0.2,0C12.7,53.2,0,65.9,0,81.5
s12.7,28.3,28.3,28.3H198v-0.4C215.4,106.8,228.8,91.8,228.8,73.7z">
<animateMotion
path="M-40,0 0,0 -100,0 -40,0 z"
dur="60s"
repeatCount="indefinite"
/>
</path>
</g>
<!-- / CLOUD RIGHT -->
</g>
</svg>
</div>
</div>
Main code things:
So I have body
, which has perspective: 300px;
. Then I have .image
which has transform-style: preserve-3d;
and inside that element I have the <g>
's with classes.
As an example I have a .cloud-left
.
So the structure is basically:
<body>
<div class="container">
<div class="image">
<svg>
<g id="wheather">
<g class="cloud-left">...</g>
...
</g>
</svg>
</div>
</div>
</body>
In javascript I have this (Shortned, to see all code, please see the fiddle above):
const cloudLeft = document.querySelector('.cloud-left'); // get the element
container.addEventListener('mouseenter', e => {
//popout
cloudLeft.style.transform = 'translateZ(400px)'
})
container.addEventListener('mouseleave', e => {
//popback
cloudLeft.style.transform = 'translateZ(0)'
})
But this does not work as I want.
I have also tried to set transform-style: preserve-3d;
on <g id="weather">
which is the direct parent to the other <g>
's, but no difference.
I am not getting the <g>
to move/popout in z-axis. Am I missing something in the svg or does this not work in svg groups?
I have another example where this works, but it is not an svg: https://jsfiddle.net/saturday99/94o5j8ts/