├── .gitignore ├── Gruntfile.js ├── LICENSE ├── README.md ├── canvas ├── arc.js ├── area-radial.js ├── area.js ├── line-radial.js ├── line.js └── symbol.js ├── dist ├── d3.canvas.0.1.0.js └── d3.canvas.0.1.0.min.js ├── entry.js ├── index.js ├── package-lock.json ├── package.json └── test ├── arc.js ├── area-radial.js ├── area.js ├── line-radial.js ├── line.js └── symbol.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | grunt.loadNpmTasks('grunt-contrib-uglify'); 3 | grunt.loadNpmTasks('grunt-webpack'); 4 | 5 | grunt.initConfig({ 6 | pkg: grunt.file.readJSON('package.json'), 7 | 8 | uglify: { 9 | dist: { 10 | src: 'dist/<%= pkg.name %>.<%= pkg.version %>.js', 11 | dest: 'dist/<%= pkg.name %>.<%= pkg.version %>.min.js' 12 | } 13 | }, 14 | 15 | webpack: { 16 | build: { 17 | entry: './entry', 18 | output: { 19 | path: __dirname + '/dist', 20 | filename: '<%= pkg.name %>.<%= pkg.version %>.js' 21 | } 22 | } 23 | } 24 | }); 25 | 26 | grunt.registerTask('default', ['webpack', 'uglify']); 27 | }; 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Bryan Witherspoon 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | d3.js Canvas 2 | ============ 3 | A plugin for d3.js for rendering to HTML5 canvas. 4 | 5 | Usage 6 | ----- 7 | D3 is all about binding data to elements. However, unlike SVG, canvas is driven by a JavaScript API, and not DOM elements. 8 | 9 | ### d3.canvas.line (and radial) 10 | ```javascript 11 | var data = [[0, 1], [1, 1], [2, 2], [3, 3], [4, 5]], line; 12 | 13 | // the svg way 14 | line = d3.svg.line(); 15 | d3.select('path').datum(data).attr('d', line); 16 | 17 | // using d3.canvas 18 | line = d3.canvas.line(); 19 | d3.select('canvas').call(line, data); 20 | ``` 21 | 22 | ### d3.canvas.area 23 | ```javascript 24 | var data = [{x: 0, y0: 5, y1: 10}, ...], area; 25 | 26 | // the svg way 27 | area = d3.svg.area() 28 | .x(function(d) { return d.x; }) 29 | .y0(function(d) { return d.y0; }) 30 | .y1(function(d) { return d.y1; }); 31 | d3.select('path').datum(data).attr('d', area); 32 | 33 | // d3.canvas 34 | area = d3.canvas.area() 35 | .x(function(d) { return d.x; }) 36 | .y0(function(d) { return d.y0; }) 37 | .y1(function(d) { return d.y1; }); 38 | d3.select('canvas').call(area, data); 39 | ``` 40 | 41 | ### d3.canvas.arc 42 | ```javascript 43 | var d = { 44 | innerRadius: 10, 45 | outerRadius: 20, 46 | startAngle: Math.PI / 3, 47 | endAngle: 5 * Math.PI / 3 48 | }; 49 | 50 | // svg 51 | var arc = d3.svg.arc(); 52 | d3.select('path').datum(d).attr('d', arc); 53 | 54 | // canvas 55 | var arc = d3.canvas.arc() 56 | .translate([30, 30]); 57 | d3.select('canvas').call(arc, d); 58 | ``` 59 | 60 | Todo 61 | ---- 62 | - [d3.svg.symbolTypes](https://github.com/mbostock/d3/wiki/SVG-Shapes#symbolTypes) 63 | - [d3.svg.chord](https://github.com/mbostock/d3/wiki/SVG-Shapes#chord) 64 | - [d3.svg.diagonal](https://github.com/mbostock/d3/wiki/SVG-Shapes#diagonal) 65 | - [d3.svg.diagonal.radial](https://github.com/mbostock/d3/wiki/SVG-Shapes#diagonal_radial) 66 | - [Axes](https://github.com/mbostock/d3/wiki/SVG-Axes) 67 | - [Controls](https://github.com/mbostock/d3/wiki/SVG-Controls) 68 | - More testing (mock the canvas API!) 69 | - Latest APIs? Haven't touched this in probably several versions of d3! 70 | -------------------------------------------------------------------------------- /canvas/arc.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | var innerRadius = function(d) { return d.innerRadius; }, 3 | outerRadius = function(d) { return d.outerRadius; }, 4 | startAngle = function(d) { return d.startAngle; }, 5 | endAngle = function(d) { return d.endAngle; }, 6 | arcOffset = - Math.PI / 2, 7 | strokeStyle = 'transparent', 8 | fillStyle, 9 | lineWidth, 10 | lineCap, 11 | lineJoin, 12 | miterLimit, 13 | translate; 14 | 15 | function arc(canvas, data) { 16 | canvas.each(function draw() { 17 | var ctx = this.getContext('2d'), 18 | r0 = innerRadius(data), 19 | r1 = outerRadius(data), 20 | a0 = startAngle(data) + arcOffset, 21 | a1 = endAngle(data) + arcOffset; 22 | 23 | ctx.strokeStyle = strokeStyle; 24 | ctx.fillStyle = fillStyle; 25 | ctx.lineWidth = lineWidth; 26 | ctx.lineCap = lineCap; 27 | ctx.lineJoin = lineJoin; 28 | ctx.miterLimit = miterLimit; 29 | ctx.translate.apply(ctx, translate); 30 | ctx.beginPath(); 31 | 32 | ctx.moveTo.apply(ctx, ptoc(r0, a0)); 33 | ctx.lineTo.apply(ctx, ptoc(r1, a0)); 34 | ctx.arc(0, 0, r1, a0, a1); 35 | ctx.lineTo.apply(ctx, ptoc(r0, a1)); 36 | ctx.arc(0, 0, r0, a1, a0, true); 37 | 38 | ctx.stroke(); 39 | ctx.fill(); 40 | ctx.closePath(); 41 | ctx.restore(); 42 | }); 43 | 44 | function ptoc(r, a) { 45 | return [Math.cos(a) * r, Math.sin(a) * r]; 46 | } 47 | } 48 | 49 | arc.innerRadius = function(_) { 50 | if (!arguments.length) return innerRadius; 51 | innerRadius = _; 52 | return arc; 53 | }; 54 | 55 | arc.outerRadius = function(_) { 56 | if (!arguments.length) return outerRadius; 57 | outerRadius = _; 58 | return arc; 59 | }; 60 | 61 | arc.startAngle = function(_) { 62 | if (!arguments.length) return startAngle; 63 | startAngle = _; 64 | return arc; 65 | }; 66 | 67 | arc.endAngle = function(_) { 68 | if (!arguments.length) return endAngle; 69 | endAngle = _; 70 | return arc; 71 | }; 72 | 73 | arc.centroid = function() { 74 | var r = (innerRadius.apply(this, arguments) 75 | + outerRadius.apply(this, arguments)) / 2, 76 | a = (startAngle.apply(this, arguments) 77 | + endAngle.apply(this, arguments)) / 2 + arcOffset; 78 | return [Math.cos(a) * r, Math.sin(a) * r]; 79 | }; 80 | 81 | arc.strokeStyle = function(_) { 82 | if (!arguments.length) return strokeStyle; 83 | strokeStyle = _; 84 | return arc; 85 | }; 86 | 87 | arc.fillStyle = function(_) { 88 | if (!arguments.length) return fillStyle; 89 | fillStyle = _; 90 | return arc; 91 | }; 92 | 93 | arc.lineWidth = function(_) { 94 | if (!arguments.length) return lineWidth; 95 | lineWidth = _; 96 | return arc; 97 | }; 98 | 99 | arc.lineCap = function(_) { 100 | if (!arguments.length) return lineCap; 101 | lineCap = _; 102 | return arc; 103 | }; 104 | 105 | arc.lineJoin = function(_) { 106 | if (!arguments.length) return lineJoin; 107 | lineJoin = _; 108 | return arc; 109 | }; 110 | 111 | arc.miterLimit = function(_) { 112 | if (!arguments.length) return miterLimit; 113 | miterLimit = _; 114 | return arc; 115 | }; 116 | 117 | arc.translate = function(_) { 118 | if (!arguments.length) return translate; 119 | translate = _; 120 | return arc; 121 | }; 122 | 123 | return arc; 124 | }; 125 | -------------------------------------------------------------------------------- /canvas/area-radial.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | // TODO: Rewrite to support projections 3 | var startAngle = function(d) { return d[0]; }, 4 | endAngle = function(d) { return d[0]; }, 5 | innerRadius = 0, 6 | outerRadius = function(d) { return d[1]; }, 7 | strokeStyle = 'transparent', 8 | fillstyle, 9 | lineWidth, 10 | lineCap, 11 | lineJoin, 12 | miterLimit, 13 | angleOffset = - Math.PI / 2; 14 | 15 | function area(canvas, data) { 16 | var n = data.length; 17 | 18 | function coords0() { 19 | var r = +innerRadius.apply(this, arguments), 20 | a = +startAngle.apply(this, arguments) + angleOffset; 21 | 22 | return [Math.cos(a) * r, Math.sin(a) * r]; 23 | } 24 | 25 | function coords1() { 26 | var r = +outerRadius.apply(this, arguments), 27 | a = +endAngle.apply(this, arguments) + angleOffset; 28 | 29 | return [Math.cos(a) * r, Math.sin(a) * r]; 30 | } 31 | 32 | canvas.each(function draw() { 33 | var ctx = this.getContext('2d'), 34 | i = 0; 35 | 36 | ctx.strokeStyle = strokeStyle; 37 | ctx.fillStyle = fillStyle; 38 | ctx.lineWidth = lineWidth; 39 | ctx.lineCap = lineCap; 40 | ctx.lineJoin = lineJoin; 41 | ctx.miterLimit = miterLimit; 42 | 43 | ctx.beginPath(); 44 | ctx.moveTo.apply(ctx, coords0(data[0], 0)); 45 | while (++i < n) { 46 | ctx.lineTo.apply(ctx, coords0(data[i], i)); 47 | } 48 | while (--i > -1) { 49 | ctx.lineTo.apply(ctx, coords1(data[i], i)); 50 | } 51 | ctx.lineTo.apply(ctx, coords0(data[0], 0)); 52 | ctx.stroke(); 53 | ctx.fill(); 54 | ctx.closePath(); 55 | }); 56 | } 57 | 58 | area.angle = function(_) { 59 | if (!arguments.length) return endAngle; 60 | startAngle = endAngle = _; 61 | return area; 62 | }; 63 | 64 | area.radius = function(_) { 65 | if (!arguments.length) return outerRadius; 66 | innerRadius = outerRadius = _; 67 | return area; 68 | }; 69 | 70 | area.startAngle = function(_) { 71 | if (!arguments.length) return startAngle; 72 | startAngle = _; 73 | return area; 74 | }; 75 | 76 | area.endAngle = function(_) { 77 | if (!arguments.length) return endAngle; 78 | endAngle = _; 79 | return area; 80 | }; 81 | 82 | area.innerRadius = function(_) { 83 | if (!arguments.length) return innerRadius; 84 | innerRadius = _; 85 | return area; 86 | }; 87 | 88 | area.outerRadius = function(_) { 89 | if (!arguments.length) return outerRadius; 90 | outerRadius = _; 91 | return area; 92 | }; 93 | 94 | area.strokeStyle = function(_) { 95 | if (!arguments.length) return strokeStyle; 96 | strokeStyle = _; 97 | return area; 98 | }; 99 | 100 | area.fillStyle = function(_) { 101 | if (!arguments.length) return fillStyle; 102 | fillStyle = _; 103 | return area; 104 | }; 105 | 106 | area.lineWidth = function(_) { 107 | if (!arguments.length) return lineWidth; 108 | lineWidth = _; 109 | return area; 110 | }; 111 | 112 | area.lineCap = function(_) { 113 | if (!arguments.length) return lineCap; 114 | lineCap = _; 115 | return area; 116 | }; 117 | 118 | area.lineJoin = function(_) { 119 | if (!arguments.length) return lineJoin; 120 | lineJoin = _; 121 | return area; 122 | }; 123 | 124 | area.miterLimit = function(_) { 125 | if (!arguments.length) return miterLimit; 126 | miterLimit = _; 127 | return area; 128 | }; 129 | 130 | return area; 131 | }; 132 | -------------------------------------------------------------------------------- /canvas/area.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | var x0 = function(d) { return d[0]; }, 3 | x1 = function(d) { return d[0]; }, 4 | y0 = 0, 5 | y1 = function(d) { return d[1]; }, 6 | strokeStyle = 'transparent', 7 | fillStyle, 8 | lineWidth, 9 | lineCap, 10 | lineJoin, 11 | miterLimit; 12 | 13 | function area(canvas, data) { 14 | var n = data.length; 15 | 16 | canvas.each(function draw() { 17 | var ctx = this.getContext('2d'), 18 | i = 0; 19 | 20 | ctx.strokeStyle = strokeStyle; 21 | ctx.fillStyle = fillStyle; 22 | ctx.lineWidth = lineWidth; 23 | ctx.lineCap = lineCap; 24 | ctx.lineJoin = lineJoin; 25 | ctx.miterLimit = miterLimit; 26 | ctx.beginPath(); 27 | ctx.moveTo.apply(ctx, coords0(data[0], 0)); 28 | while (++i < n) { 29 | ctx.lineTo.apply(ctx, coords0(data[i], i)); 30 | } 31 | while (--i > -1) { 32 | ctx.lineTo.apply(ctx, coords1(data[i], i)); 33 | } 34 | ctx.lineTo.apply(ctx, coords0(data[0], 0)); 35 | ctx.stroke(); 36 | ctx.fill(); 37 | ctx.closePath(); 38 | }); 39 | 40 | function coords0() { 41 | return [+x0.apply(this, arguments), +y0.apply(this, arguments)]; 42 | } 43 | 44 | function coords1() { 45 | return [+x1.apply(this, arguments), +y1.apply(this, arguments)]; 46 | } 47 | } 48 | 49 | area.x = function(_) { 50 | if (!arguments.length) return x1; 51 | x0 = x1 = _; 52 | return area; 53 | }; 54 | 55 | area.x0 = function(_) { 56 | if (!arguments.length) return x0; 57 | x0 = _; 58 | return area; 59 | }; 60 | 61 | area.x1 = function(_) { 62 | if (!arguments.length) return x1; 63 | x1 = _; 64 | return area; 65 | }; 66 | 67 | area.y = function(_) { 68 | if (!arguments.length) return y1; 69 | y0 = y1 = _; 70 | return area; 71 | }; 72 | 73 | area.y0 = function(_) { 74 | if (!arguments.length) return y0; 75 | y0 = _; 76 | return area; 77 | }; 78 | 79 | area.y1 = function(_) { 80 | if (!arguments.length) return y1; 81 | y1 = _; 82 | return area; 83 | }; 84 | 85 | area.strokeStyle = function(_) { 86 | if (!arguments.length) return strokeStyle; 87 | strokeStyle = _; 88 | return area; 89 | }; 90 | 91 | area.fillStyle = function(_) { 92 | if (!arguments.length) return fillStyle; 93 | fillStyle = _; 94 | return area; 95 | }; 96 | 97 | area.lineWidth = function(_) { 98 | if (!arguments.length) return lineWidth; 99 | lineWidth = _; 100 | return area; 101 | }; 102 | 103 | area.lineCap = function(_) { 104 | if (!arguments.length) return lineCap; 105 | lineCap = _; 106 | return area; 107 | }; 108 | 109 | area.lineJoin = function(_) { 110 | if (!arguments.length) return lineJoin; 111 | lineJoin = _; 112 | return area; 113 | }; 114 | 115 | area.miterLimit = function(_) { 116 | if (!arguments.length) return miterLimit; 117 | miterLimit = _; 118 | return area; 119 | }; 120 | 121 | return area; 122 | }; 123 | -------------------------------------------------------------------------------- /canvas/line-radial.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | // TODO: Rewrite this and cartesian line to support projections 3 | var radius = function(d) { return d[1]; }, 4 | angle = function(d) { return d[0]; }, 5 | strokeStyle, 6 | lineWidth, 7 | lineCap, 8 | lineJoin, 9 | miterLimit, 10 | translate, 11 | angleOffset = -Math.PI / 2; 12 | 13 | function line(canvas, data) { 14 | var n = data.length; 15 | 16 | function coords() { 17 | var r = +radius.apply(this, arguments), 18 | a = +angle.apply(this, arguments) + angleOffset; 19 | 20 | return [Math.cos(a) * r, Math.sin(a) * r]; 21 | } 22 | 23 | canvas.each(function draw() { 24 | var ctx = this.getContext('2d'), 25 | i = 0; 26 | 27 | ctx.strokeStyle = strokeStyle; 28 | ctx.lineWidth = lineWidth; 29 | ctx.lineCap = lineCap; 30 | ctx.miterLimit = miterLimit; 31 | 32 | ctx.beginPath(); 33 | ctx.translate.apply(ctx, translate); 34 | ctx.moveTo.apply(ctx, coords(data[0], 0)); 35 | while (++i < n) { 36 | ctx.lineTo.apply(ctx, coords(data[i], i)); 37 | } 38 | ctx.stroke(); 39 | ctx.closePath(); 40 | }); 41 | } 42 | 43 | line.radius = function(_) { 44 | if (!arguments.length) return radius; 45 | radius = _; 46 | return line; 47 | }; 48 | 49 | line.angle = function(_) { 50 | if (!arguments.length) return angle; 51 | angle = _; 52 | return line; 53 | }; 54 | 55 | line.strokeStyle = function(_) { 56 | if (!arguments.length) return strokeStyle; 57 | strokeStyle = _; 58 | return line; 59 | }; 60 | 61 | line.lineWidth = function(_) { 62 | if (!arguments.length) return lineWidth; 63 | lineWidth = _; 64 | return line; 65 | }; 66 | 67 | line.lineCap = function(_) { 68 | if (!arguments.length) return lineCap; 69 | lineCap = _; 70 | return line; 71 | }; 72 | 73 | line.lineJoin = function(_) { 74 | if (!arguments.length) return lineJoin; 75 | lineJoin = _; 76 | return line; 77 | }; 78 | 79 | line.miterLimit = function(_) { 80 | if (!arguments.length) return miterLimit; 81 | miterLimit = _; 82 | return line; 83 | }; 84 | 85 | line.translate = function(_) { 86 | if (!arguments.length) return translate; 87 | translate = _; 88 | return line; 89 | }; 90 | 91 | return line; 92 | }; 93 | -------------------------------------------------------------------------------- /canvas/line.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | var x = function(d) { return d[0]; }, 3 | y = function(d) { return d[1]; }, 4 | strokeStyle, 5 | lineWidth, 6 | lineCap, 7 | lineJoin, 8 | miterLimit; 9 | 10 | function line(canvas, data) { 11 | var n = data.length; 12 | 13 | canvas.each(function draw() { 14 | var ctx = this.getContext('2d'), 15 | i = 0; 16 | 17 | ctx.strokeStyle = strokeStyle; 18 | ctx.lineWidth = lineWidth; 19 | ctx.lineCap = lineCap; 20 | ctx.miterLimit = miterLimit; 21 | ctx.beginPath(); 22 | ctx.moveTo.apply(ctx, coords(data[0], 0)); 23 | while (++i < n) { 24 | ctx.lineTo.apply(ctx, coords(data[i], i)); 25 | } 26 | ctx.stroke(); 27 | }); 28 | 29 | function coords() { 30 | return [+x.apply(this, arguments), +y.apply(this, arguments)]; 31 | } 32 | } 33 | 34 | line.x = function(_) { 35 | if (!arguments.length) return x; 36 | x = _; 37 | return line; 38 | }; 39 | 40 | line.y = function(_) { 41 | if (!arguments.length) return y; 42 | y = _; 43 | return line; 44 | }; 45 | 46 | line.strokeStyle = function(_) { 47 | if (!arguments.length) return strokeStyle; 48 | strokeStyle = _; 49 | return line; 50 | }; 51 | 52 | line.lineWidth = function(_) { 53 | if (!arguments.length) return lineWidth; 54 | lineWidth = _; 55 | return line; 56 | }; 57 | 58 | line.lineCap = function(_) { 59 | if (!arguments.length) return lineCap; 60 | lineCap = _; 61 | return line; 62 | }; 63 | 64 | line.lineJoin = function(_) { 65 | if (!arguments.length) return lineJoin; 66 | lineJoin = _; 67 | return line; 68 | }; 69 | 70 | line.miterLimit = function(_) { 71 | if (!arguments.length) return miterLimit; 72 | miterLimit = _; 73 | return line; 74 | }; 75 | 76 | return line; 77 | }; 78 | -------------------------------------------------------------------------------- /canvas/symbol.js: -------------------------------------------------------------------------------- 1 | function d3_canvas_symbolSize() { 2 | return 64; 3 | } 4 | 5 | function d3_svg_symbolType() { 6 | return 'circle'; 7 | } 8 | 9 | function d3_canvas_symbol() { 10 | var type = function() { return 64; }, 11 | size = function() { return 'circle'; }; 12 | 13 | function symbol() { 14 | var s = symbols[type.apply(this, arguments)] || circle; 15 | 16 | return s.call(this, size.apply(this, arguments)); 17 | } 18 | 19 | symbol.type = function(_) { 20 | if (!arguments.length) return type; 21 | type = _; 22 | return symbol; 23 | }; 24 | 25 | symbol.size = function(_) { 26 | if (!arguments.length) return size; 27 | size = _; 28 | return symbol; 29 | }; 30 | 31 | return symbol; 32 | }; 33 | 34 | d3_canvas_symbol.circle = function circle(size) { 35 | var ctx = this.getContext('2d'), 36 | r = Math.sqrt(size / Math.PI); 37 | 38 | ctx.beginPath(); 39 | ctx.arc(0, 0, r, 0, 2 * Math.PI); 40 | ctx.stroke(); 41 | ctx.endPath(); 42 | }; 43 | 44 | module.exports = d3_canvas_symbol; 45 | -------------------------------------------------------------------------------- /dist/d3.canvas.0.1.0.js: -------------------------------------------------------------------------------- 1 | (()=>{var n={833:n=>{n.exports=function(){var n,t,e,r,i,l,u=function(n){return n.innerRadius},o=function(n){return n.outerRadius},a=function(n){return n.startAngle},h=function(n){return n.endAngle},c=-Math.PI/2,f="transparent";function p(p,s){function g(n,t){return[Math.cos(t)*n,Math.sin(t)*n]}p.each((function(){var p=this.getContext("2d"),y=u(s),d=o(s),v=a(s)+c,m=h(s)+c;p.strokeStyle=f,p.fillStyle=n,p.lineWidth=t,p.lineCap=e,p.lineJoin=r,p.miterLimit=i,p.translate.apply(p,l),p.beginPath(),p.moveTo.apply(p,g(y,v)),p.lineTo.apply(p,g(d,v)),p.arc(0,0,d,v,m),p.lineTo.apply(p,g(y,m)),p.arc(0,0,y,m,v,!0),p.stroke(),p.fill(),p.closePath(),p.restore()}))}return p.innerRadius=function(n){return arguments.length?(u=n,p):u},p.outerRadius=function(n){return arguments.length?(o=n,p):o},p.startAngle=function(n){return arguments.length?(a=n,p):a},p.endAngle=function(n){return arguments.length?(h=n,p):h},p.centroid=function(){var n=(u.apply(this,arguments)+o.apply(this,arguments))/2,t=(a.apply(this,arguments)+h.apply(this,arguments))/2+c;return[Math.cos(t)*n,Math.sin(t)*n]},p.strokeStyle=function(n){return arguments.length?(f=n,p):f},p.fillStyle=function(t){return arguments.length?(n=t,p):n},p.lineWidth=function(n){return arguments.length?(t=n,p):t},p.lineCap=function(n){return arguments.length?(e=n,p):e},p.lineJoin=function(n){return arguments.length?(r=n,p):r},p.miterLimit=function(n){return arguments.length?(i=n,p):i},p.translate=function(n){return arguments.length?(l=n,p):l},p}},929:n=>{n.exports=function(){var n,t,e,r,i=function(n){return n[0]},l=function(n){return n[0]},u=0,o=function(n){return n[1]},a="transparent",h=-Math.PI/2;function c(c,f){var p=f.length;function s(){var n=+u.apply(this,arguments),t=+i.apply(this,arguments)+h;return[Math.cos(t)*n,Math.sin(t)*n]}function g(){var n=+o.apply(this,arguments),t=+l.apply(this,arguments)+h;return[Math.cos(t)*n,Math.sin(t)*n]}c.each((function(){var i=this.getContext("2d"),l=0;for(i.strokeStyle=a,i.fillStyle=fillStyle,i.lineWidth=n,i.lineCap=t,i.lineJoin=e,i.miterLimit=r,i.beginPath(),i.moveTo.apply(i,s(f[0],0));++l-1;)i.lineTo.apply(i,g(f[l],l));i.lineTo.apply(i,s(f[0],0)),i.stroke(),i.fill(),i.closePath()}))}return c.angle=function(n){return arguments.length?(i=l=n,c):l},c.radius=function(n){return arguments.length?(u=o=n,c):o},c.startAngle=function(n){return arguments.length?(i=n,c):i},c.endAngle=function(n){return arguments.length?(l=n,c):l},c.innerRadius=function(n){return arguments.length?(u=n,c):u},c.outerRadius=function(n){return arguments.length?(o=n,c):o},c.strokeStyle=function(n){return arguments.length?(a=n,c):a},c.fillStyle=function(n){return arguments.length?(fillStyle=n,c):fillStyle},c.lineWidth=function(t){return arguments.length?(n=t,c):n},c.lineCap=function(n){return arguments.length?(t=n,c):t},c.lineJoin=function(n){return arguments.length?(e=n,c):e},c.miterLimit=function(n){return arguments.length?(r=n,c):r},c}},7:n=>{n.exports=function(){var n,t,e,r,i,l=function(n){return n[0]},u=function(n){return n[0]},o=0,a=function(n){return n[1]},h="transparent";function c(c,f){var p=f.length;function s(){return[+l.apply(this,arguments),+o.apply(this,arguments)]}function g(){return[+u.apply(this,arguments),+a.apply(this,arguments)]}c.each((function(){var l=this.getContext("2d"),u=0;for(l.strokeStyle=h,l.fillStyle=n,l.lineWidth=t,l.lineCap=e,l.lineJoin=r,l.miterLimit=i,l.beginPath(),l.moveTo.apply(l,s(f[0],0));++u-1;)l.lineTo.apply(l,g(f[u],u));l.lineTo.apply(l,s(f[0],0)),l.stroke(),l.fill(),l.closePath()}))}return c.x=function(n){return arguments.length?(l=u=n,c):u},c.x0=function(n){return arguments.length?(l=n,c):l},c.x1=function(n){return arguments.length?(u=n,c):u},c.y=function(n){return arguments.length?(o=a=n,c):a},c.y0=function(n){return arguments.length?(o=n,c):o},c.y1=function(n){return arguments.length?(a=n,c):a},c.strokeStyle=function(n){return arguments.length?(h=n,c):h},c.fillStyle=function(t){return arguments.length?(n=t,c):n},c.lineWidth=function(n){return arguments.length?(t=n,c):t},c.lineCap=function(n){return arguments.length?(e=n,c):e},c.lineJoin=function(n){return arguments.length?(r=n,c):r},c.miterLimit=function(n){return arguments.length?(i=n,c):i},c}},125:n=>{n.exports=function(){var n,t,e,r,i,l,u=function(n){return n[1]},o=function(n){return n[0]},a=-Math.PI/2;function h(r,h){var c=h.length;function f(){var n=+u.apply(this,arguments),t=+o.apply(this,arguments)+a;return[Math.cos(t)*n,Math.sin(t)*n]}r.each((function(){var r=this.getContext("2d"),u=0;for(r.strokeStyle=n,r.lineWidth=t,r.lineCap=e,r.miterLimit=i,r.beginPath(),r.translate.apply(r,l),r.moveTo.apply(r,f(h[0],0));++u{n.exports=function(){var n,t,e,r,i,l=function(n){return n[0]},u=function(n){return n[1]};function o(r,o){var a=o.length;function h(){return[+l.apply(this,arguments),+u.apply(this,arguments)]}r.each((function(){var r=this.getContext("2d"),l=0;for(r.strokeStyle=n,r.lineWidth=t,r.lineCap=e,r.miterLimit=i,r.beginPath(),r.moveTo.apply(r,h(o[0],0));++l{function t(){var n=function(){return 64},t=function(){return"circle"};function e(){var e=symbols[n.apply(this,arguments)]||circle;return e.call(this,t.apply(this,arguments))}return e.type=function(t){return arguments.length?(n=t,e):n},e.size=function(n){return arguments.length?(t=n,e):t},e}t.circle=function(n){var t=this.getContext("2d"),e=Math.sqrt(n/Math.PI);t.beginPath(),t.arc(0,0,e,0,2*Math.PI),t.stroke(),t.endPath()},n.exports=t},10:(n,t,e)=>{t.arc=e(833),t.area=e(7),t.area.radial=e(929),t.line=e(212),t.line.radial=e(125),t.symbol=e(720)}},t={};window.d3=window.d3||{},d3.canvas=function e(r){var i=t[r];if(void 0!==i)return i.exports;var l=t[r]={exports:{}};return n[r](l,l.exports,e),l.exports}(10)})(); -------------------------------------------------------------------------------- /dist/d3.canvas.0.1.0.min.js: -------------------------------------------------------------------------------- 1 | (()=>{var r={833:n=>{n.exports=function(){var o,a,h,c,f,p,s=function(n){return n.innerRadius},g=function(n){return n.outerRadius},y=function(n){return n.startAngle},d=function(n){return n.endAngle},v=-Math.PI/2,m="transparent";function t(n,l){function u(n,t){return[Math.cos(t)*n,Math.sin(t)*n]}n.each(function(){var n=this.getContext("2d"),t=s(l),e=g(l),r=y(l)+v,i=d(l)+v;n.strokeStyle=m,n.fillStyle=o,n.lineWidth=a,n.lineCap=h,n.lineJoin=c,n.miterLimit=f,n.translate.apply(n,p),n.beginPath(),n.moveTo.apply(n,u(t,r)),n.lineTo.apply(n,u(e,r)),n.arc(0,0,e,r,i),n.lineTo.apply(n,u(t,i)),n.arc(0,0,t,i,r,!0),n.stroke(),n.fill(),n.closePath(),n.restore()})}return t.innerRadius=function(n){return arguments.length?(s=n,t):s},t.outerRadius=function(n){return arguments.length?(g=n,t):g},t.startAngle=function(n){return arguments.length?(y=n,t):y},t.endAngle=function(n){return arguments.length?(d=n,t):d},t.centroid=function(){var n=(s.apply(this,arguments)+g.apply(this,arguments))/2,t=(y.apply(this,arguments)+d.apply(this,arguments))/2+v;return[Math.cos(t)*n,Math.sin(t)*n]},t.strokeStyle=function(n){return arguments.length?(m=n,t):m},t.fillStyle=function(n){return arguments.length?(o=n,t):o},t.lineWidth=function(n){return arguments.length?(a=n,t):a},t.lineCap=function(n){return arguments.length?(h=n,t):h},t.lineJoin=function(n){return arguments.length?(c=n,t):c},t.miterLimit=function(n){return arguments.length?(f=n,t):f},t.translate=function(n){return arguments.length?(p=n,t):p},t}},929:n=>{n.exports=function(){var l,u,o,a,h=function(n){return n[0]},c=function(n){return n[0]},f=0,p=function(n){return n[1]},s="transparent",g=-Math.PI/2;function t(n,e){var r=e.length;function i(){var n=+f.apply(this,arguments),t=+h.apply(this,arguments)+g;return[Math.cos(t)*n,Math.sin(t)*n]}n.each(function(){var n=this.getContext("2d"),t=0;for(n.strokeStyle=s,n.fillStyle=fillStyle,n.lineWidth=l,n.lineCap=u,n.lineJoin=o,n.miterLimit=a,n.beginPath(),n.moveTo.apply(n,i(e[0],0));++t{n.exports=function(){var l,u,o,a,h,t=function(n){return n[0]},c=function(n){return n[0]},f=0,p=function(n){return n[1]},s="transparent";function e(n,e){var r=e.length;function i(){return[+t.apply(this,arguments),+f.apply(this,arguments)]}n.each(function(){var n=this.getContext("2d"),t=0;for(n.strokeStyle=s,n.fillStyle=l,n.lineWidth=u,n.lineCap=o,n.lineJoin=a,n.miterLimit=h,n.beginPath(),n.moveTo.apply(n,i(e[0],0));++t{n.exports=function(){var l,u,o,t,a,h,c=function(n){return n[1]},f=function(n){return n[0]},p=-Math.PI/2;function e(n,e){var r=e.length;function i(){var n=+c.apply(this,arguments),t=+f.apply(this,arguments)+p;return[Math.cos(t)*n,Math.sin(t)*n]}n.each(function(){var n=this.getContext("2d"),t=0;for(n.strokeStyle=l,n.lineWidth=u,n.lineCap=o,n.miterLimit=a,n.beginPath(),n.translate.apply(n,h),n.moveTo.apply(n,i(e[0],0));++t{n.exports=function(){var l,u,o,t,a,h=function(n){return n[0]},c=function(n){return n[1]};function e(n,e){var r=e.length;function i(){return[+h.apply(this,arguments),+c.apply(this,arguments)]}n.each(function(){var n=this.getContext("2d"),t=0;for(n.strokeStyle=l,n.lineWidth=u,n.lineCap=o,n.miterLimit=a,n.beginPath(),n.moveTo.apply(n,i(e[0],0));++t{function t(){var t=function(){return 64},e=function(){return"circle"};function r(){return(symbols[t.apply(this,arguments)]||circle).call(this,e.apply(this,arguments))}return r.type=function(n){return arguments.length?(t=n,r):t},r.size=function(n){return arguments.length?(e=n,r):e},r}t.circle=function(n){var t=this.getContext("2d"),n=Math.sqrt(n/Math.PI);t.beginPath(),t.arc(0,0,n,0,2*Math.PI),t.stroke(),t.endPath()},n.exports=t},10:(n,t,e)=>{t.arc=e(833),t.area=e(7),t.area.radial=e(929),t.line=e(212),t.line.radial=e(125),t.symbol=e(720)}},i={};window.d3=window.d3||{},d3.canvas=function n(t){var e=i[t];if(void 0!==e)return e.exports;e=i[t]={exports:{}};return r[t](e,e.exports,n),e.exports}(10)})(); -------------------------------------------------------------------------------- /entry.js: -------------------------------------------------------------------------------- 1 | window.d3 = window.d3 || {}; 2 | 3 | d3.canvas = require('./index'); 4 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | exports.arc = require('./canvas/arc'); 2 | exports.area = require('./canvas/area'); 3 | exports.area.radial = require('./canvas/area-radial'); 4 | exports.line = require('./canvas/line'); 5 | exports.line.radial = require('./canvas/line-radial'); 6 | exports.symbol = require('./canvas/symbol'); 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "d3.canvas", 3 | "version": "0.1.0", 4 | "description": "Canvas rendering helpers for d3.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "http://github.com/bspoon/d3-canvas.git" 12 | }, 13 | "keywords": [ 14 | "canvas" 15 | ], 16 | "author": "Bryan Witherspoon", 17 | "license": "ISC", 18 | "bugs": { 19 | "url": "https://github.com/bspoon/d3-canvas/issues" 20 | }, 21 | "devDependencies": { 22 | "chai": "^2.2.0", 23 | "grunt": "^1.4.1", 24 | "grunt-contrib-uglify": "^5.0.1", 25 | "grunt-webpack": "^5.0.0", 26 | "mocha": "^11.2.2", 27 | "webpack": "^5.67.0", 28 | "webpack-dev-server": "^5.2.1" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/arc.js: -------------------------------------------------------------------------------- 1 | var assert = require('chai').assert; 2 | 3 | var Arc = require('../canvas/arc'); 4 | 5 | describe('Arc', function() { 6 | var arc; 7 | 8 | beforeEach(function() { 9 | arc = Arc(); 10 | }); 11 | 12 | it('should support regular accessors', function() { 13 | var keys = [ 14 | 'innerRadius', 15 | 'outerRadius', 16 | 'startAngle', 17 | 'endAngle', 18 | 'strokeStyle', 19 | 'fillStyle', 20 | 'lineWidth', 21 | 'lineCap', 22 | 'lineJoin', 23 | 'miterLimit', 24 | 'translate' 25 | ], _ = 'cool'; 26 | 27 | keys.forEach(function(key) { 28 | arc[key](_); 29 | assert.equal(arc[key](), _); 30 | }); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /test/area-radial.js: -------------------------------------------------------------------------------- 1 | var assert = require('chai').assert; 2 | 3 | var AreaRadial = require('../canvas/area-radial'); 4 | 5 | describe('Radial Area', function() { 6 | var radial; 7 | 8 | beforeEach(function() { 9 | radial = AreaRadial(); 10 | }); 11 | 12 | it('should support regular accessors', function() { 13 | var keys = [ 14 | 'angle', 15 | 'radius', 16 | 'startAngle', 17 | 'endAngle', 18 | 'innerRadius', 19 | 'outerRadius', 20 | 'strokeStyle', 21 | 'fillStyle', 22 | 'lineWidth', 23 | 'lineCap', 24 | 'lineJoin', 25 | 'miterLimit' 26 | ], _ = 'cool'; 27 | 28 | keys.forEach(function(key) { 29 | radial[key](_); 30 | assert.equal(radial[key](), _); 31 | }); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /test/area.js: -------------------------------------------------------------------------------- 1 | var assert = require('chai').assert; 2 | 3 | var Area = require('../canvas/area'); 4 | 5 | describe('Area', function() { 6 | var area; 7 | 8 | beforeEach(function() { 9 | area = Area(); 10 | }); 11 | 12 | it('should support regular accessors', function() { 13 | var keys = [ 14 | 'x0', 15 | 'x1', 16 | 'y0', 17 | 'y1', 18 | 'strokeStyle', 19 | 'fillStyle', 20 | 'lineWidth', 21 | 'lineCap', 22 | 'lineJoin', 23 | 'miterLimit' 24 | ], _ = 'hi'; 25 | 26 | keys.forEach(function(key) { 27 | area[key](_); 28 | assert.equal(area[key](), _); 29 | }); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/line-radial.js: -------------------------------------------------------------------------------- 1 | var assert = require('chai').assert; 2 | 3 | var LineRadial = require('../canvas/line-radial'); 4 | 5 | describe('Radial Line', function() { 6 | var radial; 7 | 8 | beforeEach(function() { 9 | radial = LineRadial(); 10 | }); 11 | 12 | it('should support regular accessors', function() { 13 | var keys = [ 14 | 'angle', 15 | 'radius', 16 | 'strokeStyle', 17 | 'lineWidth', 18 | 'lineCap', 19 | 'lineJoin', 20 | 'miterLimit' 21 | ], _ = 'cool'; 22 | 23 | keys.forEach(function(key) { 24 | radial[key](_); 25 | assert.equal(radial[key](), _); 26 | }); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/line.js: -------------------------------------------------------------------------------- 1 | var assert = require('chai').assert; 2 | 3 | var Line = require('../canvas/line'); 4 | 5 | describe('Line', function() { 6 | var line; 7 | 8 | beforeEach(function() { 9 | line = Line(); 10 | }); 11 | 12 | it('should support regular accessors', function() { 13 | var keys = [ 14 | 'x', 15 | 'y', 16 | 'strokeStyle', 17 | 'lineWidth', 18 | 'lineCap', 19 | 'lineJoin', 20 | 'miterLimit' 21 | ], _ = 'hi'; 22 | 23 | keys.forEach(function(key) { 24 | line[key](_); 25 | assert.equal(line[key](), _); 26 | }); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/symbol.js: -------------------------------------------------------------------------------- 1 | var assert = require('chai').assert; 2 | 3 | var Symbol = require('../canvas/symbol'); 4 | 5 | describe('Symbol', function() { 6 | var symbol, _ = 'foo'; 7 | 8 | beforeEach(function() { 9 | symbol = Symbol(); 10 | }); 11 | 12 | it('should support regular accessors', function() { 13 | symbol.type(_); 14 | assert.equal(symbol.type(), _); 15 | symbol.size(_); 16 | assert.equal(symbol.type(), _); 17 | }); 18 | }); 19 | --------------------------------------------------------------------------------