canvas 水波效果
看到某些工具上有水波效果,想能不能用canvas实现呢,于是就google了一下还真有在这里与大家分享吧!
这里有一篇教程,介绍实现原理的,水波纹原理
下面是js实现的源代码
var ripple = (function(img_src, container){ var img = new Image, img_data, delay = 30, width, height, half_width, half_height, riprad = 5, oldind, newind, mapind, size, ripplemap = [], last_map = [], ripple, ripple_data, texture, texture_data, is_running = true, is_disturbed = false, timer_id, canvas = document.createElement('canvas'), /** @type {CanvasRenderingContext2D} */ ctx; function init(){ width = img.width; height = img.height; half_width = width >> 1; half_height = height >> 1; size = width * (height + 2) * 2; canvas.width = width; canvas.height = height; oldind = width; newind = width * (height + 3); /** @type {CanvasRenderingContext2D} */ ctx = canvas.getContext('2d'); container.appendChild(canvas); ctx.drawImage(img, 0, 0, width, height); for (var i = 0; i < size; i++) { last_map[i] = ripplemap[i] = 0; } texture = ctx.getImageData(0, 0, width, height); texture_data = texture.data; ripple = ctx.getImageData(0, 0, width, height); ripple_data = ripple.data; canvas.addEventListener('mousemove', function(/* Event */evt){ disturb(evt.offsetX || evt.layerX, evt.offsetY || evt.layerY); }, false); start(); disturb(180,130); } function stop(){ if (timer_id) clearInterval(timer_id); } function start(){ stop(); timer_id = setInterval(run, delay); } function run(){ if (is_disturbed) { newframe(width, height); ctx.putImageData(ripple, 0, 0); }else{ } } function disturb(dx, dy){ dx <<= 0; dy <<= 0; is_disturbed = true; for (var j = dy - riprad; j < dy + riprad; j++) { for (var k = dx - riprad; k < dx + riprad; k++) { ripplemap[oldind + (j * width) + k] += 4048; } } //newframe(width, height); //ctx.putImageData(ripple, 0, 0); } function newframe(){ var i, a, b, data, cur_pixel, new_pixel, old_data; i = oldind; oldind = newind; newind = i; i = 0; mapind = oldind; var _width = width, _height = height, _ripplemap = ripplemap, _mapind = mapind, _newind = newind, _last_map = last_map, _rd = ripple.data, _td = texture.data, _half_width = half_width, _half_height = half_height, _is_disturbed = false; for (var y = 0; y < _height; y++) { for (var x = 0; x < _width; x++) { data = (_ripplemap[_mapind - _width] + _ripplemap[_mapind + _width] + _ripplemap[_mapind - 1] + _ripplemap[_mapind + 1]) >> 1; data -= _ripplemap[_newind + i]; data -= data >> 5; _ripplemap[_newind + i] = data; //where data=0 then still, where data>0 then wave data = 1024 - data; old_data = _last_map[i]; _last_map[i] = data; if (old_data != data) { //offsets _is_disturbed = true; a = (((x - _half_width) * data / 1024) << 0) + _half_width; b = (((y - _half_height) * data / 1024) << 0) + _half_height; //bounds check if (a >= _width) a = _width - 1; if (a < 0) a = 0; if (b >= _height) b = _height - 1; if (b < 0) b = 0; new_pixel = (a + (b * _width)) * 4; cur_pixel = i * 4; _rd[cur_pixel] = _td[new_pixel]; _rd[cur_pixel + 1] = _td[new_pixel + 1]; _rd[cur_pixel + 2] = _td[new_pixel + 2]; //_rd[cur_pixel + 3] = _td[new_pixel + 3]; } ++_mapind; ++i; } } mapind = _mapind; is_disturbed = _is_disturbed; } img.onload = init; img.src = img_src; return { start: start, stop: stop, disturb: disturb } });
与大家分享了!!!
分割线---------------------------------------------------------------------------------