效果图预览:

image.png
html5技术提升1 - 图2

雪花的绘制:先看起点,再一步步画。

html5技术提升1 - 图3
雪花的一条线绘制:

  1. <script>
  2. //必要步骤
  3. var canvas = document.querySelector('#snow');
  4. var context = canvas.getContext('2d');
  5. canvas.width = window.innerWidth; //放置全屏
  6. canvas.height = window.innerHeight;
  7. function snow() {
  8. //雪花的中心点:平移。
  9. context.translate(100, 100); //雪花的中心点,通过移动画布到达位置
  10. context.moveTo(-20, 0); //雪花在顶点的左半部分
  11. context.lineTo(20, 0); //雪花在顶点的右半部分
  12. context.moveTo(50,50);
  13. context.lineTo(90,50);
  14. context.strokeStyle = "#fff";
  15. context.lineWidth = 5;
  16. context.lineCap = "round"; //圆角
  17. context.stroke();
  18. }
  19. snow();

问题1:雪花边边的点如何去取?

雪花的边: sin60 = 对边/斜边 => 对边 = sin60斜边 => y=sin60 半径(r) sin30 = 对边/斜边 => 对边 = sin30斜边 => x=sin30 半径(r)

雪花思路:

  1. function snow() {
  2. context.save();
  3. context.translate(100, 100); //雪花的中心点,通过移动画布到达位置
  4. context.moveTo(-20, 0); //雪花在顶点的左半部分
  5. context.lineTo(20, 0); //雪花在顶点的右半部分
  6. context.strokeStyle = '#fff';
  7. context.lineWidth = 5;
  8. context.lineCap = 'round';
  9. /*
  10. sin60=对边/斜边 => 对边=sin60*斜边 => y=sin60*半径(r)
  11. sin30=对边/斜边 => 对边=sin30*斜边 => x=sin30*半径(r)
  12. */
  13. var disX = Math.sin(30 * Math.PI / 180) * 20;
  14. var disY = Math.sin(60 * Math.PI / 180) * 20;
  15. context.moveTo(-disX, -disY);
  16. context.lineTo(disX, disY);
  17. context.moveTo(-disX, disY);
  18. context.lineTo(disX, -disY);
  19. context.stroke();
  20. context.restore();
  21. //第二个雪花构造:
  22. context.save();
  23. context.translate(50, 50); //雪花的中心点
  24. context.scale(0.5, 0.5);
  25. context.rotate(20 * Math.PI / 180);
  26. context.moveTo(-20, 0);
  27. context.lineTo(20, 0);
  28. /* context.moveTo(50, 50);
  29. context.lineTo(90, 50); */
  30. context.strokeStyle = '#fff';
  31. context.lineWidth = 5;
  32. context.lineCap = 'round';
  33. /*
  34. sin60=对边/斜边 => 对边=sin60*斜边 => y=sin60*半径(r)
  35. sin30=对边/斜边 => 对边=sin30*斜边 => x=sin30*半径(r)
  36. */
  37. var disX = Math.sin(30 * Math.PI / 180) * 20;
  38. var disY = Math.sin(60 * Math.PI / 180) * 20;
  39. //由此得出思路:
  40. context.moveTo(-disX, -disY);
  41. context.lineTo(disX, disY);
  42. context.moveTo(-disX, disY);
  43. context.lineTo(disX, -disY);
  44. context.stroke();
  45. context.restore();
  46. }
  47. //snow();

构造无数雪花:

  1. 写snow的方法放在prototype上
  2. 解决一个问题:在render之后,第一个雪花和第二个雪花的边都变粗

