简体   繁体   English

在用户滚动时使用不透明度对SVG路径进行动画处理

[英]Animate SVG paths with opacity on user scroll sequentially

I've built an SVG that I want to animate, it has three parts/layers, each has a predefined amount of paths. 我已经构建了一个我想要制作动画的SVG,它有三个部分/层,每个部分都有预定义的路径。

The SVG is a circle logo type thing, has words at the top part of the circle and dashes around the remaining space and then type in the middle of the circle. SVG是圆形徽标类型的东西,在圆圈的顶部有单词并且在剩余空间周围划线,然后键入圆圈的中间。

Like this but simpler: http://pixelcurse.com/wp-content/uploads/2015/11/logo-badges-8.jpg 像这样但更简单: http //pixelcurse.com/wp-content/uploads/2015/11/logo-badges-8.jpg

What I want to do is this: 我想要做的是:

  1. Set opacity of svg to 0 before it comes into viewport 在进入视口之前将svg的不透明度设置为0
  2. Detect when SVG starts to come into viewport 检测SVG何时开始进入视口
  3. Change opacity of each path in first two <g> blocks sequentially based on scroll position (scrolling down) 根据滚动位置顺序更改前两个<g>块中每个路径的不透明度(向下滚动)
  4. When scrolling up the sequence reverses 向上滚动序列时会反转

I've been attempting to do this for two days on and off with nothing but failure. 我一直在尝试这样做两天,只有失败。 I succeeded working with simple jquery animation and css animation (see below code) but could not get these playing nice with scroll position. 我成功地使用了简单的jquery动画和css动画(见下面的代码),但是无法通过滚动位置获得这些效果。

Another idea I had but then realised it would be very cumbersome and not work in reverse was to have multiple if / else based on scroll position but I don't want this to have an explicit number due to different resolutions this will have to work on. 我有的另一个想法,但后来意识到这将是非常麻烦,而不是反向工作是有多个if / else基于滚动位置,但我不希望它有一个明确的数字,因为不同的分辨率,这将必须工作。

HTML: HTML:

<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 640 640" style="enable-background:new 0 0 640 640;" xml:space="preserve">
    <g id="mainsvg">
        <g id="top-circle-words">
            <path/>
            <path/>
            <path/>
            <path/>
            <path/>
            <path/>
            <path/>
            <path/>
            <path/>
            <path/>
        </g>

        <g id="bot-circle-dashes">
            <path/>
            <path/>
            <path/>
            <path/>
            <path/>
            <path/>
            <path/>
            <path/>
            <path/>
            <path/>
            <path/>
        </g>

        <g id="middle-words">
            <path/>
            <path/>
        </g>
    </g>
</svg>

CSS - animation attempt - works but no control - just plays on load: CSS - 动画尝试 - 但无法控制 - 只需加载:

svg {width:100%;max-width:50%;margin:50% auto;display:block;}

@-webkit-keyframes animIn { 0% { opacity: 0; } 100% { opacity:1; } }
@-webkit-keyframes animOut { 0% { opacity: 1; } 100% { opacity:0; } }

.animIn { -webkit-animation: animIn 500ms 1.5s normal backwards; -webkit-animation-fill-mode: both; }
.animOut { -webkit-animation: animOut 500ms 3s reverse backwards; -webkit-animation-fill-mode: both; }

g#top-circle-words path:nth-child(1) { -webkit-animation-delay: 50ms }
g#top-circle-words path:nth-child(2) { -webkit-animation-delay: 100ms }
g#top-circle-words path:nth-child(3) { -webkit-animation-delay: 150ms }
g#top-circle-words path:nth-child(4) { -webkit-animation-delay: 200ms }
g#top-circle-words path:nth-child(5) { -webkit-animation-delay: 250ms }
g#top-circle-words path:nth-child(6) { -webkit-animation-delay: 300ms }
g#top-circle-words path:nth-child(7) { -webkit-animation-delay: 350ms }
g#top-circle-words path:nth-child(8) { -webkit-animation-delay: 400ms }
g#top-circle-words path:nth-child(9) { -webkit-animation-delay: 450ms }
g#top-circle-words path:nth-child(10) { -webkit-animation-delay: 500ms }

