Several days ago my best friend Alexey Kovyrin asked me to help him to create flashing effect on HTML page. I gave him advice to create this effect using moo.fx library. I wanted to show how to extend it, but I couldn’t keep from creating this effect myself.
moo.fx is a superlightweight, ultratiny, megasmall javascript effects library, written with prototype.js. It’s easily to extend it with custom effect and in this post I will show you how you can do this. In this article I’ll show how to create flashing effect: element’s background will smoothly change from one color to another and go back to first color (maybe several times).
To extend fx.Base you can use following construction:
1 2 3 | fx.Flash = Class.create(); Object.extend(Object.extend(fx.Flash.prototype, fx.Base.prototype), { // ... |
Now we need to decide in which format initial colors will be passed. I think the most simple to user is to pass color values in #RRGGBB format, the most popular format in web-design. We need to parse this format to get separate color’s parts (reg, green and blue), therefor it’s necessary to create function that makes hexadecimal => decimal conversion. To assign background color to the element while flashing reverse function is required.
1 2 3 4 5 6 7 8 9 10 11 12 | hD: "0123456789ABCDEF", d2h: function(d) { var h = this.hD.substr(d & 15, 1); while (d > 15) { d >>= 4; h = this.hD.substr(d & 15, 1) + h; } if (h.length == 1) h = "0" + h; return h; }, h2d: function(h) { return parseInt(h, 16); } |
Now we are ready to develop constructor (method initialize()):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | initialize: function(el, options) { this.el = $(el); var color_from = (options && options.color_from) || "#ffffff"; var color_to = (options && options.color_to) || "#ff0000"; var color_f = this.h2d(color_from.substr(1)); var color_t = this.h2d(color_to.substr(1)); var _options = { red: [color_f >> 16, color_t >> 16], green: [(color_f >> 8) & 255, (color_t >> 8) & 255], blue: [color_f & 255, color_t & 255], count: 1 }; Object.extend(_options, options || {}); if (_options.onComplete) _options.flashOnComplete = _options.onComplete; this.setOptions(_options); } |
This function can accept following options:
- duration – duration in milliseconds of changing color from first to second or vice versa. For example, if you pass count = 3, complete effect execution time will be 3 * 2 * duration (default is 500).
- onComplete – a function that will get called upon effect completion.
- transition – transition type. (default is fx.sinoidal)
- color_from – beginning color (default is #ffffff)
- color_to – ending color (default is #ff0000)
- count – flashes count (default is 1)
Effect dependents on onComplete function therefor this parameters is saved to another options variable flashOnComplete.
Function increase() is called during effect. In this function we can calculate current color based on internal variable this.now:
1 2 3 4 5 6 | increase: function() { var r = this.d2h(this.now * (this.options.red[0] - this.options.red[1]) / 255 + this.options.red[1]); var g = this.d2h(this.now * (this.options.green[0] - this.options.green[1]) / 255 + this.options.green[1]); var b = this.d2h(this.now * (this.options.blue[0] - this.options.blue[1]) / 255 + this.options.blue[1]); this.el.style.backgroundColor = "#" + r + g + b; } |
To call effect function toggle() used. OnComplete is used to repeat effect from ending to beginnig color. It also decrements current count value to make it possible to repeat effect count times.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | toggle: function() { if (this.flashCount == undefined) this.flashCount = this.options.count; this.options.onComplete = this.onComplete.bind(this); this.custom(255, 0); }, onComplete: function() { this.flashCount--; if (this.flashCount == 0) { this.flashCount = undefined; this.options.onComplete = this.options.flashOnComplete; } else this.options.onComplete = this.toggle.bind(this); this.custom(0, 255); } |
Thats all. You can download source file here. Samples are shown below this.
1 | var sample1 = new fx.Flash("sample-area", {color_from:"#ffffe3", color_to:"#007f00", count:3, transition:fx.circ, duration:300}); |
1 | var sample2 = new fx.Flash("sample-area", {color_from:"#ffffe3", color_to:"#7f0000", count:1, duration:600}); |
Огромное спасибо за такое элегантное решение моей проблемы! Как мне показалось, начальство больше оценило этот эффект, чем 3000+ строк кода, которые были написаны в проекте за последние полторы недели :-)
ИМХО, используя script.aculo.us делать такие еффекты еще проще. Там тоже уже есть готовый абстрактный класс Effect расширяя который можно писать свои эффекты. А можно, используя опять-таки инструменты этой библиотеки, делать связки эффектов, использовая лишь базоыве (core) эффекты. Можно получить очень разнообразные вариации.
Вообщем, рекомендую обратить внимание.
Да, script.aculo.us не только про эффекты, поэтому она занимает побольше. Но, можно подключить модули пофайлово, и тогда тоже немного места займет. А можно использовать всю библиотеку и делать вообще кучу всего в “одну строку” :)
hi,
can u send and argument to the onComplete which will perform another function each time?
for exaple:
//javascript
var myFunction;
function AjaxMe(which, what, whatToDo){
new Ajax(which, {postBody: ‘sleep=0’, update: $(what), onComplete: myFunction}).request();}
//html
Toggle me
thanks for your help
amit
Да-да, хотелось бы услышать от автора, что он думает по поводу script.aculo.us.
script.aculo.us – отличная библиотека для использования в больших проектах, сильно завязанных на всяких эффектах. Если разрабатывается маленькое приложение, или большое, но в котором нужно в паре мест добавить симпатичные эффекты – зачем тягать здоровенную библиотеку? :-)
Вообще сейчас moo.fx вырос до mootools, и это уже не просто библиотека с парой эффектов, а реальная альтернатива prototype+script.aculo.us.