Визуальные эффекты иконок (глифов)

Чтобы привлечь внимание пользователей к некоторым событиям, мы можем изменить визуальные свойства иконок, например — цвет или цвет фона. Мы также можем анимировать значок, я не фанат анимации, но иногда это бывает необходимо. В данном примере я покажу вам, как сделать анимацию на примере обычной Ext.button.Button. Все эффекты могут накладываться друг на друга, то есть иконка кнопки может показывать и биение и вращаться одновременно.

Все визуальные эффекты создаются миксинами. Мы должны быть особенно осторожны, что бы не переопределить существующие методы.

Биение
Вращение
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Ext.define('app.ux.button.animation.beating.Mixin', {
extend: 'Ext.Mixin',
glyphBeatingTaskRunner: false,
glyphBeatingTask: false,
glyphBeatingTaskRunnerInterval: 100,
startBeating: function () {
var me = this;
if(!this.glyphBeatingTaskRunner) {
this.glyphBeatingTaskRunner = new Ext.util.TaskRunner();
}
if (!this.glyphBeatingTask) {
this.beatingSizeMax = this.btnIconEl.getWidth();
this.glyphSize = this.beatingSizeMin = this.beatingSizeMax * 0.4;
this.beatingSizeStep = (this.beatingSizeMax - this.beatingSizeMin) * 0.1;
}
this.glyphBeatingTask = this.glyphBeatingTaskRunner.start({
run: function () {
me.updateGlyphSize.call(me);
},
interval: this.glyphBeatingTaskRunnerInterval
});
return this;
},
stopBeating: function () {
if (this.glyphBeatingTask) {
this.glyphBeatingTaskRunner.stop(
this.glyphBeatingTask,
true
);
}
return this;
},
updateGlyphSize: function () {
this.glyphSize = this.glyphSize + this.beatingSizeStep;
if (this.glyphSize > this.beatingSizeMax || this.glyphSize < this.beatingSizeMin) {
this.beatingSizeStep = this.beatingSizeStep * -1;
}
this.setGlyphSize(Math.floor(this.glyphSize));
},
setGlyphSize: function(glyphSize) {
glyphSize = Ext.isNumeric(glyphSize) ? glyphSize: null;
this.btnIconEl.setStyle('font-size', glyphSize + 'px');
return this;
}
});
Ext.define('app.ux.button.animation.beating.Mixin', { extend: 'Ext.Mixin', glyphBeatingTaskRunner: false, glyphBeatingTask: false, glyphBeatingTaskRunnerInterval: 100, startBeating: function () { var me = this; if(!this.glyphBeatingTaskRunner) { this.glyphBeatingTaskRunner = new Ext.util.TaskRunner(); } if (!this.glyphBeatingTask) { this.beatingSizeMax = this.btnIconEl.getWidth(); this.glyphSize = this.beatingSizeMin = this.beatingSizeMax * 0.4; this.beatingSizeStep = (this.beatingSizeMax - this.beatingSizeMin) * 0.1; } this.glyphBeatingTask = this.glyphBeatingTaskRunner.start({ run: function () { me.updateGlyphSize.call(me); }, interval: this.glyphBeatingTaskRunnerInterval }); return this; }, stopBeating: function () { if (this.glyphBeatingTask) { this.glyphBeatingTaskRunner.stop( this.glyphBeatingTask, true ); } return this; }, updateGlyphSize: function () { this.glyphSize = this.glyphSize + this.beatingSizeStep; if (this.glyphSize > this.beatingSizeMax || this.glyphSize < this.beatingSizeMin) { this.beatingSizeStep = this.beatingSizeStep * -1; } this.setGlyphSize(Math.floor(this.glyphSize)); }, setGlyphSize: function(glyphSize) { glyphSize = Ext.isNumeric(glyphSize) ? glyphSize: null; this.btnIconEl.setStyle('font-size', glyphSize + 'px'); return this; } });
Ext.define('app.ux.button.animation.rotate.Mixin', {
extend: 'Ext.Mixin',
glyphRotateTaskRunner: false,
glyphRotateTask: false,
glyphRotateTaskRunnerInterval: 100,
glyphRotateDeg: 0,
glyphRotateStep: 10,
startRotate: function () {
var me = this;
if (!this.glyphRotateTaskRunner) {
this.glyphRotateTaskRunner = new Ext.util.TaskRunner();
}
this.glyphRotateTask = this.glyphRotateTaskRunner.start({
run: function () {
me.rotateGlyph.call(me);
},
interval: this.glyphRotateTaskRunnerInterval
});
return this;
},
stopRotate: function () {
if (this.glyphRotateTask) {
this.glyphRotateTaskRunner.stop(
this.glyphRotateTask,
true
);
}
return this;
},
rotateGlyph: function () {
this.glyphRotateDeg = this.glyphRotateDeg + this.glyphRotateStep;
if (this.glyphRotateDeg > 360) {
this.glyphRotateDeg = 0;
}
this.setGlyphRotationDeg(Math.floor(this.glyphRotateDeg));
},
setGlyphRotationDeg: function(glyphRotateDeg) {
glyphRotateDeg = Ext.isNumeric(glyphRotateDeg) ? glyphRotateDeg: null;
this.btnIconEl.setStyle('-webkit-transform', 'rotate(' + glyphRotateDeg + 'deg)');
return this;
}
});
Ext.define('app.ux.button.animation.rotate.Mixin', { extend: 'Ext.Mixin', glyphRotateTaskRunner: false, glyphRotateTask: false, glyphRotateTaskRunnerInterval: 100, glyphRotateDeg: 0, glyphRotateStep: 10, startRotate: function () { var me = this; if (!this.glyphRotateTaskRunner) { this.glyphRotateTaskRunner = new Ext.util.TaskRunner(); } this.glyphRotateTask = this.glyphRotateTaskRunner.start({ run: function () { me.rotateGlyph.call(me); }, interval: this.glyphRotateTaskRunnerInterval }); return this; }, stopRotate: function () { if (this.glyphRotateTask) { this.glyphRotateTaskRunner.stop( this.glyphRotateTask, true ); } return this; }, rotateGlyph: function () { this.glyphRotateDeg = this.glyphRotateDeg + this.glyphRotateStep; if (this.glyphRotateDeg > 360) { this.glyphRotateDeg = 0; } this.setGlyphRotationDeg(Math.floor(this.glyphRotateDeg)); }, setGlyphRotationDeg: function(glyphRotateDeg) { glyphRotateDeg = Ext.isNumeric(glyphRotateDeg) ? glyphRotateDeg: null; this.btnIconEl.setStyle('-webkit-transform', 'rotate(' + glyphRotateDeg + 'deg)'); return this; } });
Ext.define('app.ux.button.animation.beating.Mixin', {
    extend: 'Ext.Mixin',

    glyphBeatingTaskRunner: false,
    glyphBeatingTask: false,
    glyphBeatingTaskRunnerInterval: 100,

    startBeating: function () {
        var me = this;
        if(!this.glyphBeatingTaskRunner) {
            this.glyphBeatingTaskRunner = new Ext.util.TaskRunner();
        }
        if (!this.glyphBeatingTask) {
            this.beatingSizeMax = this.btnIconEl.getWidth();
            this.glyphSize = this.beatingSizeMin = this.beatingSizeMax * 0.4;
            this.beatingSizeStep = (this.beatingSizeMax - this.beatingSizeMin) * 0.1;
        }

        this.glyphBeatingTask = this.glyphBeatingTaskRunner.start({
            run: function () {
                me.updateGlyphSize.call(me);
            },
            interval: this.glyphBeatingTaskRunnerInterval
        });
        return this;
    },

    stopBeating: function () {
        if (this.glyphBeatingTask) {
            this.glyphBeatingTaskRunner.stop(
                this.glyphBeatingTask,
                true
            );
        }
        return this;
    },

    updateGlyphSize: function () {
        this.glyphSize = this.glyphSize + this.beatingSizeStep;
        if (this.glyphSize > this.beatingSizeMax || this.glyphSize < this.beatingSizeMin) {
            this.beatingSizeStep = this.beatingSizeStep * -1;
        }
        this.setGlyphSize(Math.floor(this.glyphSize));
    },

    setGlyphSize: function(glyphSize) {
        glyphSize = Ext.isNumeric(glyphSize) ? glyphSize: null;
        this.btnIconEl.setStyle('font-size', glyphSize + 'px');
        return this;
    }
});
Ext.define('app.ux.button.animation.rotate.Mixin', {
    extend: 'Ext.Mixin',

    glyphRotateTaskRunner: false,
    glyphRotateTask: false,
    glyphRotateTaskRunnerInterval: 100,
    glyphRotateDeg: 0,
    glyphRotateStep: 10,

    startRotate: function () {
        var me = this;
        if (!this.glyphRotateTaskRunner) {
            this.glyphRotateTaskRunner = new Ext.util.TaskRunner();
        }
        this.glyphRotateTask = this.glyphRotateTaskRunner.start({
            run: function () {
                me.rotateGlyph.call(me);
            },
            interval: this.glyphRotateTaskRunnerInterval
        });
        return this;
    },

    stopRotate: function () {
        if (this.glyphRotateTask) {
            this.glyphRotateTaskRunner.stop(
                this.glyphRotateTask,
                true
            );
        }
        return this;
    },

    rotateGlyph: function () {
        this.glyphRotateDeg = this.glyphRotateDeg + this.glyphRotateStep;
        if (this.glyphRotateDeg > 360) {
            this.glyphRotateDeg = 0;
        }
        this.setGlyphRotationDeg(Math.floor(this.glyphRotateDeg));
    },

    setGlyphRotationDeg: function(glyphRotateDeg) {
        glyphRotateDeg = Ext.isNumeric(glyphRotateDeg) ? glyphRotateDeg: null;
        this.btnIconEl.setStyle('-webkit-transform', 'rotate(' + glyphRotateDeg + 'deg)');
        return this;
    }
});

