javascript - Draw a line with two different sized ends -
how can have line 2 different sizes canvas?
i have line drawing canvas
start out width of 30
, gradually(proportionally) reduce down size of 15
, reaches 15 right @ end of line.
i though perhaps if set context.linewidth
in 2 places (start , end) work.
<!doctype html> <html> <head> <style> body { margin: 0px; padding: 0px; } </style> </head> <body> <canvas id="mycanvas" width="578" height="200"></canvas> <script> var canvas = document.getelementbyid('mycanvas'); var context = canvas.getcontext('2d'); context.beginpath(); context.moveto(100, 150); context.linewidth = 30; context.lineto(450, 50); context.linewidth = 15; context.stroke(); </script> </body> </html>
i once wondered building such variable-width line, , ended building own solution, , wrote blog post out of it.
i'll copy first part of here, rounded version can found here : https://gamealchemist.wordpress.com/2013/08/28/variable-width-lines-in-html5-canvas/
variable width lines in html5
drawing such [variable width] line quite easy once realize need draw not line : in fact polygon.
if line segment want draw (a,b), situation looks :
what want draw in fact a1,a2,b2,b1 polygon.
if call n normal vector (drawn on scheme), , w1 , w2 width in , b respectively, have :
a1 = + n * w1/2
a2 = – n * w1/2
b1 = b + n * w2/2
b2 = b – n * w2/2
so how find normal vector n ?
maths says if (x,y) defines vector v , normal vector coordinates (-y, x).
n, vector normal ab hence have ( – ( yb – ya ) , ( xb – xa ) ) coordinates.
there annoying thing vector : depends on ab length, not want : need normalize vector, i.e. have standard length of 1, when later multiply vector w1/2, right length vector added.
vector normalisation done dividing x , y of vector vector length. since length found using phytagore’s theorem, makes 2 squares, 1 square root, , 2 divides find normalized vector n :
// computing normalized vector normal ab length = math.sqrt( sq (xb-xa) + sq (yb - ya) ) ; nx = - (yb - ya) / length ; ny = (xb - xa) / length ;
so can compute 4 points, let link them poly-line, , fill resulting shape : here comes our variable width segment !
here javascript code :
// varline : draws line a(x1,y1) b(x2,y2) // starts w1 width , ends w2 width. // relies on fillstyle color. // ctx valid canvas's context2d. function varline(ctx, x1, y1, x2, y2, w1, w2) { var dx = (x2 - x1); var dy = (y2 - y1); w1 /= 2; w2 /= 2; // use w1/2 , w2/2 computations. // length of ab vector var length = math.sqrt(sq(dx) + sq(dy)); if (!length) return; // exit if 0 length dx /= length ; dy /= length ; var shiftx = - dy * w1 // compute aa1 vector's x var shifty = dx * w1 // compute aa1 vector's y ctx.beginpath(); ctx.moveto(x1 + shiftx, y1 + shifty); ctx.lineto(x1 - shiftx, y1 - shifty); // draw a1a2 shiftx = - dy * w2 ; // compute bb1 vector's x shifty = dx * w2 ; // compute bb1 vector's y ctx.lineto(x2 - shiftx, y2 - shifty); // draw a2b1 ctx.lineto(x2 + shiftx, y2 + shifty); // draw b1b2 ctx.closepath(); // draw b2a1 ctx.fill(); }
so let see result on small example : drawing variable width segments within circle nice hsl colors :
(about @marke's (interesting) remark on chaining line segments, fear quite difficult goal, since there many specific cases depending on line length/ w1 /w2 / angle in between segments. quite solved using force fields , marching cubes, fear off-topic !! :-) )
Comments
Post a Comment