canvas用于在网页上绘制图像、动画,可以将其理解为画布,在这个画布上构建想要的效果。
canvas可以绘制动态效果,除了常用的规则动画之外,还可以采用粒子的概念来实现较复杂的动效,本文分别采用普通动效与粒子特效实现了一个简单的时钟。
普通时钟
普通动效即利用canvas的api,实现有规则的图案、动画。
效果
该效果实现比较简单,主要分析一下刻度与指针角度偏移的实现。
绘制刻度
此例为小时刻度的绘制:表盘上共有12个小时,Math.PI为180°,每小时占据30°。
.save()表示保存canvas当前环境的状态,在此基础上进行绘制。绘制完成之后,返回之前保存过的路径状态和属性。
分钟刻度同理,改变角度与样式即可。
// 小时时间刻度 offscreenCanvasCtx.save(); for (var i = 0; i < 12; i++) { offscreenCanvasCtx.beginPath(); // 刻度颜色 offscreenCanvasCtx.strokeStyle = '#fff'; // 刻度宽度 offscreenCanvasCtx.lineWidth = 3; // 每小时占据30° offscreenCanvasCtx.rotate(Math.PI / 6); // 开始绘制的位置 offscreenCanvasCtx.lineTo(140, 0) // 结束绘制的位置; offscreenCanvasCtx.lineTo(120, 0); // 绘制路径 offscreenCanvasCtx.stroke(); } offscreenCanvasCtx.restore();
指针指向
以秒针为例:获取当前时间的秒数,并计算对应的偏移角度
var now = new Date(), sec = now.getSeconds(), min = now.getMinutes(), hr = now.getHours(); hr = hr > 12 ? hr - 12 : hr; //秒针 offscreenCanvasCtx.save(); offscreenCanvasCtx.rotate(sec * (Math.PI / 30)); ...... offscreenCanvasCtx.stroke();
粒子动效
canvas可以用来绘制复杂,不规则的动画。粒子特效可以用来实现复杂、随机的动态效果。
粒子,指图像数据imageData
中的每一个像素点,获取到每个像素点之后,添加属性或事件对区域内的粒子进行交互,达到动态效果。
效果
粒子获取
以下图的图片转化为例,该效果是先在canvas上渲染图片,然后获取文字所在区域的每个像素点。
let image = new Image(); image.src='../image/logo.png'; let pixels=[]; //存储像素数据 let imageData; image.width = 300; image.height = 300 // 渲染图片,并获取该区域内像素信息 image.onload=function(){ ctx.drawImage(image,(canvas.width-image.width)/2,(canvas.height-image.height)/2,image.width,image.height); imageData=ctx.getImageData((canvas.width-image.width)/2,(canvas.height-image.height)/2,image.width,image.height); //获取图表像素信息 //绘制图像 };
像素信息
图片的大小为300*300,共有90000个像素,每个像素占4位,存放rgba数据。
粒子绘制
function getPixels(){ var pos=0; var data=imageData.data; //RGBA的一维数组数据 //源图像的高度和宽度为300px for(var i=1;i<=image.width;i++){ for(var j=1;j<=image.height;j++){ pos=[(i-1)*image.width+(j-1)]*4; //取得像素位置 if(data[pos]>=0){ var pixel={ x:(canvas.width-image.width)/2+j+Math.random()*20, //重新设置每个像素的位置信息 y:(canvas.height-image.height)/2+i+Math.random()*20, //重新设置每个像素的位置信息 fillStyle:'rgba('+data[pos]+','+(data[pos+1])+','+(data[pos+2])+','+(data[pos+3])+')' } pixels.push(pixel); } } } } function drawPixels() { var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext("2d"); ctx.clearRect(0,0,canvas.width,canvas.height); var len = pixels.length, curr_pixel = null; for (var i = 0; i < len; i++) { curr_pixel = pixels[i]; ctx.fillStyle = curr_pixel.fillStyle; ctx.fillRect(curr_pixel.x, curr_pixel.y, 1, 1); } }
粒子时钟
渲染文字时钟
function time() { ctx.clearRect(0,0,canvas.width,canvas.height) ctx.font = "150px 黑体"; ctx.textBaseline='top'; ctx.fillStyle = "rgba(245,245,245,0.2)"; ctx.fillText(new Date().format('hh:mm:ss'),(canvas.width-textWidth)/2,(canvas.height-textHeight)/2,textWidth,textHeight); }
效果
获取粒子
文字转换粒子概念同上,获取选定区域的像素,根据筛选条件进行选择并存入数组。经过遍历后重新绘制。
function getPixels(){ let imgData = ctx.getImageData((canvas.width-textWidth)/2,(canvas.height-textHeight)/2,textWidth,textHeight); let data = imgData.data pixelsArr = [] for(let i=1;i<=textHeight;i++){ for(let j=1;j<=textWidth;j++){ pos=[(i-1)*textWidth+(j-1)]*4; //取得像素位置 if(data[pos]>=0){ var pixel={ x:j+Math.random()*20, //重新设置每个像素的位置信息 y:i+Math.random()*20, //重新设置每个像素的位置信息 fillStyle:'rgba('+data[pos]+','+(data[pos+1])+','+(data[pos+2])+','+(data[pos+3])+')' }; pixelsArr.push(pixel); } } } }
imgData
保存了所选区域内的像素信息,每个像素点占据4位,保存了RGBA四位信息。筛选每个像素的第四位,这段代码中将所有透明度不为0的像素都保存到了数组pixelsArr
中。
x
、y
记载了该粒子的位置信息,为了产生效果图中的运动效果,给每个粒子添加了0-20个像素的偏移位置,每次重绘时,偏移位置随机生成,产生运动效果。
粒子重绘
获取粒子之后,需要清除画布中原有的文字,将获取到的粒子重新绘制到画布上去。
function drawPixels() { // 清除画布内容,进行重绘 ctx.clearRect(0,0,canvas.width,canvas.height); for (let i in pixelsArr) { ctx.fillStyle = pixelsArr[i].fillStyle; let r = Math.random()*4 ctx.fillRect(pixelsArr[i].x, pixelsArr[i].y, r, r); } }
粒子重绘时的样式为筛选像素时原本的颜色与透明度,并且每个在画布上绘制每个粒子时,定义大小参数r,r取值为0-4中随机的数字。最终生成的粒子大小随机。
实时刷新
获取粒子并成功重绘之后,需要页面实时刷新时间。这里采用window.requestAnimationFrame(callback)
方法。
function time() { ...... getpixels(); //获取粒子 drawPixels(); // 重绘粒子 requestAnimationFrame(time); }
window.requestAnimationFrame(callback)
方法告诉浏览器您希望执行动画并请求浏览器在下一次重绘之前调用指定的函数来更新动画。该方法使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用。
该方法不需要设置时间间隔,调用频率采用系统时间间隔(1s)。
文档解释戳这里
效果
总结
本文主要通过两种不同的方式实现了时钟的动态效果,其中粒子时钟具有更多的可操作性。在以后的canvas系列中会针对粒子系统实现更多的动态效果。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
P70系列延期,华为新旗舰将在下月发布
3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。
而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?
根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。
更新日志
- 英雄联盟六个龙魂是哪六个 英雄联盟六个龙魂介绍一览
- 《忆蚀》Subliminal:揭秘后室之谜,路知行献声Weplay文化展
- 初始之部制作人气漫画改编游戏《我家大师兄脑子有坑》参展2024WePlay
- 《异环》「奇点测试」定档11.28 超自然都市轻喜剧即将放送!
- 16层乐队.2024-大快朵颐【摩登天空】【FLAC分轨】
- 群星.1988-电视金曲巡礼【EMI百代】【WAV+CUE】
- 群星.1992-电视金曲巡礼VOL.2【EMI百代】【WAV+CUE】
- 廖昌永《情缘HQ》头版限量[低速原抓WAV+CUE]
- 蔡琴《老歌》头版限量编号MQA-24K金碟[低速原抓WAV+CUE]
- 李嘉《国语转调》3CD[WAV+CUE]
- 谭咏麟《爱的根源 MQA-UHQCD》2022头版限量编号 [WAV+CUE][1G]
- 江洋 《江洋原创琵琶作品专辑》[320K/MP3][118.08MB]
- 江洋 《江洋原创琵琶作品专辑》[FLAC/分轨][228.33MB]
- 《战舰世界》语音包文件夹位置介绍
- 《CSGO》送好友皮肤方法介绍