【问题标题】:How to draw a star by using canvas HTML5?如何使用 canvas HTML5 绘制星星?
【发布时间】:2014-09-14 19:28:40
【问题描述】:

我正在尝试使用画布绘制星星,但代码没有运行。我想了解:测量 Y 和 X 坐标的步骤是什么?如何找到它们?画什么形状?

<html>
 <head>
   <meta charset = "utf-8">
   <title>Drawing Lines</title>
 </head>
 <body>
   <canvas id = "drawLines" width = "400" height = "200" 
     style = "border: 1px solid Black;">
   </canvas>
   <script>
     var canvas = document.getElementById("drawLines");
     var context = canvas.getContext("2d")

     canvas.beginPath(); 
     canvas.moveTo(50,50);
     canvas.lineTo(120,150);
     canvas.lineTo(0,180); 
     canvas.lineTo(120,210);
     canvas.lineTo(50,310);  
     canvas.lineTo(160,250);
     canvas.lineTo(190,370);
     canvas.lineTo(220,250);
     canvas.lineTo(330,310);
     canvas.lineTo(260,210);
     canvas.lineTo(380,180);
     canvas.closePath();
     canvas.stroke();
   </script>
 </body>
</html>

【问题讨论】:

    标签: javascript html html5-canvas


    【解决方案1】:

    星星基本上是一个正多边形,内半径和外半径上都有交替的点。

    这是一个绘制星形的灵活函数示例。

    您可以设置位置、#spikes 以及尖刺的内外半径:

    示例代码和演示:http://jsfiddle.net/m1erickson/8j6kdf4o/

    <!doctype html>
    <html>
    <head>
    <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    <style>
        body{ background-color: ivory; }
        canvas{border:1px solid red;}
    </style>
    <script>
    $(function(){
    
        var canvas=document.getElementById("canvas");
        var ctx=canvas.getContext("2d");
    
        function drawStar(cx,cy,spikes,outerRadius,innerRadius){
          var rot=Math.PI/2*3;
          var x=cx;
          var y=cy;
          var step=Math.PI/spikes;
    
          ctx.beginPath();
          ctx.moveTo(cx,cy-outerRadius)
          for(i=0;i<spikes;i++){
            x=cx+Math.cos(rot)*outerRadius;
            y=cy+Math.sin(rot)*outerRadius;
            ctx.lineTo(x,y)
            rot+=step
    
            x=cx+Math.cos(rot)*innerRadius;
            y=cy+Math.sin(rot)*innerRadius;
            ctx.lineTo(x,y)
            rot+=step
          }
          ctx.lineTo(cx,cy-outerRadius);
          ctx.closePath();
          ctx.lineWidth=5;
          ctx.strokeStyle='blue';
          ctx.stroke();
          ctx.fillStyle='skyblue';
          ctx.fill();
        }
    
        drawStar(100,100,5,30,15);
    
    }); // end $(function(){});
    </script>
    </head>
    <body>
        <canvas id="canvas" width=300 height=300></canvas>
    </body>
    </html>
    

    【讨论】:

    • 谢谢,我在大约 5 分钟内完成了大约 3 个小时的工作,谢谢你 :)
    • ctx.strokeSyle有错别字,应该是ctx.strokeStyle
    • 这是我最终使用的答案。干净、多功能且无错误。
    【解决方案2】:

    坐标转换功能可以更短:

    function strokeStar(x, y, r, n, inset) {
        ctx.save();
        ctx.beginPath();
        ctx.translate(x, y);
        ctx.moveTo(0,0-r);
        for (var i = 0; i < n; i++) {
            ctx.rotate(Math.PI / n);
            ctx.lineTo(0, 0 - (r*inset));
            ctx.rotate(Math.PI / n);
            ctx.lineTo(0, 0 - r);
        }
        ctx.closePath();
        ctx.fill();
        ctx.restore();
    }
    

    【讨论】:

    • 喜欢这种方法,可以适应任何具有旋转对称性的东西。
    【解决方案3】:

    lineTo()、moveTo()、stroke() 等这些函数属于上下文对象,而不是画布对象。您是否正在检查您的开发者控制台(Chrome 中的 f12)?你会看到这些函数是未定义的。

    【讨论】:

    • 是的,我正在通过 Chrome 检查控制台。如何定义它们?如何将它们写成画布对象?
    【解决方案4】:
    //function to draw star with N spikes
    //centered on a circle of radius R, centered on (cX,cY)
    function star(R, cX, cY, N) {
      //star draw
      ctx.beginPath();
      ctx.moveTo(cX + R,cY);
      for(var i = 1; i <= N * 2; i++)
      {
        if(i % 2 == 0){
          var theta = i * (Math.PI * 2) / (N * 2);
          var x = cX + (R * Math.cos(theta));
          var y = cY + (R * Math.sin(theta));
        } else {
          var theta = i * (Math.PI * 2) / (N * 2);
          var x = cX + ((R/2) * Math.cos(theta));
          var y = cY + ((R/2) * Math.sin(theta));
        }
    
        ctx.lineTo(x ,y);
      }
      ctx.closePath();
      ctx.stroke();
    }
    

    【讨论】:

      【解决方案5】:

      正如@v-rubinetti 所述,您正试图错误地调用方法。

      虽然通过编码在画布中绘制简单的星星很容易,但绘制高级的东西就很复杂了。您可以使用Inkscape 等开源矢量图形软件以及ink2canvas 扩展来绘制高级矢量图形并将其保存到html5 文档中。

      例如,这是在 Inkscape 中绘制并使用 ink2canvas 扩展保存的 25 角星:

      <!DOCTYPE html>
      <html>
      <head>
          <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
          <title>Inkscape Output</title>
      </head>
      <body>
          <canvas id='canvas' width='320' height='320'></canvas>
          <script>
          var ctx = document.getElementById("canvas").getContext("2d");
          ctx.save();
          ctx.lineJoin = 'miter';
          ctx.strokeStyle = 'rgb(0, 0, 0)';
          ctx.lineCap = 'butt';
          ctx.lineWidth = 1.000000;
          ctx.fillStyle = 'rgb(255, 255, 0)';
          ctx.beginPath();
          ctx.transform(0.506236, 0.000000, 0.000000, 0.505711, 82.274469, 51.410524);
          ctx.moveTo(342.857130, 449.505040);
          ctx.lineTo(234.764940, 344.516400);
          ctx.lineTo(279.468630, 488.419550);
          ctx.lineTo(200.881970, 359.847880);
          ctx.lineTo(208.393950, 510.347410);
          ctx.lineTo(164.250710, 366.271350);
          ctx.lineTo(134.098980, 513.910810);
          ctx.lineTo(127.172840, 363.383190);
          ctx.lineTo(61.251941, 498.885850);
          ctx.lineTo(91.978093, 351.364870);
          ctx.lineTo(-5.569921, 466.216610);
          ctx.lineTo(60.877887, 330.971560);
          ctx.lineTo(-62.167941, 417.955810);
          ctx.lineTo(35.826363, 303.484630);
          ctx.lineTo(-104.985860, 357.135850);
          ctx.lineTo(18.397601, 270.631190);
          ctx.lineTo(-131.333260, 287.578290);
          ctx.lineTo(9.686712, 234.475540);
          ctx.lineTo(-139.554650, 213.653670);
          ctx.lineTo(10.241036, 197.289490);
          ctx.lineTo(-129.133450, 140.006950);
          ctx.lineTo(20.025741, 161.409550);
          ctx.lineTo(-100.724450, 71.265628);
          ctx.lineTo(38.426018, 129.090210);
          ctx.lineTo(-56.112700, 11.748970);
          ctx.lineTo(64.285711, 102.362200);
          ctx.lineTo(1.898679, -34.803371);
          ctx.lineTo(95.979959, 82.904945);
          ctx.lineTo(69.664621, -65.466342);
          ctx.lineTo(131.517300, 71.941014);
          ctx.lineTo(142.927140, -78.313274);
          ctx.lineTo(168.664780, 70.159311);
          ctx.lineTo(217.082890, -72.536949);
          ctx.lineTo(205.088300, 77.671789);
          ctx.lineTo(287.472380, -48.500313);
          ctx.lineTo(238.499240, 94.006409);
          ctx.lineTo(349.672790, -7.713676);
          ctx.lineTo(266.798250, 118.136810);
          ctx.lineTo(399.775840, 47.260185);
          ctx.lineTo(288.207210, 148.546780);
          ctx.lineTo(434.633360, 112.967060);
          ctx.lineTo(301.380910, 183.325570);
          ctx.lineTo(452.055130, 185.278350);
          ctx.lineTo(305.491610, 220.287880);
          ctx.lineTo(450.946490, 259.650470);
          ctx.lineTo(300.281000, 257.111240);
          ctx.lineTo(431.377070, 331.410340);
          ctx.lineTo(286.076510, 291.481900);
          ctx.lineTo(394.576520, 396.049020);
          ctx.lineTo(263.770630, 321.240230);
          ctx.closePath();
          ctx.fill();
          ctx.stroke();
          ctx.restore();
          </script>
      </body>
      </html>
      

      【讨论】:

      • 当您可以简单地从 SVG 文件中绘图时,为什么要将 SVG 文件转换为代码:jsfiddle.net/Lq6rksct/1 将数据硬编码到您的代码中被认为是一种不好的做法。
      • 我还能如何回答有关上下文方法的问题?在 Canvas 与 SVG 的辩论中,我不偏袒任何一方。选择最适合您正在做的事情的一种(例如,对于游戏,画布效果最好)。
      • 您可能想重新阅读我的评论。我什至没有说在画布上使用 SVG。
      • 不回答问题。期待“测量 x 和 y”和“绘制任何形状”。应该进行一些计算才能得到相关答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-04
      • 2013-09-04
      • 1970-01-01
      • 1970-01-01
      • 2021-01-16
      • 2020-02-27
      相关资源
      最近更新 更多