效果图预览:
雪花的绘制:先看起点,再一步步画。

雪花的一条线绘制:
<script>//必要步骤var canvas = document.querySelector('#snow');var context = canvas.getContext('2d');canvas.width = window.innerWidth; //放置全屏canvas.height = window.innerHeight;function snow() {//雪花的中心点:平移。context.translate(100, 100); //雪花的中心点,通过移动画布到达位置context.moveTo(-20, 0); //雪花在顶点的左半部分context.lineTo(20, 0); //雪花在顶点的右半部分context.moveTo(50,50);context.lineTo(90,50);context.strokeStyle = "#fff";context.lineWidth = 5;context.lineCap = "round"; //圆角context.stroke();}snow();
问题1:雪花边边的点如何去取?
雪花的边: sin60 = 对边/斜边 => 对边 = sin60斜边 => y=sin60 半径(r) sin30 = 对边/斜边 => 对边 = sin30斜边 => x=sin30 半径(r)
雪花思路:
function snow() {context.save();context.translate(100, 100); //雪花的中心点,通过移动画布到达位置context.moveTo(-20, 0); //雪花在顶点的左半部分context.lineTo(20, 0); //雪花在顶点的右半部分context.strokeStyle = '#fff';context.lineWidth = 5;context.lineCap = 'round';/*sin60=对边/斜边 => 对边=sin60*斜边 => y=sin60*半径(r)sin30=对边/斜边 => 对边=sin30*斜边 => x=sin30*半径(r)*/var disX = Math.sin(30 * Math.PI / 180) * 20;var disY = Math.sin(60 * Math.PI / 180) * 20;context.moveTo(-disX, -disY);context.lineTo(disX, disY);context.moveTo(-disX, disY);context.lineTo(disX, -disY);context.stroke();context.restore();//第二个雪花构造:context.save();context.translate(50, 50); //雪花的中心点context.scale(0.5, 0.5);context.rotate(20 * Math.PI / 180);context.moveTo(-20, 0);context.lineTo(20, 0);/* context.moveTo(50, 50);context.lineTo(90, 50); */context.strokeStyle = '#fff';context.lineWidth = 5;context.lineCap = 'round';/*sin60=对边/斜边 => 对边=sin60*斜边 => y=sin60*半径(r)sin30=对边/斜边 => 对边=sin30*斜边 => x=sin30*半径(r)*/var disX = Math.sin(30 * Math.PI / 180) * 20;var disY = Math.sin(60 * Math.PI / 180) * 20;//由此得出思路:context.moveTo(-disX, -disY);context.lineTo(disX, disY);context.moveTo(-disX, disY);context.lineTo(disX, -disY);context.stroke();context.restore();}//snow();
构造无数雪花:
- 写snow的方法放在prototype上
- 解决一个问题:在render之后,第一个雪花和第二个雪花的边都变粗
解决方法:是scale问题,context.beginPath();//开启路径,解决变粗问题
function Snow(x, y, scale, rotate, speedX, speedY, speedR) {this.x = x;this.y = y;this.scale = scale;this.rotate = rotate;this.speedX = speedX;this.speedY = speedY;this.speedR = speedR;}Snow.prototype.render = function () {context.save();context.beginPath(); //开启一条路径context.translate(this.x, this.y); //雪花的中心点context.scale(this.scale, this.scale);context.rotate(this.rotate * Math.PI / 180);context.moveTo(-20, 0);context.lineTo(20, 0);context.strokeStyle = '#fff';context.lineWidth = 5;context.lineCap = 'round';var disX = Math.sin(30 * Math.PI / 180) * 20;var disY = Math.sin(60 * Math.PI / 180) * 20;context.moveTo(-disX, -disY);context.lineTo(disX, disY);context.moveTo(-disX, disY);context.lineTo(disX, -disY);context.stroke();context.restore();}
生成无数雪花:
var snowArray = []; //存储所有的雪花,为了运动function init() {var len = 100;for (var i = 0; i < len; i++) {// 所有属性的值都是随机的(除了y)var x = Math.random() * canvas.width;var scale = Math.random() + 0.5; //0.5~1.5var rotate = Math.random() * 60; //0~60var speedX = Math.random() + 1; //1-2var speedY = Math.random() + 5; //5-6var speedR = Math.random() * 4 + 2; //0-4 2-6//生成雪花(function (x, y, scale, rotate, speedX, speedY, speedR) {setTimeout(function () {var snow = new Snow(x, y, scale, rotate, speedX, speedY, speedR);snow.render();snowArray.push(snow); //初始位置的渲染}, Math.random() * 8000);})(x, 0, scale, rotate, speedX, speedY, speedR);}snowing();}init();
snowing方法:让雪花飘起来
原理:清除画布,清一下,画一下
注:但是问题是阵雪,如何解决? 取模。
取模原理:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|
| =>0 | 1 | 2 | 3 | 0 | 1 | 2 | 3 |
js代码:
function snowing() {setInterval(function() {context.clearRect(0,0,canvas.width,canvas.height);for(var i = 0;i < snowArray.length;i++){//用取模来持续雪花效果!!!难//更新雪花的位置(取模是为了把值限制一个范围)snowArray[i].x = (snowArray[i].x + snowArray[i].speedX) % canvas.width;snowArray[i].y = (snowArray[i].y + snowArray[i].speedY) % canvas.height;snowArray[i].rotate = (snowArray[i].rotate + snowArray[i].speedR) % 60;snowArray[i].render();//重新画/*0 1 2 3 4 5 6 7 8 => 0 1 2 3 0 1 2 3*/}},30)}
合成属性:
效果图:
fillRect->正方形生成
arc ->圆生成
有重叠部分,用globalCompositeOperation方法,用完颜色叠加。
<!DOCTYPE html><html><head><meta charset="UTF-8"><title></title></head><body><canvas id="canvas" width="500" height="500"></canvas><script>/*@type:HTMLCanvasElement*/var canvas = document.querySelector('#canvas');var context = canvas.getContext('2d');context.beginPath();context.fillStyle = 'red';context.fillRect(100, 100, 200, 200);context.globalCompositeOperation='lighter';//处理两图形重叠部分context.beginPath();context.fillStyle = 'green';context.arc(300, 300, 100, 0, Math.PI * 2);context.fill();</script></body></html>

