首页 > 解决方案 > 如何绘制形状然后将其声明为变量?

问题描述

<!DOCTYPE html>
<html>
<body>

<canvas id="myCanvas" width="350" height="300"
style="border:6px solid black;">
</canvas>

<script>
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.strokeStyle = 'gold';
ctx.strokeRect(20, 10, 160, 100);
</script>

</body>
</html>

现在,我想继续转动这个绘制的矩形:

ctx.strokeStyle = 'gold';
ctx.strokeRect(20, 10, 160, 100);

在我可以简单地命名为“矩形”的变量中,我可以轻松地修改并在整个项目中调用它。我怎样才能做到这一点?谢谢你!

标签: javascripthtmlhtml5-canvas

解决方案


你可以使用Path2D

使用Path2D创建路径并根据需要渲染它们很方便,并且从渲染的角度来看,路径会更快一些,因为每次渲染路径时都不需要创建子路径。

最好围绕原点 (0,0) 创建子路径,以便您可以根据需要轻松移动、旋转和缩放它们。

示例创建一些具有不同内容的路径

function createRect() {
    const path = new Path2D();
    path.rect(-70, -45, 140, 90);  // add the sub path;
    return path;
}
function createCircle() {
    const path = new Path2D();
    path.arc(0, 0, 50, 0, Math.PI * 2);  // add the sub path;
    return path;
}
function createRandLines() {
    const path = new Path2D();
    var i = 10;
    while(i--) {
        path.moveTo(Math.random() * 20 - 10, Math.random() * 20 - 10);
        path.lineTo(Math.random() * 20 - 10, Math.random() * 20 - 10);
    }
    return path;
}

创建路径

const myCircle = createCircle();
const myRect = createCircle();
const myLines1 = createRandLines();
const myLines2 = createRandLines();

然后,您可以使用单个函数渲染任何路径。

function strokePath(path, x, y, lineWidth = ctx.lineWidth, color = ctx.strokeStyle) { // defaults to current style
    ctx.setTransform(1, 0, 0, 1, x, y);  // position the path so its (0,0) origin is at x,y
    ctx.lineWidth = lineWidth;
    ctx.strokeStyle = color;
    ctx.stroke(path);
}

传递路径位置样式和线宽来绘制路径。

const W = ctx.canvas.width;
const H = ctx.canvas.height;
strokePath(myCircle, Math.random() * W, Math.random() * H); 
strokePath(myRect, Math.random() * W, Math.random() * H);   
strokePath(myLines1, Math.random() * W, Math.random() * H); 
strokePath(myLines2, Math.random() * W, Math.random() * H); 

例子

关于创建路径功能的更详细的绘制功能和一些组织。

该示例一次创建 4 条路径,然后多次绘制它们,随机定位、旋转、缩放、alpha 褪色、着色和填充。

const W = canvas.width;
const H = canvas.height;
const ctx = canvas.getContext("2d");
ctx.lineCap = ctx.lineJoin = "round";
// Some math utils
Math.TAU = Math.PI * 2;
Math.rand = (m = 0, M = 1) => Math.random() * (M - m) + m;
Math.randItem = array => array[Math.random() * array.length | 0];

const FACE = [[-3,-38,-34,-32,-47,-16,-48,15,-36,34,-5,43,32,38,47,12,47,-21,25,-35],[-31,-19,-42,-6,-32,1,-9,-6,-6,-24],[5,-24,3,-6,29,2,40,-5,33,-19],[-30,15,-14,32,12,31,29,15,15,15,-2,23,-17,16],[-28,-14,-29,-6,-18,-9,-17,-15],[11,-17,12,-8,20,-6,22,-13,18,-16],[2,-39,0,-53,-9,-60],[-14,17,-16,26,-7,28,-5,22],[2,21,1,28,11,27,13,16]];

// Object to hold path types
const paths = {
  rect() {
    const path = new Path2D();
    path.rect(-20, -10, 40, 20); // add the sub path;
    return path;
  },
  ellipse() {
    const path = new Path2D();
    path.ellipse(0, 0, 20, 10, 0, 0, Math.TAU); // add the sub path;
    return path;
  },
  randLines() {
    const path = new Path2D();
    var i = 10;
    while (i--) {
      path.moveTo(Math.rand(-20, 20), Math.rand(-20, 20));
      path.lineTo(Math.rand(-20, 20), Math.rand(-20, 20));
    }
    return path;
  },
  face() {
    const path = new Path2D();
    FACE .forEach(sub => { // each sub path
      let i = 0;
      path.moveTo(sub[i++] / 3, sub[i++] / 3);
      while (i < sub.length) { path.lineTo(sub[i++] / 3, sub[i++] / 3) }
      path.closePath();
    });
    return path;
  }
};

// Function to draw scaled, rotated, faded, linewidth, colored path		
function strokePath(path, x, y, scale, rotate, alpha, lineWidth, color, fillColor) { 
  ctx.lineWidth = lineWidth * (1 / scale);  //Scale line width  by inverse scale to ensure the pixel size is constant
  ctx.setTransform(scale, 0, 0, scale, x, y); // position the path so its (0,0) origin is at x,y
  ctx.rotate(rotate);
  if (fillColor) {
    ctx.globalAlpha = 1;
    ctx.fillStyle = fillColor;
    ctx.fill(path, "evenodd");
  }
  ctx.globalAlpha = alpha;
  ctx.strokeStyle = color;
  ctx.stroke(path);
}

// create some paths and colors
const pathArray = [paths.ellipse(), paths.rect(), paths.randLines(), paths.face()];
const colors = "#F00,#FA0,#0B0,#0AF,#00F,#F0A,#000,#888".split(",");

drawRandomPath();

function drawRandomPath() {
  strokePath(
    Math.randItem(pathArray),         // random path
    Math.rand(0, W), Math.rand(0, H), // random pos
    Math.rand(0.25, 1),               // random scale
    Math.rand(0, Math.TAU),           // random rotate
    Math.rand(0.5, 1),                // random alpha
    1,                                // constant lineWidth
    Math.randItem(colors),            // random color
    Math.rand() < 0.2 ? "#EED" : undefined, // Fill 1 in 5 with white
  );
  setTimeout(drawRandomPath, 250); // draw another path every quarter second.
}
* {margin:0px}
canvas {border:1px solid}
<canvas id="canvas" width="600" height="190"></canvas>


推荐阅读