首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在两条线交点之间创建一条具有度的曲线。

在两条线交点之间创建一条具有度的曲线。
EN

Stack Overflow用户
提问于 2021-11-29 21:07:38
回答 1查看 125关注 0票数 0

我想制作一片枫叶,就像加拿大国旗上的枫叶,但是当这些线相交时,我有一个问题,那就是曲线只在相交处,并在两条线之间产生一定的程度。我的意思是,在我所看到的图片中,A,B,C等显示了:

加拿大旗曲线

这是我迄今为止创建的函数:

代码语言:javascript
复制
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();
  }  
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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,复制并粘贴到行对象中即可。只要两条线相交,长度就无关紧要。

代码语言:javascript
复制
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)
代码语言:javascript
复制
<canvas id='canvas'></canvas>

在获得了两行的精确x1、y1、x2、y2坐标之后,我们就可以通过行相交函数运行它们以获得CP1。

代码语言:javascript
复制
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)
代码语言:javascript
复制
<canvas id='canvas'></canvas>

正如您现在看到的,这个函数只是一个控制台,记录在arcTo()中作为arcTo()使用的坐标。现在你可以正确地画线了。请注意,arcTo()将绘制一条直线连接到绘图中的前一点。这意味着我们不需要使用'lineTo()‘从前一点到弧开始,只是从弧结束到下一个点。

代码语言:javascript
复制
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()
代码语言:javascript
复制
<canvas id='canvas'></canvas>

当你穿过整片叶子时,最终的产品将会是这样的。助手函数已经被移除,因为现在我已经有了数字,所以不需要它们。创建这样的绘图方式将有助于减少问题时,试图填补它。

代码语言:javascript
复制
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()
代码语言:javascript
复制
<canvas id='canvas'></canvas>

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70161332

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档