解决方法:是scale问题,context.beginPath();//开启路径,解决变粗问题

  1. function Snow(x, y, scale, rotate, speedX, speedY, speedR) {
  2. this.x = x;
  3. this.y = y;
  4. this.scale = scale;
  5. this.rotate = rotate;
  6. this.speedX = speedX;
  7. this.speedY = speedY;
  8. this.speedR = speedR;
  9. }
  10. Snow.prototype.render = function () {
  11. context.save();
  12. context.beginPath(); //开启一条路径
  13. context.translate(this.x, this.y); //雪花的中心点
  14. context.scale(this.scale, this.scale);
  15. context.rotate(this.rotate * Math.PI / 180);
  16. context.moveTo(-20, 0);
  17. context.lineTo(20, 0);
  18. context.strokeStyle = '#fff';
  19. context.lineWidth = 5;
  20. context.lineCap = 'round';
  21. var disX = Math.sin(30 * Math.PI / 180) * 20;
  22. var disY = Math.sin(60 * Math.PI / 180) * 20;
  23. context.moveTo(-disX, -disY);
  24. context.lineTo(disX, disY);
  25. context.moveTo(-disX, disY);
  26. context.lineTo(disX, -disY);
  27. context.stroke();
  28. context.restore();
  29. }

生成无数雪花:

  1. var snowArray = []; //存储所有的雪花,为了运动
  2. function init() {
  3. var len = 100;
  4. for (var i = 0; i < len; i++) {
  5. // 所有属性的值都是随机的(除了y)
  6. var x = Math.random() * canvas.width;
  7. var scale = Math.random() + 0.5; //0.5~1.5
  8. var rotate = Math.random() * 60; //0~60
  9. var speedX = Math.random() + 1; //1-2
  10. var speedY = Math.random() + 5; //5-6
  11. var speedR = Math.random() * 4 + 2; //0-4 2-6
  12. //生成雪花
  13. (function (x, y, scale, rotate, speedX, speedY, speedR) {
  14. setTimeout(function () {
  15. var snow = new Snow(x, y, scale, rotate, speedX, speedY, speedR);
  16. snow.render();
  17. snowArray.push(snow); //初始位置的渲染
  18. }, Math.random() * 8000);
  19. })(x, 0, scale, rotate, speedX, speedY, speedR);
  20. }
  21. snowing();
  22. }
  23. init();

snowing方法:让雪花飘起来

原理:清除画布,清一下,画一下
注:但是问题是阵雪,如何解决? 取模。
取模原理:

0 1 2 3 4 5 6 7 8
=>0 1 2 3 0 1 2 3

js代码:

  1. function snowing() {
  2. setInterval(function() {
  3. context.clearRect(0,0,canvas.width,canvas.height);
  4. for(var i = 0;i < snowArray.length;i++){
  5. //用取模来持续雪花效果!!!难
  6. //更新雪花的位置(取模是为了把值限制一个范围)
  7. snowArray[i].x = (snowArray[i].x + snowArray[i].speedX) % canvas.width;
  8. snowArray[i].y = (snowArray[i].y + snowArray[i].speedY) % canvas.height;
  9. snowArray[i].rotate = (snowArray[i].rotate + snowArray[i].speedR) % 60;
  10. snowArray[i].render();//重新画
  11. /*
  12. 0 1 2 3 4 5 6 7 8 => 0 1 2 3 0 1 2 3
  13. */
  14. }
  15. },30)
  16. }

合成属性:

效果图:
image.png
fillRect->正方形生成
arc ->圆生成
有重叠部分,用globalCompositeOperation方法,用完颜色叠加。

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title></title>
  6. </head>
  7. <body>
  8. <canvas id="canvas" width="500" height="500"></canvas>
  9. <script>
  10. /*@type:HTMLCanvasElement*/
  11. var canvas = document.querySelector('#canvas');
  12. var context = canvas.getContext('2d');
  13. context.beginPath();
  14. context.fillStyle = 'red';
  15. context.fillRect(100, 100, 200, 200);
  16. context.globalCompositeOperation='lighter';//处理两图形重叠部分
  17. context.beginPath();
  18. context.fillStyle = 'green';
  19. context.arc(300, 300, 100, 0, Math.PI * 2);
  20. context.fill();
  21. </script>
  22. </body>
  23. </html>