使用 typescript 和 canvas 重构snow效果
前言:之前做过一个 snow 效果,但是是直接用 HTML 做的 点击此处查看 ,几个星期前,我用 typescript 和 canvas 重构了一下,
snow效果是一个很简单的效果,但是用来练手还是不错的;
- 首先创建基本变量:
let canvas = <HTMLCanvasElement>document.getElementById('canvas'); let ctx = canvas.getContext('2d'); let H = canvas.height = window.innerHeight; let W = canvas.width = window.innerWidth; ctx.fillStyle = "#53B7F6";
在获取 canvas 的 dom 时可能后报错,所以要用断言或者 let canvas:any
这样来写,不然会报错;
这里让 canvas 的长,宽分别等于浏览器视窗的长宽,颜色为蓝色,如果想做背景,可以去掉;
- 获取图片文件:
const renderImg = (x: number = 10, y: number = 10): void => { ctx.drawImage(snowImg, x, y, 42, 30); }; let readStatus: boolean = false; let snowImg: any = new Image(); snowImg.onload = (): void => { readStatus = true; }; snowImg.src = 'snow.jpg';
要记得读取图片的函数是异步执行的,所以添加一个状态,来判断图片是否已加载,而 renderImg 函数呢,就是在 canvas 上绘制图片,
他有初始值x=10,y=10,后面的42,30 是图片的大小,这个如果你换一个图片的话需要好好调节这2个数值;
- 创建例子存储数组:
const snowNum: number = 8; interface snowType { x: number, y: number, stepX: number, stepY: number } let store: snowType[] = []; const add = (): void => { let num: number = snowNum * Math.random() | 0; while (num--) { store.push({ x: Math.random() * W | 0, y: 0, stepX: (Math.random() * 5 - 2) | 0, stepY: ((Math.random() * 8) | 0) + 2 }) } };
snowNum 的作用是每秒最多出现8片 snow,store 中存储了 snow 的坐标位置,和每秒的移动速度;
- 渲染函数:
const render = (): void => { if (!readStatus) return; clearBg(); let length: number = store.length; while (length--) { let {x, y, stepX, stepY}:snowType = store[length]; renderImg(x, y); store[length].x += stepX; store[length].y += stepY; if (check(store[length])) { store.splice(length, 1); } } };
通过坐标来渲染图片并添加移动,做出判断,当 snow 移动到浏览器底部时删除他;
- 时间计时:
let addTime: number = 0; let lastTime: number = 0; const animotion = (timestamp: number = 0): void => { if (timestamp - lastTime > 50) { render(); lastTime = timestamp; } if (timestamp - addTime > 1000) { add(); addTime = timestamp; } try { window.requestAnimationFrame(animotion); } catch { alert('你的浏览器不支持rAF,请更新或更换浏览器') } }; animotion();
之前的计时我都是拿 setInterval 来做计时器的,但是会有一个缺点,不知道大家有没碰到过,就是在 chrome 里
切换到其他页面是,数组仍在添加,但是已经停止了渲染,所以再切回来的时候,会出现一大堆的东西,而这个用 rAF 是没有的,
但是他需要较高的兼容(IE>10),不过网上已经有了用 setInterval 做兼容方法,百度一下就有了,我这里就不讲了;
最后:
demo: 点击此处查看
GitHub:https://github.com/Grewer/JsDemo/tree/master/snow
如果该文章帮到了你,还请推荐或 star;
完;
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步