如何取消/取消多个Fx.Morphs

时间:2014-05-12 19:53:16

标签: javascript mootools

我做了一个简单的Mootools动画,它使一个元素在一个圆形路径上移动,使用两个独立的Fx.Morph变量。我的问题是我需要能够取消动画,我不能我的生活弄清楚如何处理取消两个变形而不直接调用它们或将它们保存为全局变量。

以下是我使用的代码的简化版本:http://jsfiddle.net/4vBj9/2/

我尝试过使用$(img).get('morph').cancel();,但这似乎不适用于具有多个Fx的元素。

编辑:发生在我身上,我忘了提到取消动画的事件可能不会发生在它实例化的同一范围内,所以我无法真正调用处理变形的变量

2 个答案:

答案 0 :(得分:2)

ERM。您可以使用本地元素存储。默认情况下,.get('morph')会为您检索第一个fx实例,但由于您每次都有多个/创建一个新实例并且不使用.get/.set,您最好做一些像相反:

;(function(){
    var img = document.id('img');

    $('add').addEvent('click', function() {
        // try to get from storage, set empty array as default
        var fxs = img.retrieve('fxs', []);
        // if empty, make instances, store into array
        if (!fxs.length) {
                [].push.apply(fxs, [
                new Fx.Morph(img, {
                    duration: 1500,
                    transition: Fx.Transitions.linear.easeOut
                }),
                new Fx.Morph(img, {
                    duration: 750,
                    transition: Fx.Transitions.easeOutCirc
                })
            ]);
            // save it as one off
            img.store('fxs', fxs);
        }
        // reference as array elements
        fxs[0].start({
            top: 175
        });
        fxs[1].start({
            left: 175
        }).chain(function() {
            // this === fx instance. DRY
            this.options.transition = Fx.Transitions.easeInCirc;
            this.options.duration = 764;
            this.start({
                left: 10
            });
        });
    });

    $('rem').addEvent('click', function() {
       img.removeProperty('style');
    });

}());

很久以后,完全独立的代码:

;(function(){ // new scope
    $('box').addEvent('click', function(){
        var fxs = $('img').retrieve('fxs');
        fxs && fxs.invoke('stop');
    });
}());

这实现了代码的分离和对变量的依赖,并使其成为DRY和封装 - 它还重新使用相同的fx实例,因此在首次启动后运行起来会更快。

这是你的事。 http://jsfiddle.net/4vBj9/6/

如果您正在进行需要在javascript中流畅的复杂和嵌套动画,请考虑https://github.com/julianshapiro/velocity - 它是制作动画的最快方式,包括CSS过渡(查看基准测试) )。哦 - 也可以做css3道具,mootools不能。

答案 1 :(得分:1)

由于您正在尝试基于曲线创建动画,我将向您展示更优雅的方式来实现这一目标。它基于扩展Fx类并添加对Bezier曲线的支持。

贝塞尔曲线

Bezier curves用于计算机图形学计算平滑曲线和描述路径。这里的一个优点是只需要一个FX实例,这将提高性能,而且,您可以创建基于任何类型的曲线的动画。

Base Fx Class

第一部分是extend base Fx class(所有Fx实例的基类),因此可以完全控制动画。我们现在可以使用在动画的每一步上触发的set()函数来手动计算和设置效果所需的值。这里最重要的部分是get_points()函数,其中计算了动画元素的当前位置。使用的公式是三次曲线。

    Fx.Bezier = new Class({

        Extends: Fx,

        initialize: function ( element, options ) {
            this.element = document.id(element);
            this.parent(options);
        },

        set: function ( now ) {
            var pos = this.get_points( now );
            this.element.setStyles( { 'left': pos.x, 'top': pos.y } );
            return this;
        },  

        start: function( from, to ) {
            return this.parent( from, to );
        },

        get_points: function( t ) {
            var p = this.options.points;
            var t1 = 1-t;
            return {
                x: p.x0*t*t*t + p.x1*3*t*t*t1 + p.x2*3*t*t1*t1 + p.x3*t1*t1*t1,
                y: p.y0*t*t*t + p.y1*3*t*t*t1 + p.y2*3*t*t1*t1 + p.y3*t1*t1*t1
            };
        }

    }); 

Element.Properties

为了能够像Fx.Beziertween一样将morph设置为动态参数,我们必须在Element.Properties对象中创建元素属性。

    Element.Properties.bezier = {

        set: function( options ){
            this.get( 'bezier' ).cancel().setOptions( options );
            return this;
        },

        get: function(){
            var bezier = this.retrieve( 'bezier' );
            if ( !bezier ){
                bezier = new Fx.Bezier( this, {link: 'cancel'} );
                this.store( 'bezier', bezier );
            }
            return bezier;
        }

    };

用法

现在我们可以使用自定义FX,存储在变量中,或存储在元素存储中。 这是一个如何存储在变量中的示例,还可以查看小提琴,其中示例了如何使用元素存储。

var myBezier = new Fx.Bezier( 'img' , { 
    points: { x0: 10, y0: 10, x1: 250, y1: 0, x2: 250, y2: 250, x3: 100, y3: 250 },
    duration: 1500, 
    transition: Fx.Transitions.Expo.easeIn
});

myBezier
    .start( 1, 0 )
    .chain( function() {
        var points = this.options.points;

        this.setOptions({
            points: { x0: points.x3, y0: points.y3, x1: (points.x3-points.x2)+points.x3, y1: points.y2, x2: 0, y2: 0, x3: 150, y3: 150 },
            transition: Fx.Transitions.Expo.easeOut
        }).start( 1, 0 );
    });

小提琴:http://jsfiddle.net/m5ErG/

关于此主题的一些链接: