带有pageSnap的FabricJS奇怪的线条动画

Posted

技术标签:

【中文标题】带有pageSnap的FabricJS奇怪的线条动画【英文标题】:FabricJS weird line animation with pageSnap 【发布时间】:2017-01-15 08:13:33 【问题描述】:

我正在使用 FabricJS 创建 JS 线条动画并使用 PageSnapJS 创建捕捉部分。但是,线条动画行为是非常随机的。如果您慢慢滚动彩色页面,您会看到红线动画。第 1 到 2 页通常很好,但第 2 到 3 页失败。我的计算不正确吗?如何纠正它?

这是我的代码(JSFiddle 在问题的末尾):

var canvas;
var current_page = 1;
var is_animating = false;
var line_options = 
    stroke: 'red',
    strokeWidth: 3
;
$(document).ready(function() 
    canvas = new fabric.Canvas('line_effect');
    canvas.setHeight($('.indicator').height());
    canvas.setWidth(50);
    canvas.renderAll();
    var section_h = $('.section').height();

    var startPts = [
        x: 48, y: 0,
        x: 48, y: $('.section').height()
    ];
    var endPts = [
        x: 48, y: $('.section').height() * 2,
        x: 48, y: $('.section').height()
    ];

    var line = new fabric.Polyline(startPts, line_options);
    canvas.add(line);

    function animateLine(i, prop, endPts) 
        fabric.util.animate(
            startValue: line.points[i][prop],
            endValue: endPts[i][prop],
            duration: 1000,
            easing: fabric.util.ease.easeInOutCubic,
            onChange: function(value) 
                line.points[i][prop] = value;
                if(i === startPts.length - 1 && prop == 'y') 
                    canvas.renderAll();
                
            ,
            onComplete: function() 
                line.setCoords();
                if(i === startPts.length - 1 && prop == 'y') 
                    even = !even;
                    animateLine(i, prop, endPts);
                
            
        );
    
    function animate(startPage, endPage) 
        if(is_animating) 
            return;
         else if(startPage == endPage) 
            return;
         else if(Math.abs(startPage - endPage) > 1) 
            // Jump to that section immediately.
            console.log('Jump to Page ' + endPage);
            canvas.remove(line);
            if(endPage == 1) 
                line = new fabric.Line([48, section_h * 0, 48, section_h * 1], line_options);
             else if(endPage == 2) 
                line = new fabric.Line([48, section_h * 1, 48, section_h * 2], line_options);
             else if(endPage == 3) 
                line = new fabric.Line([48, section_h * 2, 48, section_h * 3], line_options);
             else if(endPage == 4) 
                line = new fabric.Line([48, section_h * 3, 48, section_h * 4], line_options);
             
            canvas.add(line);
         else 
            is_animating = true;
            if(startPage == 1 && endPage == 2) 
                console.log('Page 1 > 2');
                startPts = [
                    x: 48, y: section_h * 0,
                    x: 48, y: section_h * 1
                ];
                endPts = [
                    x: 48, y: section_h * 2,
                    x: 48, y: section_h * 1
                ];
             else if(startPage == 2 && endPage == 3) 
                console.log('Page 2 > 3');
                startPts = [
                    x: 48, y: section_h * 1,
                    x: 48, y: section_h * 2
                ];
                endPts = [
                    x: 48, y: section_h * 3,
                    x: 48, y: section_h * 2
                ];
             else if(startPage == 3 && endPage == 4) 
                console.log('Page 3 > 4');
                startPts = [
                    x: 48, y: section_h * 2,
                    x: 48, y: section_h * 3
                ];
                endPts = [
                    x: 48, y: section_h * 4,
                    x: 48, y: section_h * 3
                ];
             else if(startPage == 4 && endPage == 3) 
                console.log('Page 4 > 3');
                startPts = [
                    x: 48, y: section_h * 4,
                    x: 48, y: section_h * 3
                ];
                endPts = [
                    x: 48, y: section_h * 2,
                    x: 48, y: section_h * 3
                ];
             else if(startPage == 3 && endPage == 2) 
                console.log('Page 3 > 2');
                startPts = [
                    x: 48, y: section_h * 2,
                    x: 48, y: section_h * 3
                ];
                endPts = [
                    x: 48, y: section_h * 2,
                    x: 48, y: section_h * 1
                ];
             else if(startPage == 2 && endPage == 1) 
                console.log('Page 2 > 1');
                startPts = [
                    x: 48, y: section_h * 2,
                    x: 48, y: section_h * 1
                ];
                endPts = [
                    x: 48, y: section_h * 0,
                    x: 48, y: section_h * 1
                ];
             else 
                console.log('Others: ' + startPage + ' > ' + endPage);
            
            canvas.remove(line);
            line = new fabric.Polyline(startPts, line_options);
            canvas.add(line);
            for(var i = 0, len = startPts.length; i < len; i++) 
                animateLine(i, 'y', even ? endPts : startPts); 
            
            is_animating = false;
        
    

    var even = true;
    $('.contents').panelSnap(
        $menu: false, // the menu DOM object
        onSnapStart: function($target) 
            if($target.data('panel') == 'page2') 
                animate(current_page, 2);
             else if($target.data('panel') == 'page3') 
                animate(current_page, 3);
             else if($target.data('panel') == 'page4') 
                animate(current_page, 4);
             else if($target.data('panel') == 'page1') 
                animate(current_page, 1);
             
        ,
        onSnapFinish: function($target) 
            current_page = parseInt($target.data('panel').replace('page', ''));
            console.log('Current Page: ' + current_page);
        

    );
);

这里是JSFiddle

【问题讨论】:

【参考方案1】:

我已经看到其他框架中的动画在使用相对尺寸时会失败,但在使用绝对尺寸值时会成功。我开始玩你的小提琴,使用一些额外的 js 开始将高度和宽度的值设置为 px 值而不是 % 值,它看起来很有希望。

这适用于 JSFiddle 容器。

$('html, body').css('height':$('.contents').height()+'px','width':$('.contents').width()+'px');
  $('.indicator .section').css('height':$('.contents').height/4+'px');

如果您需要响应式设计,您可以尝试朝这个方向前进。我怀疑你正在做的事情会有几个这样的调整来确定事情。

【讨论】:

谢谢。会朝这个方向努力。我有问题的代码已经修复了&lt;canvas&gt; 的宽度和高度,因为 100% 的高度会使画布内容变得模糊。

以上是关于带有pageSnap的FabricJS奇怪的线条动画的主要内容,如果未能解决你的问题,请参考以下文章

面料JS |滚动或拖动任何对象时显示不需要的线条

FPDI合并PDF文件,出现奇怪的线条

对圆形和线条使用相同的不透明度和颜色,但在画布上显示奇怪的结果[重复]

使用 plotly.express 折线图,线条以奇怪的顺序连接?怎么修? [关闭]

Fabric jsstickman - 以编程方式动画制作肢体并保持所有圆圈和线条之间的关节

谷歌浏览器打开弹窗后出现奇怪的线条,如何避免?