Цвета иконок и цвета фона реализованы в виде расширения класса. Здесь я переопределяю iconTpl из Ext.button.Button

ExtendedButton
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Ext.define('app.ux.button.Button', {
extend: 'Ext.button.Button',
mixins: {
beating: 'app.ux.button.animation.beating.Mixin',
rotate: 'app.ux.button.animation.rotate.Mixin'
},
glyphColor: false,
glyphBackgroundColor: false,
glyphSize: false,
iconTpl:
'<span id="{id}-btnIconEl" data-ref="btnIconEl" role="presentation" unselectable="on" class="{baseIconCls} ' +
'{baseIconCls}-{ui} {iconCls} {glyphCls}{childElCls}" style="' +
'<tpl if="iconUrl">background-image:url({iconUrl});</tpl>' +
'<tpl if="glyph">' +
'<tpl if="glyphFontFamily">' +
'font-family:{glyphFontFamily};' +
'<tpl if="glyphColor">' +
' color: {glyphColor};' +
'</tpl>' +
'<tpl if="glyphBackgroundColor">' +
' background-color: {glyphBackgroundColor};' +
'</tpl>' +
'<tpl if="glyphSize">' +
' font-size: {glyphSize};' +
'</tpl>' +
'</tpl>' +
'">{glyph}' +
'<tpl else>' +
'">' +
'</tpl>' +
'</span>',
initComponent: function() {
this.callParent();
},
setGlyphColor: function(rgbColor) {
this.glyphColor = this.isValidRgb(rgbColor) ? rgbColor: null;
this.btnIconEl.setStyle('color', this.glyphColor);
return this;
},
getGlyphColor: function() {
return this.glyphColor;
},
setGlyphBackgroundColor: function(rgbColor) {
this.glyphBackgroundColor = this.isValidRgb(rgbColor) ? rgbColor: null;
this.btnIconEl.setStyle('background-color', this.glyphBackgroundColor);
return this;
},
getGlyphBackgroundColor: function() {
return this.glyphBackgroundColor;
},
getGlyphSize: function() {
return this.glyphSize;
},
getTemplateArgs: function() {
var templateArgs = this.callParent();
templateArgs.glyphColor = this.glyphColor;
templateArgs.glyphBackgroundColor = this.glyphBackgroundColor;
templateArgs.glyphSize = this.glyphSize;
return templateArgs;
},
isValidRgb: function(rgb) {
var isValid = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(rgb);
return isValid;
}
});
Ext.define('app.ux.button.Button', { extend: 'Ext.button.Button', mixins: { beating: 'app.ux.button.animation.beating.Mixin', rotate: 'app.ux.button.animation.rotate.Mixin' }, glyphColor: false, glyphBackgroundColor: false, glyphSize: false, iconTpl: '<span id="{id}-btnIconEl" data-ref="btnIconEl" role="presentation" unselectable="on" class="{baseIconCls} ' + '{baseIconCls}-{ui} {iconCls} {glyphCls}{childElCls}" style="' + '<tpl if="iconUrl">background-image:url({iconUrl});</tpl>' + '<tpl if="glyph">' + '<tpl if="glyphFontFamily">' + 'font-family:{glyphFontFamily};' + '<tpl if="glyphColor">' + ' color: {glyphColor};' + '</tpl>' + '<tpl if="glyphBackgroundColor">' + ' background-color: {glyphBackgroundColor};' + '</tpl>' + '<tpl if="glyphSize">' + ' font-size: {glyphSize};' + '</tpl>' + '</tpl>' + '">{glyph}' + '<tpl else>' + '">' + '</tpl>' + '</span>', initComponent: function() { this.callParent(); }, setGlyphColor: function(rgbColor) { this.glyphColor = this.isValidRgb(rgbColor) ? rgbColor: null; this.btnIconEl.setStyle('color', this.glyphColor); return this; }, getGlyphColor: function() { return this.glyphColor; }, setGlyphBackgroundColor: function(rgbColor) { this.glyphBackgroundColor = this.isValidRgb(rgbColor) ? rgbColor: null; this.btnIconEl.setStyle('background-color', this.glyphBackgroundColor); return this; }, getGlyphBackgroundColor: function() { return this.glyphBackgroundColor; }, getGlyphSize: function() { return this.glyphSize; }, getTemplateArgs: function() { var templateArgs = this.callParent(); templateArgs.glyphColor = this.glyphColor; templateArgs.glyphBackgroundColor = this.glyphBackgroundColor; templateArgs.glyphSize = this.glyphSize; return templateArgs; }, isValidRgb: function(rgb) { var isValid = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(rgb); return isValid; } });
Ext.define('app.ux.button.Button', {
    extend: 'Ext.button.Button',

    mixins: {
        beating: 'app.ux.button.animation.beating.Mixin',
        rotate: 'app.ux.button.animation.rotate.Mixin'
    },

    glyphColor: false,
    glyphBackgroundColor: false,
    glyphSize: false,

    iconTpl:
        '<span id="{id}-btnIconEl" data-ref="btnIconEl" role="presentation" unselectable="on" class="{baseIconCls} ' +
                '{baseIconCls}-{ui} {iconCls} {glyphCls}{childElCls}" style="' +
            '<tpl if="iconUrl">background-image:url({iconUrl});</tpl>' +
            '<tpl if="glyph">' +
                '<tpl if="glyphFontFamily">' +
                    'font-family:{glyphFontFamily};' +
                    '<tpl if="glyphColor">' +
                        ' color: {glyphColor};' +
                    '</tpl>' +
                    '<tpl if="glyphBackgroundColor">' +
                        ' background-color: {glyphBackgroundColor};' +
                    '</tpl>' +
                    '<tpl if="glyphSize">' +
                        ' font-size: {glyphSize};' +
                    '</tpl>' +
                '</tpl>' +
                '">{glyph}' +
            '<tpl else>' +
                '">' +
            '</tpl>' +
        '</span>',

    initComponent: function() {
        this.callParent();
    },

    setGlyphColor: function(rgbColor) {
        this.glyphColor = this.isValidRgb(rgbColor) ? rgbColor: null;
        this.btnIconEl.setStyle('color', this.glyphColor);
        return this;
    },

    getGlyphColor: function() {
        return this.glyphColor;
    },

    setGlyphBackgroundColor: function(rgbColor) {
        this.glyphBackgroundColor = this.isValidRgb(rgbColor) ? rgbColor: null;
        this.btnIconEl.setStyle('background-color', this.glyphBackgroundColor);
        return this;
    },

    getGlyphBackgroundColor: function() {
        return this.glyphBackgroundColor;
    },

    getGlyphSize: function() {
        return this.glyphSize;
    },

    getTemplateArgs: function() {
        var templateArgs = this.callParent();
        templateArgs.glyphColor = this.glyphColor;
        templateArgs.glyphBackgroundColor = this.glyphBackgroundColor;
        templateArgs.glyphSize = this.glyphSize;
        return templateArgs;
    },

    isValidRgb: function(rgb) {
        var isValid  = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(rgb);
        return isValid;
    }
});

 
Fiddle:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *