zoukankan      html  css  js  c++  java
  • 学习HTML5 canvas遇到的问题

      学习HTML5 canvas遇到的问题

    1. 非零环绕原则(nonzZero rule) 

    • 非零环绕原则是canvas在进行填充的时候是否要进行填充的判断依据。
    • 在判断填充的区域拉一条线出来,拉到图形的外面,这条拉出来的线就是辅助线。判断绘制的线是否是从辅助线的左边穿过到辅助线的右边,此时这种穿过的方式记录为+1;如果是从辅助线的右边穿到辅助线的左边,就记做-1.最后将所有记录的数字进行求和,如果求和的结果为0,代表这块区域不要填充,否则,必须填充
    • 上面的原理较难理解,可以这样理解,当在大矩形中绘制小矩形,大矩形的绘制方向与小矩形的绘制方向相同时,填充颜色后,大小矩形都填充相同颜色;大矩形的绘制方向与小矩形的绘制方向相反时,填充颜色后,小矩形不会填充颜色,大矩形与小矩形之间的区域会填充颜色。
    • 大矩形的绘制方向与小矩形的绘制方向相同时的代码
    •  1 <!DOCTYPE html>
       2 <html lang="en">
       3 
       4 <head>
       5 <meta charset="UTF-8">
       6 <title>非零环绕原则</title>
       7 </head>
       8 
       9 <body>
      10 <canvas id="canvas" style="margin:0 auto;border:1px #666 solid" width="800" height="600">
      11 </canvas>
      12 <script>
      13 var canvas = document.getElementById('canvas');
      14 var ctx = canvas.getContext('2d');
      15 ctx.moveTo(100, 100);
      16 ctx.lineTo(100, 400);
      17 ctx.lineTo(400, 400);
      18 ctx.lineTo(400, 100);
      19 ctx.lineTo(100, 100);
      20 
      21 ctx.moveTo(200, 200);
      22 ctx.lineTo(300, 300);
      23 ctx.lineTo(300, 300);
      24 ctx.lineTo(300, 200);
      25 ctx.lineTo(200, 200);
      26 ctx.fill();
      27 </script>
      28 </body>
      29 
      30 </html>
      View Code
    • 大矩形的绘制方向与小矩形的绘制方向相同时的效果图
    • 大矩形的绘制方向与小矩形的绘制方向相反时的代码
    •  1 <!DOCTYPE html>
       2 <html lang="en">
       3 
       4 <head>
       5 <meta charset="UTF-8">
       6 <title>非零环绕原则</title>
       7 </head>
       8 
       9 <body>
      10 <canvas id="canvas" style="margin:0 auto;border:1px #666 solid" width="800" height="600">
      11 </canvas>
      12 <script>
      13 var canvas = document.getElementById('canvas');
      14 var ctx = canvas.getContext('2d');
      15 ctx.moveTo(100, 100);
      16 ctx.lineTo(100, 400);
      17 ctx.lineTo(400, 400);
      18 ctx.lineTo(400, 100);
      19 ctx.lineTo(100, 100);
      20 
      21 ctx.moveTo(200, 200);
      22 ctx.lineTo(300, 200);
      23 ctx.lineTo(300, 300);
      24 ctx.lineTo(200, 300);
      25 ctx.lineTo(200, 200);
      26 ctx.fill();
      27 </script>
      28 </body>
      29 
      30 </html>
      View Code
    • 大矩形的绘制方向与小矩形的绘制方向相反时效果图

    2. closePath() 与 lineTo()的区别 

    • closePath与lineTo闭合是有区别的,closePath闭合自然,lineTo闭合会有锯齿,仅在闭合的连接处会有区别
    • 效果图
    •  1 <!DOCTYPE html>
       2 <html lang="en">
       3 
       4 <head>
       5 <meta charset="UTF-8">
       6 <title>Document</title>
       7 <style>
       8 canvas {
       9 display: block;
      10 margin: 100px auto;
      11 border: 1px solid #000;
      12 }
      13 </style>
      14 </head>
      15 
      16 <body>
      17 <canvas id="myCanvas" width="600px" height="400px"></canvas>
      18 <script>
      19 var myCanvas = document.getElementById("myCanvas");
      20 var ctx = myCanvas.getContext('2d');
      21 ctx.lineWidth = 20;
      22 ctx.moveTo(100, 100);
      23 ctx.lineTo(100, 100 + 100);
      24 ctx.lineTo(100 + 100, 100 + 100);
      25 ctx.lineTo(100, 100);
      26 
      27 ctx.moveTo(300, 100);
      28 ctx.lineTo(300, 100 + 100);
      29 ctx.lineTo(300 + 100, 100 + 100);
      30 ctx.closePath();
      31 ctx.stroke();
      32 </script>
      33 </body>
      34 </html>
      View Code

    3. arc绘图的注意事项 

    • 使用 arc 绘图的时候, 如果没有设置 moveTo ,那么会从开始绘弧的地方作为起始点,连线到圆弧的起点.
    • 如果使用 stroke 方法, 那么会连线到圆弧的起始位置. 如果是 fill 方法, 会自动闭合路径填充.
    •  1 <!DOCTYPE html>
       2 <html lang="en">
       3 <head>
       4 <meta charset="UTF-8">
       5 <title>Document</title>
       6 <style>
       7 canvas{
       8 display: block;
       9 margin: 0 auto;
      10 border: 1px solid #666;
      11 }
      12 </style>
      13 </head>
      14 <body>
      15 <canvas id="myCanvas" width="800" height="300"></canvas>
      16 <script>
      17 var myCanvas = document.getElementById("myCanvas");
      18 var ctx = myCanvas.getContext('2d');
      19 ctx.moveTo(50,100);
      20 ctx.lineTo(100,100);
      21 ctx.arc(150,150,50,0,Math.PI);
      22 ctx.stroke();
      23 
      24 ctx.moveTo(200,100);
      25 ctx.lineTo(300,100);
      26 ctx.arc(300,150,50,0,Math.PI*1.2);
      27 ctx.stroke();
      28 
      29 ctx.beginPath();
      30 ctx.moveTo(400,100);
      31 ctx.lineTo(500,100);
      32 ctx.arc(500,150,50,0,Math.PI*1.2);
      33 ctx.fill();
      34 
      35 ctx.beginPath();
      36 ctx.moveTo(600,50);
      37 ctx.lineTo(700,100);
      38 ctx.arc(700,150,50,0,Math.PI*1.2);
      39 ctx.fill();
      40 </script>
      41 </body>
      42 </html>
      View Code
    • 效果图

    3.1 解决方法一:使用beginPath(),开启新的路径,两次绘制的图形就不会相互产生影响

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4 <meta charset="UTF-8">
     5 <title>Document</title>
     6 <style>
     7 canvas{
     8 display: block;
     9 margin: 0 auto;
    10 border: 1px solid #666;
    11 }
    12 </style>
    13 </head>
    14 <body>
    15 <canvas id="myCanvas" width="800" height="300"></canvas>
    16 <script>
    17 var myCanvas = document.getElementById("myCanvas");
    18 var ctx = myCanvas.getContext('2d');
    19 ctx.moveTo(50,100);
    20 ctx.lineTo(100,100);
    21 //使用beginPath(),多添加的两句代码
    22 ctx.stroke();
    23 ctx.beginPath();
    24 ctx.arc(150,150,50,0,Math.PI);
    25 ctx.stroke();
    26 </script>
    27 </body>
    28 </html>
    View Code

    效果图

    3.2 解决方法一:使用moveTo(),将上一个图形的终点移动到下一个即将绘制的图形上,就可以解决问题,效果与上面的解决方法相同。但是,该方法只需要使用一次stroke().

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4 <meta charset="UTF-8">
     5 <title>Document</title>
     6 <style>
     7 canvas{
     8 display: block;
     9 margin: 0 auto;
    10 border: 1px solid #666;
    11 }
    12 </style>
    13 </head>
    14 <body>
    15 <canvas id="myCanvas" width="800" height="300"></canvas>
    16 <script>
    17 var myCanvas = document.getElementById("myCanvas");
    18 var ctx = myCanvas.getContext('2d');
    19 ctx.moveTo(50,100);
    20 ctx.lineTo(100,100);
    21 //添加moveTO()这一句代码即可
    22 ctx.moveTo(200,150);
    23 ctx.arc(150,150,50,0,Math.PI);
    24 ctx.stroke();
    25 </script>
    26 </body>
    27 </html>
    View Code

    3.3  arc的一个小应用,绘制圆环进度条,使用了lineWidth

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 
     4 <head>
     5 <meta charset="UTF-8">
     6 <title>Document</title>
     7 <style>
     8 canvas {
     9 display: block;
    10 margin: 0 auto;
    11 border: 1px solid #666;
    12 }
    13 </style>
    14 </head>
    15 
    16 <body>
    17 <canvas id="myCanvas" width="400" height="400"></canvas>
    18 <script>
    19 var myCanvas = document.getElementById("myCanvas");
    20 var ctx = myCanvas.getContext('2d');
    21 
    22 function toRad(d) {
    23 return d * Math.PI / 180;
    24 }
    25 var x = 200,
    26 y = 200,
    27 angle = 0,
    28 percent = 0;
    29 var timeId = setInterval(function() {
    30 ctx.clearRect(0,0,myCanvas.width,myCanvas.height);
    31 ctx.beginPath();
    32 ctx.arc(x, y, 120, 0, toRad(angle));
    33 ctx.strokeStyle = '#00f';
    34 ctx.lineWidth = 40;
    35 ctx.stroke();
    36 
    37 ctx.fillStyle = '#f00';
    38 ctx.font = '700 30px Arial';
    39 ctx.textAlign = 'center';
    40 ctx.textBaseline = 'middle';
    41 percent = Math.floor(angle /360*100);
    42 ctx.fillText(percent + '%', x, y);
    43 if (percent >= 100) {
    44 clearInterval(timeId)
    45 }
    46 else{
    47 angle++;
    48 }
    49 }, 20);
    50 </script>
    51 </body>
    52 
    53 </html>
    View Code

    效果图

    4. arcTo()的使用

    • arcTo绘制圆角,需要线端点,矩形顶点以及另一线段的端点三个参考点
    •  1 <!DOCTYPE html>
       2 <html lang="en">
       3 
       4 <head>
       5     <meta charset="UTF-8">
       6     <title>Document</title>
       7     <style>
       8     canvas {
       9         display: block;
      10         margin: 0 auto;
      11         border: 1px solid #666;
      12     }
      13     </style>
      14 </head>
      15 
      16 <body>
      17     <canvas id="myCanvas" width="600" height="460"></canvas>
      18     <script>
      19     var myCanvas = document.getElementById("myCanvas");
      20     var ctx = myCanvas.getContext('2d');
      21 
      22     function toRad(d) {
      23         return d * Math.PI / 180;
      24     }
      25 
      26     function circleRect(x, y, width, height, r, color) {
      27         //保存之前的绘图状态
      28         ctx.save();
      29         ctx.beginPath();
      30         //绘制四条边
      31         ctx.moveTo(x + r, y);
      32         ctx.lineTo(x + width - r, y);
      33 
      34         ctx.moveTo(x + r, y + height);
      35         ctx.lineTo(x + width - r, y + height);
      36 
      37         ctx.moveTo(x, y + r);
      38         ctx.lineTo(x, y + height - r);
      39 
      40         ctx.moveTo(x + width, y + r);
      41         ctx.lineTo(x + width, y + height - r);
      42 
      43         ctx.moveTo(x + r, y);
      44         ctx.arcTo(x, y, x, y + r, r);
      45 
      46         ctx.moveTo(x + width - r, y);
      47         ctx.arcTo(x + width, y, x + width, y + r, r);
      48 
      49         ctx.moveTo(x, y + height - r);
      50         ctx.arcTo(x, y + height, x + r, y + height, r);
      51 
      52         ctx.moveTo(x + width - r, y + height);
      53         ctx.arcTo(x + width, y + height, x + width, y + height - r, r);
      54         //传入颜色,则使用传入的颜色;否则使用默认黑色
      55         ctx.strokeStyle = color || '#000';
      56         ctx.stroke();
      57         //恢复之前的绘图状态
      58         ctx.restore();
      59     }
      60 
      61     circleRect(100, 100, 200, 200, 50, 'red');
      62     circleRect(300, 300, 100, 100, 25);
      63     </script>
      64 </body>
      65 
      66 </html>
      View Code
    • 效果图

     

  • 相关阅读:
    二分图 洛谷P2055 [ZJOI2009]假期的宿舍
    并查集 洛谷P1640 [SCOI2010]连续攻击游戏
    贪心 洛谷P2870 Best Cow Line, Gold
    贪心 NOIP2013 积木大赛
    快速幂 NOIP2013 转圈游戏
    倍增LCA NOIP2013 货车运输
    树形DP 洛谷P2014 选课
    KMP UVA1328 Period
    动态规划入门 BZOJ 1270 雷涛的小猫
    KMP POJ 2752Seek the Name, Seek the Fame
  • 原文地址:https://www.cnblogs.com/stevexu/p/7196081.html
Copyright © 2011-2022 走看看