admin管理员组文章数量:1279124
I need some help from you guys. I can't find a good solution to my problem. I got sections in my website with some animated SVGs. I used vivus.js for this. / The problem is that i can't find a solution to start the animation when the user scrolls on the section with the animated SVGs.
I need some help from you guys. I can't find a good solution to my problem. I got sections in my website with some animated SVGs. I used vivus.js for this. https://maxwellito.github.io/vivus-instant/ The problem is that i can't find a solution to start the animation when the user scrolls on the section with the animated SVGs.
Share Improve this question edited Oct 28, 2017 at 0:57 Paul LeBeau 102k9 gold badges168 silver badges197 bronze badges asked Oct 27, 2017 at 7:06 Dan PlatonDan Platon 531 silver badge4 bronze badges 1- Add please a minimal working code snippet and what you tried yet to achieve it. – Doomenik Commented Oct 27, 2017 at 7:10
2 Answers
Reset to default 10To trigger an animation when the SVG scrolls into view, there are two steps you need to resolve:
- detect when the SVG is visible
- have the animation paused initially, then trigger it when you want
Detecting when an element is visible
You need to add an event handler for scroll events. In that event handler, you pare the page scroll location (window.scrollY
) against the SVG's location on the page. You can get that using getBoundingClientRect()
.
See the demos below for example code implementing this technique.
Starting an animation running
The second step is actually triggering the animation at that time. How you keep an animation paused and then start it running, depends on the method of animation you are using.
SVG SMIL animation
In this first example, we are using the SMIL animation elements that are part of the SVG standard.
To have an animation wait for you to start it running, set the begin
attribute to "indefinite"
. The you can start it running by calling beginElement()
on the <animate>
element.
// Get the position on the page of the SVG
var svgLocation = document.getElementById("mysvg").getBoundingClientRect();
// Scroll offset that triggers animation start.
// In this case it is the bottom of the SVG.
var offsetToTriggerAnimation = svgLocation.y + svgLocation.height;
// Function to handle the scroll event.
// Add an event handler to the document for the "onscroll" event
function scrollAnimTriggerCheck(evt)
{
var viewBottom = window.scrollY + window.innerHeight;
if (viewBottom > offsetToTriggerAnimation) {
// Start the SMIL animation
document.getElementById("anim").beginElement();
// Remove the event handler so it doesn't trigger again
document.removeEventListener("scroll", scrollAnimTriggerCheck);
}
}
// Add an event handler to the document for the "onscroll" event
document.addEventListener("scroll", scrollAnimTriggerCheck);
svg {
border: solid 1px grey;
}
p {
margin-bottom: 1000px;
}
<p>Scroll down</p>
<svg id="mysvg">
<rect x="0" width="150" height="150" fill="rebeccapurple">
<animate id="anim" attributeName="x" from="0" to="150" dur="2s"
fill="freeze" begin="indefinite"/>
</rect>
</svg>
<br>
<br>
<br>
<br>
CSS animation
There are a couple of way you can trigger an animation to start when you are using CSS animations.
Put your
animation
property in its own style set class, then add that class to the element:.anim { animation-name: slide; animation-duration: 2s; } myobject.classList.add("anim");
// Get the position on the page of the SVG
var svgLocation = document.getElementById("mysvg").getBoundingClientRect();
// Scroll offset that triggers animation start.
// In this case it is the bottom of the SVG.
var offsetToTriggerAnimation = svgLocation.y + svgLocation.height;
// Function to handle the scroll event.
// Add an event handler to the document for the "onscroll" event
function scrollAnimTriggerCheck(evt)
{
var viewBottom = window.scrollY + window.innerHeight;
if (viewBottom > offsetToTriggerAnimation) {
// Start the CSS animation by adding the animation CSS rules to the rect element
document.querySelector("rect").classList.add("anim");;
// Remove the event handler so it doesn't trigger again
document.removeEventListener("scroll", scrollAnimTriggerCheck);
}
}
// Add an event handler to the document for the "onscroll" event
document.addEventListener("scroll", scrollAnimTriggerCheck);
.anim {
animation: slide 2s linear forwards;
}
@keyframes slide {
from {
transform: translate(0px, 0px);
}
to {
transform: translate(150px, 0px);
}
}
svg { border: solid 1px grey; }
p { margin-bottom: 1000px; }
<p>Scroll down</p>
<svg id="mysvg">
<rect x="0" width="150" height="150" fill="rebeccapurple"/>
</svg>
<br>
<br>
<br>
<br>
The second way is to make use of the
animation-play-state
CSS property. Not all browsers support this yet.The idea is that you set
animation-play-state
topaused
initially, then change it torunning
when you want the animation to start. You can either do that by adding a class with that property (similar to above). Or you can set thestyle.animationPlayState
property directly, as in the example below.
// Get the position on the page of the SVG
var svgLocation = document.getElementById("mysvg").getBoundingClientRect();
// Scroll offset that triggers animation start.
// In this case it is the bottom of the SVG.
var offsetToTriggerAnimation = svgLocation.y + svgLocation.height;
// Function to handle the scroll event.
// Add an event handler to the document for the "onscroll" event
function scrollAnimTriggerCheck(evt)
{
var viewBottom = window.scrollY + window.innerHeight;
if (viewBottom > offsetToTriggerAnimation) {
// Start the CSS animation by setting the animation-play-state to "running"
document.querySelector("rect").style.animationPlayState = "running";
// Remove the event handler so it doesn't trigger again
document.removeEventListener("scroll", scrollAnimTriggerCheck);
}
}
// Add an event handler to the document for the "onscroll" event
document.addEventListener("scroll", scrollAnimTriggerCheck);
.anim {
animation: slide 2s linear forwards;
animation-play-state: paused;
}
@keyframes slide {
from {
transform: translate(0px, 0px);
}
to {
transform: translate(150px, 0px);
}
}
svg { border: solid 1px grey; }
p { margin-bottom: 1000px; }
<p>Scroll down</p>
<svg id="mysvg">
<rect x="0" width="150" height="150" fill="rebeccapurple" class="anim"/>
</svg>
<br>
<br>
<br>
<br>
Anyone looking for a React solution, this is what worked for me,
changing the key
value of an svg elements i wanted re-start the animation of.
For example, I set the key of an svg element as such:
<span
ref={nameRef}
className={`underline-animation ${
nameRefinView ? "in-view" : ""
}`}
>
<svg
....
key={nameKey} // <----HERE
>
<path
....
/>
</svg>
Awshaf
</span>
Note: naneRefinView
is true when nameRef
es into viewport, and defined as such:
const [nameRef, nameRefinView] = useInView({
threshold: 0.6,
triggerOnce: false,
});
Ref of inView: https://github./thebuilder/react-intersection-observer
Finally I change the key
every time the element es into viewport:
useEffect(() => {
if (!nameRefinView) {
} else {
setNameKey(Math.random());
}
}, [nameRefinView]);
Whenever react's key value changes, it triggers a re-render of the element without a page refresh. That is why when there is a new key, the animation is restarted as the element bees rendered. For reference here is the CSS i used for the code above:
.underline-animation {
text-decoration: none;
position: relative;
}
.underline-animation svg {
display: inline-block !important;
position: absolute;
top: 85%;
left: 0;
width: 100%;
height: auto;
}
.underline-animation .stroke {
stroke: rgb(0, 0, 0);
stroke-width: .15em;
stroke-dasharray: 822;
stroke-dashoffset: 822;
animation: underlineAnimation 0.88s 0.7s cubic-bezier(0.17, 0.55, 0.55, 1) forwards;
animation-play-state: paused;
}
//==== ANIMATION starts ONLY when the element is in view port====
.underline-animation.in-view .stroke {
animation-play-state: running; /* Start animation when in view */
}
本文标签: javascriptHow to start an animated SVG on entering viewportStack Overflow
版权声明:本文标题:javascript - How to start an animated SVG on entering viewport? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741240180a2363820.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论