效果图预览:
雪花的绘制:先看起点,再一步步画。
雪花的一条线绘制:
<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.5
var rotate = Math.random() * 60; //0~60
var speedX = Math.random() + 1; //1-2
var speedY = Math.random() + 5; //5-6
var 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>