Mootools - один объект Fx.Morph для разных эффектов? Также Morph onComplete

У меня проблемы с объектом Mootools Fx.Morph. Я ожидал, что смогу использовать один и тот же объект несколько раз для создания разных эффектов. Я хотел бы переключить эффект на один div. Но мой эффект срабатывает только в первый раз. Есть ли волшебники Fx.Morph, которые могли бы посоветовать?

это мой класс

    var F = new Class({

    Implements: [Options, Events],

    myFX: null,

    dDiv: null,

    options: {
        container: null,
        width: '250px',
        background: '#ccc'
    },

    initialize: function(options) {
        this.setOptions(options);
        this.addDemoDiv();
    },

    addDemoDiv: function() {
        var dDiv = new Element('div', {
            'class': 'myClass',
            html: 'Click me!',
            styles: {
                padding: '20px',
                border: '1px solid #999',
                width: this.options.width,
                background: this.options.background
            },
            events: {
                click:  this.animate.bind(this)
            }
        });

        if (!this.container) {
            this.dDiv = dDiv.inject(document.body);
        } else {
            this.dDiv = dDiv.inject(this.container);
        }

        this.myFx = new Fx.Morph(dDiv);
    },

    animate: function(e) {
        this.dDiv.set('html', 'Hello world');
        this.myFx.start({
            height: 200,
            width: 500,
            link: 'cancel',
            onComplete: function(){
                this.dDiv.removeEvent('click', this.animate);
                this.dDiv.addEvent('click', this.deanimate.bind(this));
            }.bind(this)
        });
    },

    deanimate: function(e) {
        this.dDiv.set('html', 'Click me!');
        this.myFx.start({
            height: 20,
            width: 250,
            link: 'cancel',
            onComplete: function() {
                this.dDiv.removeEvent('click', this.deanimate);
                this.dDiv.addEvent('click', this.animate.bind(this));       
            }.bind(this)
        });
    }

});

window.addEvent('domready', function() {

    var item = new F({cntainer: 'container', background: '#ddd', width: '250px'});

});

Я пробовал довольно много вещей, в том числе отказался от свойства Fx.Morph и просто вызывал .morph в div с каждым щелчком мыши. Это, казалось, вызывало ужасные проблемы с браузером, возможно, потому, что он создавал новый объект Morph с каждым щелчком и утечкой памяти.

Метод deanimate() определенно вызывается, потому что this.dDiv.set('html', 'Click me!'); работает. Но div не сжимается. Я пробовал применять другие эффекты, например цвет фона, но они тоже игнорируются.

Означает ли это, что объект Fx.Morph уничтожается после запуска start()?

Обработчик onComplete для Fx.Morph также ведет себя не так, как вы ожидаете. Когда я помещаю console.log в onComplete метода animate(), сообщение журнала отображается задолго до завершения анимации. Итак, onComplete только после завершения синтаксического анализа скрипта?

Или это только я лох? Любые указатели с благодарностью получены!

======================

Добавлено позже

Я смог обойти эту проблему, потеряв объект Fx.Morph и анимировав его с помощью .morph и переключаемой переменной, например

    animate: function(e) {
        if (!this.anim) {
            this.dDiv.set('html', 'Hello world');
            this.dDiv.morph({
                background: '#666',
                width: 500,
                height: 250
            });
            this.anim = true;
        } else {
            this.dDiv.set('html', 'Click me!');
            this.dDiv.morph({
                background: '#eee',
                width: 250,
                height: 100
            });
            this.anim = false;
        }
    }

Но если кто-нибудь может пролить свет на то, почему первая версия не работала, я был бы очень признателен!


person And Finally    schedule 29.03.2011    source источник


Ответы (1)


это ошибка в привязке и removeEvent.

this.animate.bind(this) возвращает функцию, НЕ совпадающую с this.animate, с которой вы сравниваете при удаленииEvent.

если вы связываете обратные вызовы событий, которые вам нужно удалить, вы должны сохранить их: http://jsfiddle.net/yLhHG/ (неполный, но он сначала сжимается. читайте больше:

в основном:

this.boundEvents = {
    click: this.animate.bind(this)
};

...

this.dDiv.removeEvent('click', this.boundEvents.click);

or:

this.dDiv.addEvent('click', this.boundEvent = this.animate.bind(this));

...

this.dDiv.removeEvent("click", this.boundEvent);

и наконец:

вы можете полностью переписать это, чтобы иметь один метод, но передавать другой объект. обновит его через мгновение.

там: http://jsfiddle.net/yLhHG/1/

var F = new Class({

    Implements: [Options, Events],

    myFX: null,

    dDiv: null,

    options: {
        container: null,
        width: '250px',
        background: '#ccc',
        fx: {
            animate: {
                props: {
                    height: 200,
                    width: 500
                },
                html: "hello world"
            },
            deanimate: {
                props: {
                    height: 20,
                    width: 250
                },
                html: "bye world"
            }
        }
    },

    initialize: function(options) {
        this.setOptions(options);
        this.container = this.options.container || document.body;
        this.addDemoDiv();
    },

    addDemoDiv: function() {
        this.element =  new Element('div', {
            'class': 'myClass',
            html: 'Click me!',
            styles: {
                padding: '20px',
                border: '1px solid #999',
                width: this.options.width,
                background: this.options.background
            },
            events: {
                click: this.animate.bind(this)
            },
            morph: {
                link: "cancel",
                onComplete: function() {

                }.bind(this),
                onStart: function() {
                    this.element.set("html", this.options.fx[this.action].html);
                }.bind(this),
                onCancel: function() {
                   //
                }
            }
        }).inject(this.container);

    },

    animate: function(e) {
        this.action = this.action == "animate" ? "deanimate" : "animate";
        this.element.morph(this.options.fx[this.action].props);
    }
});

new F({
    cntainer: 'container',
    background: '#ddd',
    width: '250px'
});
person Dimitar Christoff    schedule 29.03.2011
comment
Ого, ты герой! Большое спасибо Димитар. Это очень великодушно с твоей стороны. - person And Finally; 30.03.2011
comment
не беспокойтесь, мне нравится работать с mootools для развлечения, когда мне не приходится делать это в рамках моей повседневной работы :) - person Dimitar Christoff; 30.03.2011
comment
fyrye сделал то же самое на форуме Mootools и опубликовал пару альтернативных решений - см. http://www.mooforum.net/help-f26/can-use-the-same-morph-object-несколькораз-t4419.html#p16010 - person And Finally; 30.03.2011