我正在研究一个小脚本,它应该(最终)在两个路径之间创建一个动画补间动画。它还有很长的路要走,而且我确信有些东西可以做得更好,但这就是我所处的位置以及我遇到的问题:
我想将顶点从矩形的中心(形状一)向外投影到blob的路径上(形状二)。见下图。
我的最终目标是将其作为一个通用脚本,您可以在其中插入形状一和形状二的点,并使它们相互变形。这只是为了我自己的利益,所以我不想在已经完成的情况下使用插件。谢谢!
HTML:
<canvas id="canvas" width="100%" height="100%">
Canvas is not supported.
</canvas>
JS:
$(function() {
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
baseX = 500,
baseY = 350;
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
var Shape = function(baseX, baseY, points) {
this.baseX = baseX;
this.baseY = baseY;
this.points = points;
this.drawPoints = function(stroke) {
var points = this.points;
var rad = 5;
for (i=0; i<points.length; i++) {
ctx.beginPath();
ctx.fillStyle = 'gray';
var splitPoints = points[i].split(',');
switch(splitPoints[0]) {
case 'm':
ctx.arc(splitPoints[1], splitPoints[2], rad, 2 * Math.PI, false);
if (stroke === true) {
ctx.fill();
}
break;
case 'l':
ctx.arc(splitPoints[1], splitPoints[2], rad, 2 * Math.PI, false);
if (stroke === true) {
ctx.fill();
}
break;
case 'b':
ctx.arc(splitPoints[5], splitPoints[6], rad, 2 * Math.PI, false);
if (stroke === true) {
ctx.fill();
}
break;
}
}
ctx.closePath();
}
this.drawPath = function(stroke) {
var points = this.points;
ctx.beginPath();
for (i=0; i<points.length; i++) {
var splitPoints = points[i].split(',');
switch(splitPoints[0]) {
case 'm':
ctx.moveTo(splitPoints[1], splitPoints[2]);
break;
case 'l':
ctx.lineTo(splitPoints[1], splitPoints[2]);
break;
case 'b':
ctx.bezierCurveTo(splitPoints[1], splitPoints[2], splitPoints[3], splitPoints[4], splitPoints[5], splitPoints[6]);
break;
}
}
ctx.closePath();
if (stroke === true) {
ctx.stroke();
}
}
}
var rectanglePoints = [];
//type, ptx1, pty1, ptx2, pty2...
rectanglePoints.push(`m, ${baseX + 200}, ${baseY - 100}`);
rectanglePoints.push(`l, ${baseX + 200}, ${baseY + 100}`);
rectanglePoints.push(`l, ${baseX - 200}, ${baseY + 100}`);
rectanglePoints.push(`l, ${baseX - 200}, ${baseY - 100}`);
var rectangle = new Shape(baseX, baseY, rectanglePoints);
rectangle.drawPath(true);
rectangle.drawPoints(true);
var blobPoints = [];
//type, ptx1, pty1, ptx2, pty2...
blobPoints.push(`m, ${baseX + 100}, ${baseY - 300}`);
blobPoints.push(`b, ${baseX + 300}, ${baseY - 375}, ${baseX + 250}, ${baseY - 215}, ${baseX + 250}, ${baseY - 200}`);
blobPoints.push(`b, ${baseX + 150}, ${baseY + 150}, ${baseX + 200}, ${baseY + 150}, ${baseX + 250}, ${baseY + 200}`);
blobPoints.push(`b, ${baseX + 350}, ${baseY + 300}, ${baseX + 300}, ${baseY + 400}, ${baseX + 50}, ${baseY + 300}`);
blobPoints.push(`b, ${baseX}, ${baseY + 250}, ${baseX}, ${baseY + 250}, ${baseX - 100}, ${baseY + 200}`);
blobPoints.push(`b, ${baseX - 350}, ${baseY + 175}, ${baseX - 350}, ${baseY + 175}, ${baseX - 400}, ${baseY}`);
blobPoints.push(`b, ${baseX - 400}, ${baseY - 300}, ${baseX - 200}, ${baseY - 100}, ${baseX}, ${baseY - 250}`);
var blob = new Shape(baseX, baseY, blobPoints);
blob.drawPath(true);
blob.drawPoints(true);
var findCentroid = function(points) {
var xSum = 0;
var ySum = 0;
var xPoints = 0;
var yPoints = 0;
var centroid = [];
for (i=0; i<points.length; i++) {
var splitPoints = points[i].split(',');
switch(splitPoints[0]) {
case 'm':
xSum += splitPoints[1]/1;
ySum += splitPoints[2]/1;
xPoints += 1;
yPoints += 1;
break;
case 'l':
xSum += splitPoints[1]/1;
ySum += splitPoints[2]/1;
xPoints += 1;
yPoints += 1;
break;
case 'b':
xSum += splitPoints[1]/1;
ySum += splitPoints[2]/1;
xPoints += 1;
yPoints += 1;
break;
}
}
centroid.push(xSum/xPoints);
centroid.push(ySum/yPoints);
return centroid;
}
var projectPoints = function(shapeOne, shapeTwo) {
var pointsOne = shapeOne.points;
var pointsTwo = shapeTwo.points;
var centroid = findCentroid(rectanglePoints);
for (var i=0; i<pointsOne.length; i++) {
//ispointinstroke would be good but it doesn't have wide browser support. Use inpointinpath
var splitPoints = pointsOne[i].split(',');
switch(splitPoints[0]) {
case 'm':
x = splitPoints[1]/1;
y = splitPoints[2]/1;
break;
case 'l':
x = splitPoints[1]/1;
y = splitPoints[2]/1;
break;
case 'b':
x = splitPoints[5]/1;
y = splitPoints[6]/1;
break;
}
//get vector between the centroid and the current x,y value
var vectorX = x - centroid[0]/1;
var vectorY = y - centroid[1]/1;
//increment resolution
var incRes = 100;
termX = vectorX/incRes;
termY = vectorY/incRes;
shapeTwo.drawPath();
while (ctx.isPointInPath(centroid[0]/1 + termX, centroid[0]/1 + termY)) {
termX += vectorX/incRes;
termY += vectorY/incRes;
console.log(termX);
console.log(termY);
}
ctx.beginPath();
ctx.moveTo(centroid[0],centroid[1]);
ctx.lineTo(centroid[0] + termX, centroid[1] + termY);
ctx.stroke();
ctx.closePath();
}
}
projectPoints(rectangle, blob);
var centroid = findCentroid(rectanglePoints);
ctx.beginPath();
ctx.arc(centroid[0], centroid[1], 10, 2 * Math.PI, false);
ctx.fill();
ctx.closePath();
});
的jsfiddle: https://jsfiddle.net/6g076jw0/1/