FabricJS带有pageSnap的奇怪线条动画

时间:2016-09-07 14:56:57

标签: javascript jquery animation fabricjs

我正在使用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 个答案:

答案 0 :(得分:1)

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

这适用于JSFiddle容器。

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

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