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 } }); |
与大家分享了!!!
分割线---------------------------------------------------------------------------------
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 单线程的Redis速度为什么快?
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库