Created
June 30, 2012 04:04
-
-
Save getify/3022194 to your computer and use it in GitHub Desktop.
polyfill for dashed-lines in canvas
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // note: uses the native "mozDash" or "webkitLineDash" functionality if present, polyfills with manual dashed-lines drawing | |
| // note #2: this polyfill does *not* currently work with arcs, bezier-curves, and quadratic-curves. that functionality would be theoretically possible, but is probably very hard to implement. | |
| // note #3: it also doesn't work with rect() or strokeRect() yet, though those should be relatively straightforward to do, by manually drawing the lines using lineTo(). | |
| (function(){ | |
| var _moveTo = CanvasRenderingContext2D.prototype.moveTo, | |
| _lineTo = CanvasRenderingContext2D.prototype.lineTo, | |
| pos = { | |
| x: 0, | |
| y: 0 | |
| } | |
| ; | |
| CanvasRenderingContext2D.prototype.moveTo = function(x,y) { | |
| _moveTo.call(this,x,y); | |
| pos.x = x; | |
| pos.y = y; | |
| }; | |
| CanvasRenderingContext2D.prototype.lineTo = function(x,y) { | |
| // adapted from: http://stackoverflow.com/a/4663129 | |
| if ("_lineDash" in this && this._lineDash) { | |
| _moveTo.call(this,pos.x,pos.y); | |
| this.save(); | |
| var _x = pos.x; | |
| var _y = pos.y; | |
| var dx = (x-_x), dy = (y-_y); | |
| var len = Math.sqrt(dx*dx + dy*dy); | |
| var rot = Math.atan2(dy,dx); | |
| this.translate(_x,_y); | |
| _moveTo.call(this,0,0); | |
| this.rotate(rot); | |
| var dc = this._lineDash.length; | |
| var di = 0, draw = true; | |
| _x = 0; | |
| while (len > _x) { | |
| _x += this._lineDash[di++ % dc]; | |
| if (_x > len) _x = len; | |
| draw ? _lineTo.call(this,_x,0) : _moveTo.call(this,_x,0); | |
| draw = !draw; | |
| } | |
| this.restore(); | |
| this.moveTo(x,y); | |
| } | |
| else { | |
| _lineTo.call(this,x,y); | |
| pos.x = x; | |
| pos.y = y; | |
| } | |
| }; | |
| })(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <script src="canvas-dashed-lines.js"></script> | |
| </head> | |
| <body> | |
| <canvas id="foobar" width="500" height="500"></canvas> | |
| <script> | |
| var foobar = document.getElementById("foobar"); | |
| var ctx = foobar.getContext("2d"); | |
| with (ctx) { | |
| strokeStyle = "#f00"; | |
| lineWidth = "1"; | |
| if ("mozDash" in ctx) { | |
| mozDash = [10,5]; | |
| } | |
| else if ("webkitLineDash" in ctx) { | |
| webkitLineDash = [10,5]; | |
| } | |
| else { | |
| ctx._lineDash = [10,5]; // polyfill setting | |
| } | |
| beginPath(); | |
| moveTo(10,10); | |
| lineTo(78,132); | |
| lineTo(250,50); | |
| lineTo(250,100); | |
| lineTo(240,100); | |
| stroke(); | |
| } | |
| </script> | |
| </body> | |
| </html> |
danschumann
commented
Sep 18, 2015
Also, it doesn't work great if all of your line segments are like 1 px long. The lineTo shouldn't default to draw = true. Just because you're calling lineTo doesn't mean that you need to draw, because you might be in a gap. If you have a lineDash of 5px on, 5px off, and you draw 10 line segments, each 1px each, then the first 5 should be filled and the next 5 not... I'll see what I can come up with.
Here's one that allows you to draw hundreds of 1px line segments. It keeps track of the 'dashedness' around corners
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment