我想制作一片枫叶,就像加拿大国旗上的枫叶,但是当这些线相交时,我有一个问题,那就是曲线只在相交处,并在两条线之间产生一定的程度。我的意思是,在我所看到的图片中,A,B,C等显示了:
这是我迄今为止创建的函数:
function drawMapleLeaf (ctx,x,y,width,height) {
let rx = width;
let ry = height;
let xc = x + rx / 2;
let yc = y + height;
let xPoints = new Array(26).fill(0);
let yPoints = new Array(26).fill(0);
xPoints [0] = (xc + rx * 0.021423);
yPoints [0] = (yc - ry * 0.215686);
xPoints [1] = (xc + rx * 0.270780);
yPoints [1] = (yc - ry * 0.203804);
xPoints [2] = (xc + rx * 0.271820);
yPoints [2] = (yc - ry * 0.295752);
xPoints [3] = (xc + rx * 0.482015);
yPoints [3] = (yc - ry * 0.411765);
xPoints [4] = (xc + rx * 0.443046);
yPoints [4] = (yc - ry * 0.483267);
xPoints [5] = (xc + rx * 0.500000);
yPoints [5] = (yc - ry * 0.587435);
xPoints [6] = (xc + rx * 0.363353);
yPoints [6] = (yc - ry * 0.619576);
xPoints [7] = (xc + rx * 0.342287);
yPoints [7] = (yc - ry * 0.693849);
xPoints [8] = (xc + rx * 0.153596);
yPoints [8] = (yc - ry * 0.612537);
xPoints [9] = (xc + rx * 0.201601);
yPoints [9] = (yc - ry * 0.918462);
xPoints [10] = (xc + rx * 0.093001);
yPoints [10] = (yc - ry * 0.894514);
xPoints [11] = xc;
yPoints [11] = (yc - ry);
xPoints [12] = (xc - rx * 0.093001);
yPoints [12] = yPoints [10];
xPoints [13] = (xc - rx * 0.201601);
yPoints [13] = yPoints [9];
xPoints [14] = (xc - rx * 0.153596);
yPoints [14] = yPoints [8];
xPoints [15] = (xc - rx * 0.342287);
yPoints [15] = yPoints [7];
xPoints [16] = (xc - rx * 0.363353);
yPoints [16] = yPoints [6];
xPoints [17] = (xc - rx * 0.500000);
yPoints [17] = yPoints [5];
xPoints [18] = (xc - rx * 0.443046);
yPoints [18] = yPoints [4];
xPoints [19] = (xc - rx * 0.482015);
yPoints [19] = yPoints [3];
xPoints [20] = (xc - rx * 0.271820);
yPoints [20] = yPoints [2];
xPoints [21] = (xc - rx * .2707796);
yPoints [21] = yPoints [1];
xPoints [22] = (xc - rx * 0.021423);
yPoints [22] = yPoints [0];
xPoints [23] = xPoints [22];
yPoints [23] = yc;
xPoints [24] = xPoints [0];
yPoints [24] = yPoints [23];
xPoints [25] = xPoints [0];
yPoints [25] = yPoints [0];
ctx.beginPath();
ctx.moveTo(xPoints[0],yPoints[0]);
for(let i=1;i<xPoints.length;i++){
ctx.lineTo(xPoints[i],yPoints[i]);
}
//ctx.stroke();
ctx.fillStyle='red';
ctx.fill();
} 发布于 2021-12-03 08:19:02
我会尽量让这件事变得简单一些,但可能需要一些人来理解。(最后一段中的最后代码)
首先,看看arcTo() works https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-arcto-dev是如何
您会注意到您有一个起点和两个控制点(CP)。CP1是这些线相交的地方。CP2是第二行的起点。
也就是说,如果我们取两行,并在它们上运行一个相交公式,我们就可以得到CP1。CP2只是第二行的起点。
在下面的片段中,line1的顶部(第一点)是叶子的顶部。第2行的第一点是第二叶的尖端。对于每一行,x2和y2都是使用getCoords()函数导出的。因为你的图表有一个不同的坐标系,你必须取它给出的角度,然后从360减去它。所以line1的角度是63度,line2是150度。
只需插入数字,一旦获得console.log() for x2和y2,复制并粘贴到行对象中即可。只要两条线相交,长度就无关紧要。
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
canvas.width = 800;
canvas.height = 800;
let line1 = {x1: 200, y1: 50, x2: 290.79809994790935, y2: 228.20130483767355}
let line2 = {x1: 275, y1: 99, x2: 101.79491924311225, y2: 199}
function getCoords(x1, y1, length, angle) {
let rads = angle * (Math.PI/180);
x2 = x1 + length * Math.cos(rads);
y2 = y1 + length * Math.sin(rads);
console.log(x2, y2);
}
//line2 x, y, length, angle
getCoords(275, 99, 200, 150)
function drawLines(line1, line2) {
ctx.beginPath()
ctx.moveTo(line1.x1, line1.y1)
ctx.lineTo(line1.x2, line1.y2)
ctx.moveTo(line2.x1, line2.y1)
ctx.lineTo(line2.x2, line2.y2)
ctx.stroke()
}
drawLines(line1, line2)<canvas id='canvas'></canvas>
在获得了两行的精确x1、y1、x2、y2坐标之后,我们就可以通过行相交函数运行它们以获得CP1。
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
canvas.width = 800;
canvas.height = 800;
let line1 = {x1: 200, y1: 50, x2: 290.79809994790935, y2: 228.20130483767355}
let line2 = {x1: 275, y1: 99, x2: 101.79491924311225, y2: 199}
function getCoords(x1, y1, length, angle) {
let rads = angle * (Math.PI/180);
x2 = x1 + length * Math.cos(rads);
y2 = y1 + length * Math.sin(rads);
console.log(x2, y2);
}
//line2 x, y, length, angle
getCoords(275, 99, 200, 150)
function lineSegmentsIntersect(line1, line2) {
let a_dx = line1.x2 - line1.x1;
let a_dy = line1.y2 - line1.y1;
let b_dx = line2.x2 - line2.x1;
let b_dy = line2.y2 - line2.y1;
let s =
(-a_dy * (line1.x1 - line2.x1) + a_dx * (line1.y1 - line2.y1)) /
(-b_dx * a_dy + a_dx * b_dy);
let t =
(+b_dx * (line1.y1 - line2.y1) - b_dy * (line1.x1 - line2.x1)) /
(-b_dx * a_dy + a_dx * b_dy);
if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {
console.log('control x: '+Math.round(line1.x1 + t * (line1.x2 - line1.x1)));
console.log('control y: '+Math.round( line1.y1 + t * (line1.y2 - line1.y1)));
}
}
//once both lines have acurate starting and end points plug them in here
//in the console you will see CP1 for acrTo()
lineSegmentsIntersect(line1, line2)
function drawLines(line1, line2) {
ctx.beginPath()
ctx.moveTo(line1.x1, line1.y1)
ctx.lineTo(line1.x2, line1.y2)
ctx.moveTo(line2.x1, line2.y1)
ctx.lineTo(line2.x2, line2.y2)
ctx.stroke()
}
drawLines(line1, line2)<canvas id='canvas'></canvas>
正如您现在看到的,这个函数只是一个控制台,记录在arcTo()中作为arcTo()使用的坐标。现在你可以正确地画线了。请注意,arcTo()将绘制一条直线连接到绘图中的前一点。这意味着我们不需要使用'lineTo()‘从前一点到弧开始,只是从弧结束到下一个点。
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
canvas.width = 800;
canvas.height = 800;
//let line1 = {x1: 200, y1: 50, x2: 290.79809994790935, y2: 228.20130483767355}
//let line2 = {x1: 275, y1: 99, x2: 101.79491924311225, y2: 199}
function drawLines() {
ctx.beginPath()
ctx.moveTo(200, 50) //Just a starting point
ctx.arcTo(236, 121, 275, 99, 13) //(control x, control y, start of line2 x, start of line2 y, radius)
ctx.lineTo(275, 99) //(start of line2)
ctx.stroke()
}
drawLines()<canvas id='canvas'></canvas>
当你穿过整片叶子时,最终的产品将会是这样的。助手函数已经被移除,因为现在我已经有了数字,所以不需要它们。创建这样的绘图方式将有助于减少问题时,试图填补它。
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
canvas.width = 800;
canvas.height = 800;
function drawShape() {
ctx.fillStyle = 'red';
ctx.beginPath()
ctx.moveTo(200, 50)
ctx.arcTo(243, 134, 275, 99, 13);
ctx.lineTo(275, 99)
ctx.arcTo(250, 226, 308, 164.5, 13)
ctx.lineTo(308, 164.5)
ctx.arcTo(321, 194, 380, 181.5, 13)
ctx.lineTo(380, 181.5)
ctx.arcTo(360, 244, 386, 256.5, 13)
ctx.lineTo(386, 256.5)
ctx.arcTo(288, 336, 301.5, 372, 13)
ctx.lineTo(301.5, 372)
ctx.arcTo(204, 355, 209, 453, 19)
ctx.lineTo(209, 453)
ctx.lineTo(191, 453)
//..you need to finish
ctx.closePath()
ctx.fill()
ctx.stroke()
}
drawShape()<canvas id='canvas'></canvas>
https://stackoverflow.com/questions/70161332
复制相似问题