[英]smoother lineWidth changes in canvas lineTo
所以我試圖在HTML5畫布中創建一個繪圖工具,其中筆觸的權重增加了您移動鼠標的速度,而減少了移動的速度。 我正在使用ctx.lineTo(),但是在我第一次嘗試時發現,如果我移動得太快,則厚度的變化會記錄為明顯的平方增量(而不是平滑的重量增加)
所以我將ctx.lineJoin和ctx.lineCap更改為“ round”,效果更好
但這仍然不如我所願。 我正在拍攝這樣的東西
關於如何使體重變化更平穩的任何建議都將是很棒的! 這是一個有效的演示: http : //jsfiddle.net/0fhag522/1/
這是我的“點”對象(pen)和繪圖功能的預覽:
var dot = {
start: false,
weight: 1,
open: function(x,y){
ctx.lineJoin = "round";
ctx.lineCap = "round";
ctx.beginPath();
ctx.moveTo(x,y);
},
connect: function(x,y){
ctx.lineWidth = this.weight;
ctx.lineTo(x,y);
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.moveTo(x,y);
},
close: function(){
ctx.closePath();
}
}
function draw(){
if(down){
if(!dot.start){
dot.close();
prevx = mx; prevy = my;
dot.open(mx,my);
dot.start=true;
}
else {
var dx = (prevx>mx) ? prevx-mx : mx-prevx;
var dy = (prevy>my) ? prevy-my : my-prevy;
dot.weight = Math.abs(dx-dy)/2;
dot.connect( mx,my );
prevx = mx; prevy = my;
}
}
}
由於畫布沒有寬度可變的線,因此必須在線點之間繪制閉合路徑。
但是,這留下了可見的對接。
要平滑對接,可以在每個接點處繪制一個圓。
這是示例代碼和演示:
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); var cw = canvas.width; var ch = canvas.height; var $canvas = $("#canvas"); var canvasOffset = $canvas.offset(); var offsetX = canvasOffset.left; var offsetY = canvasOffset.top; var scrollX = $canvas.scrollLeft(); var scrollY = $canvas.scrollTop(); var isDown = false; var startX; var startY; var PI = Math.PI; var halfPI = PI / 2; var points = []; $("#canvas").mousedown(function(e) { handleMouseDown(e); }); function handleMouseDown(e) { e.preventDefault(); e.stopPropagation(); mx = parseInt(e.clientX - offsetX); my = parseInt(e.clientY - offsetY); var pointsLength = points.length; if (pointsLength == 0) { points.push({ x: mx, y: my, width: Math.random() * 5 + 2 }); } else { var p0 = points[pointsLength - 1]; var p1 = { x: mx, y: my, width: Math.random() * 5 + 2 }; addAngle(p0, p1); p0.angle = p1.angle; addEndcap(p0); addEndcap(p1); points.push(p1); extendLine(p0, p1); } } function addAngle(p0, p1) { var dx = p1.x - p0.x; var dy = p1.y - p0.y; p1.angle = Math.atan2(dy, dx); } function addEndcap(p) { p.x0 = px + p.width * Math.cos(p.angle - halfPI); p.y0 = py + p.width * Math.sin(p.angle - halfPI); p.x1 = px + p.width * Math.cos(p.angle + halfPI); p.y1 = py + p.width * Math.sin(p.angle + halfPI); } function extendLine(p0, p1) { ctx.beginPath(); ctx.moveTo(p0.x0, p0.y0); ctx.lineTo(p0.x1, p0.y1); ctx.lineTo(p1.x1, p1.y1); ctx.lineTo(p1.x0, p1.y0); ctx.closePath(); ctx.fillStyle = 'blue'; ctx.fill(); // draw a circle to cover the butt-joint ctx.beginPath(); ctx.moveTo(p1.x, p1.y); ctx.arc(p1.x, p1.y, p1.width, 0, Math.PI * 2); ctx.closePath(); ctx.fill(); }
body{ background-color: ivory; } #canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <h4>Click to add line segments.</h4> <canvas id="canvas" width=300 height=300></canvas>
這是創建帶有圓形線帽的 生長線的簡單功能:
/* * this function returns a Path2D object * the path represents a growing line between two given points */ function createGrowingLine (x1, y1, x2, y2, startWidth, endWidth) { // calculate direction vector of point 1 and 2 const directionVectorX = x2 - x1, directionVectorY = y2 - y1; // calculate angle of perpendicular vector const perpendicularVectorAngle = Math.atan2(directionVectorY, directionVectorX) + Math.PI/2; // construct shape const path = new Path2D(); path.arc(x1, y1, startWidth/2, perpendicularVectorAngle, perpendicularVectorAngle + Math.PI); path.arc(x2, y2, endWidth/2, perpendicularVectorAngle + Math.PI, perpendicularVectorAngle); path.closePath(); return path; } const ctx = myCanvas.getContext('2d'); // create a growing line between P1(10, 10) and P2(250, 100) // with a start line width of 10 and an end line width of 50 let line1 = createGrowingLine(10, 10, 250, 100, 10, 50); ctx.fillStyle = 'green'; // draw growing line ctx.fill(line1);
<canvas width="300" height="150" id="myCanvas"></canvas>
說明:函數createGrowingLine
通過以下方法在兩個給定點之間構造形狀:
如果您不想使用圓角線帽,請使用以下功能:
/* * this function returns a Path2D object * the path represents a growing line between two given points */ function createGrowingLine (x1, y1, x2, y2, startWidth, endWidth) { const startRadius = startWidth/2; const endRadius = endWidth/2; // calculate direction vector of point 1 and 2 let directionVectorX = x2 - x1, directionVectorY = y2 - y1; // calculate vector length const directionVectorLength = Math.hypot(directionVectorX, directionVectorY); // normalize direction vector (and therefore also the perpendicular vector) directionVectorX = 1/directionVectorLength * directionVectorX; directionVectorY = 1/directionVectorLength * directionVectorY; // construct perpendicular vector const perpendicularVectorX = -directionVectorY, perpendicularVectorY = directionVectorX; // construct shape const path = new Path2D(); path.moveTo(x1 + perpendicularVectorX * startRadius, y1 + perpendicularVectorY * startRadius); path.lineTo(x1 - perpendicularVectorX * startRadius, y1 - perpendicularVectorY * startRadius); path.lineTo(x2 - perpendicularVectorX * endRadius, y2 - perpendicularVectorY * endRadius); path.lineTo(x2 + perpendicularVectorX * endRadius, y2 + perpendicularVectorY * endRadius); path.closePath(); return path; } const ctx = myCanvas.getContext('2d'); // create a growing line between P1(10, 10) and P2(250, 100) // with a start line width of 10 and an end line width of 50 let line1 = createGrowingLine(10, 10, 250, 100, 10, 50); ctx.fillStyle = 'green'; // draw growing line ctx.fill(line1);
<canvas width="300" height="150" id="myCanvas"></canvas>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.