g#bot-circle-dashes path:nth-child(1) {-webkit-animation-delay: 550ms }
g#bot-circle-dashes path:nth-child(2) {-webkit-animation-delay: 600ms }
g#bot-circle-dashes path:nth-child(3) {-webkit-animation-delay: 650ms }
g#bot-circle-dashes path:nth-child(4) {-webkit-animation-delay: 700ms }
g#bot-circle-dashes path:nth-child(5) {-webkit-animation-delay: 750ms }
g#bot-circle-dashes path:nth-child(6) {-webkit-animation-delay: 800ms }
g#bot-circle-dashes path:nth-child(7) {-webkit-animation-delay: 850ms }
g#bot-circle-dashes path:nth-child(8) {-webkit-animation-delay: 900ms }
g#bot-circle-dashes path:nth-child(9) {-webkit-animation-delay: 1s }
g#bot-circle-dashes path:nth-child(10) {-webkit-animation-delay: 1.1s }
g#bot-circle-dashes path:nth-child(11) {-webkit-animation-delay: 1.2s }

g#middle-words {-webkit-animation-delay: 300ms; -webkit-animation-duration: 2s}

JS - useing .each(); JS - 使用.each();

$("g#top-circle-words path, g#bot-circle-dashes path").each(function(index) {
    $(this).delay(20*index).animate({opacity: 1}, 50);
});

$("g#middle-words").delay(50).animate({opacity: 1}, 500);

So if you take the above code, it should work, it's the control of it that I cannot get right? 所以,如果你采用上面的代码,它应该工作,它是它的控制,我不能正确吗? You can see with the CSS, that also works if you add the .animIn class manually to all the elements you want to animate in without using JQ. 你可以看到CSS,如果你手动将.animIn类添加到你想要动画的所有元素而不使用JQ,它也可以工作。

I did find another post on here where the OP was having a similar issue (kinda) as me and I tried to adapt the code that was marked correct but could not get that working either? 我确实找到了另一篇文章,其中OP与我有类似的问题(有点),我试图调整标记正确的代码,但也无法使其工作?

$(function() {
    var prevRange = -1;
    var range = -1;

    $(document).on('scroll', function() {
        var top = $(document).scrollTop();      
        if (top >= 2200 && top < 2401) {
            range = Math.floor(top/10)-220;
        } else {
            range = -1;
        }

        if(range != prevRange) {
            prevRange = range;
            var leftPx = (826 - range*5) + "px";
            $('path').stop().animate({left: leftPx}, 300, "easeOutQuad" );
        }
    });
}); 

Also this is something I wrote but I could see this being a pain to work with if I used multiple IF statements: 这也是我写的东西,但如果我使用多个IF语句,我可以看到这很麻烦:

// $(document).ready(function() {
//  $(window).scroll(function() {
//      if ($(this).scrollTop() > 100){
//          $('g#top-circle-words path:nth-child(1)').css( { 'opacity': '.5' } );
//      }
//      else {
//          $('path').css({
//              'opacity': '.9',
//              "border": "0"
//          });
//      }
//      console.log($(document).scrollTop());
//  });
// });

Can anyone please help me with this - been doing my brain in - apologies as I'm still learning JS and JQ so if someone can advise me the right direction to take or provide some insight with explainantion I would really appreciate it. 任何人都可以帮助我这个 - 一直在做我的大脑 - 道歉,因为我还在学习JS和JQ,所以如果有人可以建议我采取正确的方向或提供解释的一些见解我会非常感激。

I'd recommend using ScrollMagic and potentially GSAP if you need. 如果需要,我建议使用ScrollMagicGSAP

This should be the right setup, but may need to be tweaked depending on your exact SVG: 这应该是正确的设置,但可能需要根据您的确切SVG进行调整:

var tween = TweenMax.fromTo("path", 1, { opacity: 0 }, { opacity: 1 });
var scene = new ScrollMagic.Scene({triggerElement: "#mySvg" })
                .setTween(tween)
                .addIndicators({name: "tween css class"}) // add indicators (requires plugin)
                .addTo(controller);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM