在HTML5画布上将点排列成等边三角形

时间:2015-02-03 05:13:31

标签: javascript html5 canvas html5-canvas

我想在HTML5 <canvas>元素上使用0.0PI*2.0之间任意数量的弧度和给定半径将一组点(当前为正方形)排列成等边三角形(例如150)。

您可以在on this JS Bin中看到黑色方块以圆形排列,使用画布的rotate()translate()方法定位。

我尽可能接近as this

var w = canvas.width = 360;
var h = canvas.height = 360;

var PI = Math.PI,
    TAU = PI * 2,
    sqrt = Math.sqrt,
    pow = Math.pow;

var radius = 150;

ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, w, h);

ctx.translate(w/2, h/2);

ctx.fillStyle = "#000";

// draw circle (omitted)
var corners = 3;
// draw triangle (omitted)

for(var i = 0, max = 90; i < max; i++){
  var delta = i/max; // between 0.0 and 1.0
  var radian = delta * TAU; // between 0 and PI*2

  var dist = radius;

  var portion = (delta * corners) % 1;
  var dist = radius - 70 * sqrt(4 - pow(portion * 4 - 2, 2)) / 2;

  ctx.save();
  ctx.rotate(radian);
  ctx.translate(0, dist);
  ctx.fillRect(-2, -2, 4, 4);
  ctx.restore();
}

1 个答案:

答案 0 :(得分:0)

enter image description here

您可以在三角形顶点之间的线段上插值点,如下所示:

// a function that does linear interpolation
var lerp=function(a,b,pct){ return(a+pct*(b-a)); };

// x1,y1 & x2,y2 are vertices of the triangle
// pct is the percentage (0.00-1.00) between the 1st & 2nd vertex 
//    where you want to place a point
var x=lerp(x1,x2,pct/100);
var y=lerp(y1,y2,pct/100);

以下是示例代码和演示:

&#13;
&#13;
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var PI=Math.PI;
var PI2=PI*2;
var lerp=function(a,b,pct){ return(a+pct*(b-a)); };
var interpolatedDotCount=15;
var a1=PI/2;
var a2=a1+PI2/3;
var a3=a2+PI2/3;
//
var nextTime=0;
var delay=16*3;
//
var cx=150;
var cy=150;
var minRadius=50;
var maxRadius=100;
var radius=minRadius;
var radiusDirection=1;
var angleIncrement=PI2/60;
var dotSize=3;

requestAnimationFrame(animate);

function dottedTriangle(cx,cy,radius){

  ctx.clearRect(0,0,cw,ch);

  var vertex1x=cx+radius*Math.cos(a1);
  var vertex1y=cy+radius*Math.sin(a1);
  var vertex2x=cx+radius*Math.cos(a2);
  var vertex2y=cy+radius*Math.sin(a2);
  var vertex3x=cx+radius*Math.cos(a3);
  var vertex3y=cy+radius*Math.sin(a3);

  var dx=vertex2x-vertex1x;
  var dy=vertex2y-vertex1y;
  var length=Math.sqrt(dx*dx+dy*dy);

  ctx.beginPath();
  ctx.arc(cx,cy,radius,0,PI2);
  ctx.closePath();
  ctx.strokeStyle='lightcoral';
  ctx.stroke();

  interpolateDots(vertex1x,vertex1y,vertex2x,vertex2y);
  interpolateDots(vertex2x,vertex2y,vertex3x,vertex3y);
  interpolateDots(vertex3x,vertex3y,vertex1x,vertex1y);

  dot(vertex1x,vertex1y,dotSize,'red');
  dot(vertex2x,vertex2y,dotSize,'green');
  dot(vertex3x,vertex3y,dotSize,'blue');

}


function interpolateDots(x1,y1,x2,y2){
  for(var pct=0;pct<100;pct+=100/interpolatedDotCount){
    var x=lerp(x1,x2,pct/100);
    var y=lerp(y1,y2,pct/100);
    dot(x,y,dotSize,'gold');
  }
}


function dot(x,y,r,color){
  ctx.fillStyle=color;
  ctx.beginPath();
  ctx.arc(x,y,r,0,PI2);
  ctx.closePath();
  ctx.fill();
}


function animate(time){
  requestAnimationFrame(animate);
  if(time<nextTime){return;}
  nextTime+=delay;
  dottedTriangle(cx,cy,radius);

  a1+=angleIncrement;
  a2=a1+PI2/3;
  a3=a2+PI2/3;

  radius+=radiusDirection;
  if(radius<minRadius || radius>maxRadius){
    radiusDirection*=-1;
    radius+=radiusDirection;
  }
}
&#13;
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
&#13;
<canvas id="canvas" width=300 height=300></canvas>
&#13;
&#13;
&#13;