我需要在画布上绘制多色六边形

时间:2017-02-20 08:14:51

标签: javascript canvas

我需要在画布上绘制六边形,但每条边需要是不同的颜色。

我无法绘制边缘,因为我还需要一个半径和旋转值。

图片为例Colored Hexagon



var canvas = document.querySelector("canvas");
var ctx = canvas.getContext("2d");

function circle(x, y, r, fill) {
  ctx.beginPath()
  ctx.arc(x, y, r, 0, Math.PI*2)
  if (fill) {
    ctx.fill();
  } else {
    ctx.stroke();
  }
}

function poly(edges, radius, fill, startAngle) {
  if (typeof startAngle === "undefined") {
    var startAngle = -90;
  }
  var angle = 360/edges;
  ctx.beginPath();
  for (var i = 0; i <= edges; i++) {
    var a = ((angle*i)+startAngle)*(Math.PI/180);
    var x = 180 + radius * Math.cos(a);
    var y = 180 + radius * Math.sin(a);
    ctx.lineTo(x, y);
  }
  if (fill) {
    ctx.fill();
  } else {
    ctx.stroke();
  }
}

var Game = {
  "rotation": 0,
  "r": 0
};

function Draw() {
  ctx.save();
  ctx.clearRect(0, 0, 360, 360);
  ctx.lineWidth = 100;
  circle(180, 180, 180+(ctx.lineWidth/2));
  ctx.lineWidth = 1;
  poly(6, 30, false, Game.r-90);
  if (Game.r != Game.rotation) {
    if (Game.r < Game.rotation) {
      Game.r += 10;
    } else if (Game.r > Game.rotation) {
      Game.r -= 10;
    }
  }
  window.requestAnimationFrame(Draw);
  ctx.restore();
}

Draw();

document.onkeydown = function(e) {
  switch (e.which) {
    case 39: // Right Arrow
      Game.rotation += (360/6);
      break;
    case 37: // Left Arrow
      Game.rotation -= (360/6);
      break;
  }
}
&#13;
<canvas width="360" height="360"></canvas>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

跟踪Shape的位置和角度以及每个角落。

然后在需要时使用Math.cosMath.sin计算边缘:

var Shape = (function() {
  /**
   * Creates an instance of Shape.
   *
   * @param {ICoord} [position={ x: 0, y: 0 }]
   * @param {ICoord[]} [points=[]]
   * @param {number} [angle]
   *
   * @memberOf Shape
   */
  function Shape(position, points, angle) {
    if (position === void 0) {
      position = {
        x: 0,
        y: 0
      };
    }
    if (points === void 0) {
      points = [];
    }
    this.position = position;
    this.points = points;
    this.angle = 0;
    if (angle != void 0) {
      this.setAngle(angle);
    }
  }
  Shape.degreetoRadian = function(degree) {
    return degree * (Math.PI / 180);
  };
  /**
   * Create a shape from a position, a radius, the number of vertices and an angle in degrees [0;360]
   *
   * @static
   * @param {ICoord} [position={ x: 0, y: 0 }]
   * @param {number} [radius=10]
   * @param {number} [stops=4]
   * @param {number} [angle=0]
   * @returns {Shape}
   *
   * @memberOf Shape
   */
  Shape.poly = function(position, radius, stops, angle) {
    if (position === void 0) {
      position = {
        x: 0,
        y: 0
      };
    }
    if (radius === void 0) {
      radius = 10;
    }
    if (stops === void 0) {
      stops = 4;
    }
    if (angle === void 0) {
      angle = 0;
    }
    var points = [];
    for (var index = 0; index < 360; index += (360 / stops)) {
      points.push({
        x: Math.cos(this.degreetoRadian(index)) * radius,
        y: Math.sin(this.degreetoRadian(index)) * radius
      });
    }
    return new Shape(position, points, angle);
  };
  /**
   * Sets the angle to a value between 0 and 360
   *
   * @param {number} [value=this.angle]
   * @returns {Shape}
   *
   * @memberOf Shape
   */
  Shape.prototype.setAngle = function(value) {
    if (value === void 0) {
      value = this.angle;
    }
    this.angle = Math.abs(value) % 360;
    return this;
  };
  /**
   * Dissolves the points into lines, rotated to match the orientation of the Shape
   *
   * @returns {{ start: { x: number, y: number }, end: { x: number, y: number } }[]}
   *
   * @memberOf Shape
   */
  Shape.prototype.getLines = function() {
    var theta = Shape.degreetoRadian(this.angle);
    var edges = [];
    for (var indexa = 0; indexa < this.points.length; indexa++) {
      var a = this.points[indexa];
      var b = this.points[(indexa + 1) % this.points.length];
      edges.push({
        start: {
          x: a.x * Math.cos(theta) - a.y * Math.sin(theta),
          y: a.x * Math.sin(theta) + a.y * Math.cos(theta)
        },
        end: {
          x: b.x * Math.cos(theta) - b.y * Math.sin(theta),
          y: b.x * Math.sin(theta) + b.y * Math.cos(theta)
        }
      });
    }
    return edges;
  };
  return Shape;
}());
//>>Testing
//DOM
var c = document.createElement("canvas");
c.width = 100;
c.height = 100;
document.body.appendChild(c);
var ctx = c.getContext("2d");
//Shape
var drawings = [
  Shape.poly({
    x: 50,
    y: 50
  }, 50, 6, 360 / 12),
  Shape.poly({
    x: 50,
    y: 50
  }, 30, 6),
  Shape.poly({
    x: 50,
    y: 50
  }, 30, 3)
];
//Rendering
var colors = ["red", "green", "yellow", "blue", "magenta"];
var interval;
interval = setInterval(function() {
  ctx.clearRect(0, 0, c.width, c.height);
  for (var drawingIndex = 0; drawingIndex < drawings.length; drawingIndex++) {
    var drawing = drawings[drawingIndex];
    drawing.setAngle(drawing.angle + 1);
    var edges = drawing.getLines();
    ctx.lineWidth = 4;
    for (var index = 0; index < edges.length; index++) {
      var edge = edges[index];
      ctx.beginPath();
      ctx.strokeStyle = colors[index % colors.length];
      ctx.moveTo(edge.start.x + drawing.position.x, edge.start.y + drawing.position.y);
      ctx.lineTo(edge.end.x + drawing.position.x, edge.end.y + drawing.position.y);
      ctx.stroke();
      ctx.closePath();
    }
  }
}, 1000 / 60);

编辑1 - 有角度的边

基于评论显示Artsen希望得到一个有角度的交叉点。

这可以使用画布上的arc方法轻松实现:

var Xagon = /** @class */ (function () {
    function Xagon(sides, radius, angle, lineWidth) {
        if (sides === void 0) { sides = 4; }
        if (radius === void 0) { radius = 4; }
        if (angle === void 0) { angle = 0; }
        if (lineWidth === void 0) { lineWidth = 1; }
        this.sides = sides;
        this.radius = radius;
        this.angle = angle;
        this.lineWidth = lineWidth;
    }
    Xagon.prototype.draw = function (ctx, offset, handleSide) {
        if (offset === void 0) { offset = { x: 0, y: 0 }; }
        var sideOffset = 360 / this.sides;
        for (var side = 0; side < this.sides; side++) {
            var ang = Xagon.degreetoRadian(this.angle + sideOffset * side);
            ctx.beginPath();
            ctx.arc(offset.x, offset.y, this.radius - 0.5 * this.lineWidth, ang, ang);
            ctx.arc(offset.x, offset.y, this.radius + 0.5 * this.lineWidth, ang, ang);
            ctx.arc(offset.x, offset.y, this.radius + 0.5 * this.lineWidth, ang - Xagon.degreetoRadian(sideOffset), ang - Xagon.degreetoRadian(sideOffset));
            ctx.arc(offset.x, offset.y, this.radius - 0.5 * this.lineWidth, ang - Xagon.degreetoRadian(sideOffset), ang - Xagon.degreetoRadian(sideOffset));
            ctx.closePath();
            if (handleSide !== void 0) {
                handleSide(ctx, side);
            }
        }
    };
    Xagon.prototype.setAngle = function (value) {
        if (value === void 0) {
            value = this.angle;
        }
        this.angle = Math.abs(value) % 360;
        return this;
    };
    Xagon.degreetoRadian = function (degree) {
        return degree * (Math.PI / 180);
    };
    return Xagon;
}());
//TEST
var c = document.body.appendChild(document.createElement("canvas"));
var size = c.width = c.height = 500;
var ctx = c.getContext("2d");
var x = new Xagon(6, size * 0.4, 0, 50);
var interval;
var colors = ["red", "green", "yellow", "blue", "magenta", "cyan"];
function update() {
    ctx.clearRect(0, 0, size, size);
    x.setAngle(x.angle + 1);
    x.draw(ctx, { x: size / 2, y: size / 2 }, function side(ctx, sideIndex) {
        ctx.fillStyle = colors[sideIndex % colors.length];
        ctx.fill();
    });
    cancelAnimationFrame(interval);
    interval = requestAnimationFrame(update);
}
interval = requestAnimationFrame(update);