简体   繁体   中英

Arrange points into an equilateral triangle on HTML5 canvas

I would like to arrange a set of points (currently squares) into an equilateral triangle on the HTML5 <canvas> element using any number of radians between 0.0 and PI*2.0 and a given radius (eg 150 ).

You can see in on this JS Bin that the black squares are arranged around in the shape of a circle, positioned using the canvas's rotate() and translate() methods.

I got as close 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();
}

在此处输入图片说明

You can interpolate points on a line segment between the vertices of the triangle like this:

// 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);

Here's example code and a Demo:

 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*(ba)); }; 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; } } 
 body{ background-color: ivory; padding:10px; } #canvas{border:1px solid red;} 
 <canvas id="canvas" width=300 height=300></canvas> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM