簡體   English   中英

如何以編程方式繪制粗線 JavaScript?

[英]How to programmatically draw a thick line JavaScript?

我正在嘗試使用用戶可以在畫布元素上繪制的動態線來定義racecourse 所以當畫線時,程序應該為其添加邊線,如下圖所示:

結果的想法

我已經通過使用線法線設法模仿了這個想法,但無法正確完成。 目前,我將點放在線法線方向的線的中間,並使用這些點繪制輪廓。 雖然在大轉彎的情況下生成的線相對平滑,但急轉彎往往會產生環路。

如下圖所示:

結果的當前狀態

這是為上面的邊線生成點的當前代碼(我使用的是 p5.js JavaScript 庫):

 var sketch = function (p) { with(p) { let handpoints; let walkhandpoints; let collect; let parsepath; let shapse; let step; let tmp; let dorender; let lineoffset; p.setup = function() { createCanvas(600, 600); handpoints = []; walkhandpoints = 10; collect = true; parsepath = false; shapes = []; step = 2; tmp = []; dorender = true; lineoffset = 15; }; p.draw = function() { if(dorender) { background(220); update(); for (let shape of shapes) { shape.show(); } } }; function update() { if (mouseIsPressed) { if (collect) { let mouse = createVector(mouseX, mouseY); handpoints.push(mouse); Shape.drawPath(handpoints); parsepath = true; } } else if (parsepath) { let tmp1 = Shape.cleanPath(handpoints, step); let s1 = new Shape(tmp1, 1, 'line', color(175)); shapes.push(s1); let tmp2 = Line.sidePoints(tmp1, lineoffset); let s2 = new Shape(tmp2.sideA, 1, 'line', color(175,120,0)); let s3 = new Shape(tmp2.sideB, 1, 'line', color(175,0, 120)); shapes.push(s2); shapes.push(s3); handpoints = []; parsepath = false; //dorender = false; } } class Shape { constructor(points, mag, type = 'line', shader = color(200, 0, 100)) { this.points = points.slice().map(item => item.copy()); this.type = type; this.mag = mag; this.shader = shader; } static cleanPath(points, step) { let tmp = []; let output = []; for (let i = 1; i < points.length; i++) { let prev = points[i - 1]; let curr = points[i]; if (!prev.equals(curr)) { tmp.push(prev.copy()) if (i === points.length - 1) { tmp.push(curr.copy()) } } } for (let i = 0; i < tmp.length; i++) { if(i % step === 0) { output.push(tmp[i]); } } output.push(output[0]); return output; } static drawPath(points, mag = 1, type = 'line', shader = color(175)) { let s = new Shape(points, mag, type, shader); s.show(); } show() { for (let i = 0; i < this.points.length; i++) { if (this.type === 'line' && i > 0) { let prev = this.points[i - 1]; let curr = this.points[i]; strokeWeight(this.mag); stroke(this.shader); line(prev.x, prev.y, curr.x, curr.y); } else if (this.type === 'point') { noStroke(); fill(this.shader); ellipse(this.points[i].x, this.points[i].y, this.mag * 2, this.mag * 2); } } } } class Line { static sidePoints(points, lineoffset) { let sideA = []; let sideB = []; for(let i = 1; i < points.length; i++) { // take consecutive points let prev = points[i-1]; let curr = points[i]; // calculate normals let dx = curr.x-prev.x; let dy = curr.y-prev.y; let a = createVector(-dy, dx).normalize(); let b = createVector(dy, -dx).normalize(); // calculate midway of the two points let px = (prev.x+curr.x)/2; let py = (prev.y+curr.y)/2; let p = createVector(px,py); // put created points back along drawed line a.mult(lineoffset).add(p); b.mult(lineoffset).add(p); sideA.push(a); sideB.push(b); } // close paths if(!sideA[0].equals(sideA[sideA.length-1])) { sideA.push(sideA[0]); } if(!sideB[0].equals(sideB[sideB.length-1])) { sideB.push(sideB[0]); } return {sideA, sideB}; } } } }; let node = document.createElement('div'); window.document.getElementById('p5-container').appendChild(node); new p5(sketch, node);
 body { background-color:#ffffff; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.js"></script> <div id="p5-container"></div>

  • 首先,我想找到一種方法在繪制線的相應角點中繪制這些點,因此當繪制的線只有幾個點時,輪廓將保留繪制的形狀。
  • 其次,是否有一些好的方法可以減少有幾個點的區域上的點,以減少小角落中的循環和生成線中的其他類型錯誤?
  • 想法是獲取線的點,因此如果賽車速度矢量穿過它,則很容易檢測到線相交。
  • 不幸的是,我對數學符號不是很熟悉,所以如果有一些花哨的數學可以完成這項工作,請嘗試使用它們的易於理解的版本。

將來,請嘗試發布一個最小的示例 當您發布代碼時,我無法運行您的代碼。

話雖如此,您可以考慮的一種選擇是使用strokeWeight()函數以不同的寬度繪制路徑。 下面是一個例子:

const path = [];

function setup() {
  createCanvas(400, 400);
  
  // Add some default points to the path.
  path.push(createVector(0, 0));
  path.push(createVector(width/4, height/4));
}

function draw() {
  background(220);
  
  // Draw the path with a thick gray line.
  strokeWeight(50);
  stroke(200);
  for(let i = 1; i < path.length; i++){
    const prevPoint = path[i-1];
    const nextPoint = path[i];
    line(prevPoint.x, prevPoint.y, nextPoint.x, nextPoint.y);
  }
 
  // Draw the path with a thin black line.
  strokeWeight(1);
  stroke(0);
  for(let i = 1; i < path.length; i++){
    const prevPoint = path[i-1];
    const nextPoint = path[i];    
     line(prevPoint.x, prevPoint.y, nextPoint.x, nextPoint.y);
  }
}

// Add a point to the path when the user clicks.
function mousePressed(){
 path.push(createVector(mouseX, mouseY));
}

小路

這里的技巧是分兩次繪制路徑。 首先使用粗線繪制路徑,然后再次繪制路徑,這次使用細線。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM