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
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With