如何旋转和平移 html5 canvas 路径,使最后一点位于中心

How to rotate and translate html5 canvas path so the last point will be at center

这里有演示和代码:http://jsbin.com/wuhuro/1/edit?js,output

首先我这里有坐标:

var pts = [[{"X":"52.724649013065175","Y":"8.245410919189453"},{"X":"52.65681045479847","Y":"8.245067596435547"},{"X":"52.65056234595389","Y":"8.255367279052734"},{"X":"52.648271148983376","Y":"8.26772689819336"},{"X":"52.65035406028101","Y":"8.27768325805664"},{"X":"52.654519585231995","Y":"8.284549713134766"},{"X":"52.718826525722605","Y":"8.283863067626953"},{"X":"52.7250648752743","Y":"8.292789459228516"},{"X":"52.7283916301808","Y":"8.30514907836914"},{"X":"52.72402521231565","Y":"8.320941925048828"},{"X":"52.717162815135964","Y":"8.328838348388672"},{"X":"52.657851719462975","Y":"8.327465057373047"},{"X":"52.652853422873996","Y":"8.332958221435547"},{"X":"52.6480628523967","Y":"8.345661163330078"},{"X":"52.6509789143232","Y":"8.36111068725586"},{"X":"52.65639394198803","Y":"8.36832046508789"},{"X":"52.71820264168893","Y":"8.369007110595703"},{"X":"52.72423314689028","Y":"8.377933502197266"},{"X":"52.727975799697404","Y":"8.389263153076172"},{"X":"52.7281837154348","Y":"8.402652740478516"},{"X":"52.649520907667934","Y":"8.400249481201172"},{"X":"52.649312617034255","Y":"8.43149185180664"},{"X":"52.73317339571309","Y":"8.433551788330078"},{"X":"52.73317339571309","Y":"8.448314666748047"},{"X":"52.688245712958974","Y":"8.472347259521484"},{"X":"52.724649013065175","Y":"8.245410919189453"}]]; 

这个坐标我不能在 canvas 上显示,因为它太小了所以我写:

function drawPolyline(pts){
  ctx.beginPath();

  function endProp( mathFunc, array, property ) {
    return Math[ mathFunc ].apply(array, array.map(function ( item ) {
        return item[ property ];
    }));
}

var maxY = endProp( "max", pts[0], "Y" ), // 8.389
    minY = endProp( "min", pts[0], "Y" );

var maxX = endProp( "max", pts[0], "X" ), // 8.389
    minX = endProp( "min", pts[0], "X" );

  for(var i=1;i<pts[0].length;i++){
    var a = (((pts[0][i].X - minX) * (1000 - 100)) / (maxX - minX)) + 0;
    var b = (((pts[0][i].Y - minY) * (600 - 0)) / (maxY - minY)) + 0;
    ctx.lineTo(a,b);
  }
  ctx.stroke();


}

使用此函数,我可以从 pts 获得 X 和 Y 的最小值和最大值。 然后我像这样转换坐标:

NewValue = (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin

所以这是一样的:

for(var i=1;i<pts[0].length;i++){
        var a = (((pts[0][i].X - minX) * (1000 - 100)) / (maxX - minX)) + 0;
        var b = (((pts[0][i].Y - minY) * (600 - 0)) / (maxY - minY)) + 0;
        ctx.lineTo(a,b);
      }

使用此代码我可以转换坐标并轻松地在 CANVAS 上显示它们。

之后我有:

ctx.beginPath();
      ctx.moveTo(470, 300);
      ctx.lineTo(530, 300);
ctx.lineWidth = 5;
ctx.strokeStyle = 'red';
ctx.stroke();

ctx.fillStyle="blue";
ctx.beginPath();
ctx.moveTo(500,260);
ctx.lineTo(530,280);
ctx.lineTo(470,280);
ctx.closePath();
ctx.fill();

使用此代码,我在 canvas 的中心绘制三角形,正如您从顶部的演示 link 中看到的那样。

现在, 我需要转换和旋转我从 pts 创建的路径,所以我需要最后一个点位于中心,以便将我的路径与中心的三角形结合起来,如下所示:

所以我需要旋转完整路径以将其与中心三角形合并。请帮忙。

有人知道吗?

这是一种方法:

  • 调整路径中的所有点,使端点位于 [0,0]。您可以通过从路径中的每个点减去结尾的 x,y 来实现。

  • context.translate 到您 canvas 的中心。这会将路径的终点拉到 canvas.

  • 的中心
  • context.rotate 旋转路径的最后一条线段以从底部接近端点的角度。您可以使用 Math.atan2 获得最后一条线段的角度,然后计算所需的旋转角度为: -segmentAngle-PI/2

这是示例代码和演示:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var canvas1=document.getElementById("canvas1");
var ctx1=canvas1.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;


var cx=cw/2;
var cy=ch/2;

var pts=[];
for(var i=0;i<10;i++){
  var x=Math.random()*100-50+100;
  var y=Math.random()*100-50+100;
  pts.push({x:x,y:y});
}

drawPts(pts);
drawPts1(pts);


function drawPts(pts){

  var lastPt=pts[pts.length-1];
  var nextToLastPt=pts[pts.length-2];
  var dx=lastPt.x-nextToLastPt.x;
  var dy=lastPt.y-nextToLastPt.y;
  var angle=Math.atan2(dy,dx);
  var rotation=-angle-Math.PI/2;

  ctx.beginPath();
  ctx.arc(cx,cy,5,0,Math.PI*2);
  ctx.closePath();
  ctx.fillStyle='red';
  ctx.fill();

  var pts1=[];
  var lp=pts[pts.length-1];
  for(var i=0;i<pts.length;i++){
    pts1.push({x:pts[i].x-lp.x,y:pts[i].y-lp.y});
  }

  ctx.save();

  ctx.translate(cx,cy);
  ctx.rotate(rotation);

  ctx.beginPath();
  ctx.moveTo(pts1[0].x,pts1[0].y);
  for(var i=1;i<pts1.length;i++){
    ctx.lineTo(pts1[i].x,pts1[i].y);
  }
  ctx.stroke();

  ctx.beginPath();
  ctx.arc(pts1[pts1.length-1].x,pts1[pts1.length-1].y,2,0,Math.PI*2);
  ctx.closePath();
  ctx.fillStyle='blue';
  ctx.fill();

  ctx.restore();
}



function drawPts1(pts){

  var lastPt=pts[pts.length-1];

  ctx1.beginPath();
  ctx1.arc(cw/2,ch/2,5,0,Math.PI*2);
  ctx1.closePath();
  ctx1.fillStyle='red';
  ctx1.fill();

  ctx1.save();

  ctx1.beginPath();
  ctx1.moveTo(pts[0].x,pts[0].y);
  for(var i=1;i<pts.length;i++){
    ctx1.lineTo(pts[i].x,pts[i].y);
  }
  ctx1.stroke();

  ctx1.beginPath();
  ctx1.arc(lastPt.x,lastPt.y,2,0,Math.PI*2);
  ctx1.closePath();
  ctx1.fillStyle='blue';
  ctx1.fill();

  ctx1.restore();
}
body{ background-color: ivory; padding:10px; }
canvas{border:1px solid red;}
<h4>Left: original path.<br>Right: path endpoint moved to canvas centerpoint and approaching from bottom.<br>Red dot is canvas centerpoint<br>Blue dot is path endpoint</h4>
<canvas id="canvas1" width=350 height=350></canvas>
<canvas id="canvas" width=350 height=350></canvas>