可以使用基數樣來消除這樣的臺詞:
的原因是因爲@Pointy已經解釋,由於瀏覽器的速度有多快能夠響應事件(mousemove
)。有一個名爲Pointer Lock API的API,它可能有助於在將來解決這個問題,因爲它更低級,但現在我們需要使用算法來平滑出現分段的線條。
除了平滑處理之外,還有細節平滑處理,點減少處理,錐度處理等可以應用於改善效果的東西。
但是在這種特殊情況下,您可以使用以下函數作爲畫布的擴展。請撥打電話:
ctx.curve(myPointArray, tension, segments);
ctx.stroke();
該數組包含像[x1, y1, x2, y2, ... xn, yn
那樣排列的x和y點。
tension
的典型值爲0.5。 segments
(默認16)是可選的。
越緊張,曲線越圓。分段是數組中每個點之間的分辨率。對於繪圖應用程序,值5可能正常工作(更少的結果點)。
爲了讓它更好地工作,您可以在繪製原始線條的單獨畫布上註冊點。在鼠標上方處理具有此功能的行並將其繪製到主畫布上,然後清除繪圖畫布。
該功能是高度優化的 - 它還會返回已處理的點,因此您可以存儲結果而不是每次重新處理。
/**
* curve() by Ken Fyrstenberg (c) 2013 Epistemex
* See Code Project for full source:
* http://www.codeproject.com/Tips/562175/Draw-Smooth-Lines-on-HTML5-Canvas
*/
CanvasRenderingContext2D.prototype.curve = function(pts, ts, nos) {
nos = (typeof numOfSegments === 'undefined') ? 16 : nos;
var _pts = [], res = [], // clone array
x, y, // our x,y coords
t1x, t2x, t1y, t2y, // tension vectors
c1, c2, c3, c4, // cardinal points
st, st2, st3, st23, st32, // steps
t, i, l = pts.length,
pt1, pt2, pt3, pt4;
_pts.push(pts[0]); //copy 1. point and insert at beginning
_pts.push(pts[1]);
_pts = _pts.concat(pts);
_pts.push(pts[l - 2]); //copy last point and append
_pts.push(pts[l - 1]);
this.moveTo(pts[0], pts[1])
for (i = 2; i < l; i+=2) {
pt1 = _pts[i];
pt2 = _pts[i+1];
pt3 = _pts[i+2];
pt4 = _pts[i+3];
// calc tension vectors
t1x = (pt3 - _pts[i-2]) * ts;
t2x = (_pts[i+4] - pt1) * ts;
t1y = (pt4 - _pts[i-1]) * ts;
t2y = (_pts[i+5] - pt2) * ts;
for (t = 0; t <= nos; t++) {
// pre-calc steps
st = t/nos;
st2 = st * st;
st3 = st2 * st;
st23 = st3 * 2;
st32 = st2 * 3;
// calc cardinals
c1 = st23 - st32 + 1;
c2 = st32 - st23;
c3 = st3 - 2 * st2 + st;
c4 = st3 - st2;
res.push(c1 * pt1 + c2 * pt3 + c3 * t1x + c4 * t2x);
res.push(c1 * pt2 + c2 * pt4 + c3 * t1y + c4 * t2y);
} //for t
} //for i
l = res.length;
for(i=0;i<l;i+=2) this.lineTo(res[i], res[i+1]);
return res;
} //func ext
參見this answer以實現基數樣條。
您可以嘗試使用mousemove點(上圖中顯示的頂點)繪製曲線而不是直線(不確定這是否實用)。用直線表示,不管瀏覽器能夠重新渲染畫布(偶爾出現瀏覽器或操作系統忙於執行其他操作的情況),您都可以輕鬆掌握。 –
是的,這是一個好主意 - 您可以使用Bezier或Catmull-Rom樣條來平滑它,但有時候會產生一些奇怪的效果。 – Pointy
是的,但那麼筆畫將不會類似於我的鼠標移動,它將只是一種插值。並且要計算曲線,需要花費額外的時間 – daisy