Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dotted stroke in <canvas>

I guess it is not possible to set stroke property such as CSS which is quite easy. With CSS we have dashed, dotted, solid but on canvas when drawing lines/or strokes this doesn't seem to be an option. How have you implemented this?

I've seen some examples but they are really long for such a silly function.

For example:

http://groups.google.com/group/javascript-information-visualization-toolkit/browse_thread/thread/22000c0d0a1c54f9?pli=1

like image 499
thenengah Avatar asked Jan 02 '11 01:01

thenengah


People also ask

How do you make a dotted line in canvas?

To get a dashed line, use the dash parameter dash=(5,1) for 5px dash followed by 1px space. You can set the color and width of the dashed lines using the fill and width parameters.

What does dotted line represent in design?

Solid Versus Dashed or Dotted Lines The first and most basic rule of lines in design drawings is that solid lines indicate visible or “real” objects or surfaces, while anything drawing with dots and/or dashes indicates something that is unseen or “hidden” from view.

What are dashed lines in art?

In visual language, the dashed line gives us a way to express the idea that something is not concrete. Something impermanent. It may be temporary; it may not currently exist (it will in the future or it did in the past); or it may be invisible or hidden. One way or the other, it represents what it is—not solid.


2 Answers

Fun question! I've written a custom implementation of dashed lines; you can try it out here. I took the route of Adobe Illustrator and allow you to specify an array of dash/gap lengths.

For stackoverflow posterity, here's my implementation (slightly altered for s/o line widths):

var CP = window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype; if (CP && CP.lineTo){   CP.dashedLine = function(x,y,x2,y2,dashArray){     if (!dashArray) dashArray=[10,5];     if (dashLength==0) dashLength = 0.001; // Hack for Safari     var dashCount = dashArray.length;     this.moveTo(x, y);     var dx = (x2-x), dy = (y2-y);     var slope = dx ? dy/dx : 1e15;     var distRemaining = Math.sqrt( dx*dx + dy*dy );     var dashIndex=0, draw=true;     while (distRemaining>=0.1){       var dashLength = dashArray[dashIndex++%dashCount];       if (dashLength > distRemaining) dashLength = distRemaining;       var xStep = Math.sqrt( dashLength*dashLength / (1 + slope*slope) );       if (dx<0) xStep = -xStep;       x += xStep       y += slope*xStep;       this[draw ? 'lineTo' : 'moveTo'](x,y);       distRemaining -= dashLength;       draw = !draw;     }   } } 

To draw a line from 20,150 to 170,10 with dashes that are 30px long followed by a gap of 10px, you would use:

myContext.dashedLine(20,150,170,10,[30,10]); 

To draw alternating dashes and dots, use (for example):

myContext.lineCap   = 'round'; myContext.lineWidth = 4; // Lines 4px wide, dots of diameter 4 myContext.dashedLine(20,150,170,10,[30,10,0,10]); 

The "very short" dash length of 0 combined with the rounded lineCap results in dots along your line.

If anyone knows of a way to access the current point of a canvas context path, I'd love to know about it, as it would allow me to write this as ctx.dashTo(x,y,dashes) instead of requiring you to re-specify the start point in the method call.

like image 67
Phrogz Avatar answered Sep 22 '22 19:09

Phrogz


This simplified version of Phrogz's code utilises the built-in transformation functionality of Canvas and also handles special cases e.g. when dx = 0

var CP = window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype; if (CP.lineTo) {     CP.dashedLine = function(x, y, x2, y2, da) {         if (!da) da = [10,5];         this.save();         var dx = (x2-x), dy = (y2-y);         var len = Math.sqrt(dx*dx + dy*dy);         var rot = Math.atan2(dy, dx);         this.translate(x, y);         this.moveTo(0, 0);         this.rotate(rot);                var dc = da.length;         var di = 0, draw = true;         x = 0;         while (len > x) {             x += da[di++ % dc];             if (x > len) x = len;             draw ? this.lineTo(x, 0): this.moveTo(x, 0);             draw = !draw;         }                this.restore();     } } 

I think my calculations are correct and it seems to render OK.

like image 39
Rod MacDougall Avatar answered Sep 21 '22 19:09

Rod MacDougall