Based on this awesome post by John Nelson, the example simulates a chalk drawing on a blackboard.
I've used the new D3js 4.0 version and Canvas instead of SVG, since this could be a nice background for some visalization.
Based on this awesome post by John Nelson, the example simulates a chalk drawing on a blackboard.
I've used the new D3js 4.0 version and Canvas instead of SVG, since this could be a nice background for some visalization.
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <style> | |
| @font-face { | |
| font-family: 'mvboli'; | |
| src: url('mvboli.ttf'); | |
| } | |
| </style> | |
| <body> | |
| <span style="font-family: 'mvboli';"></span> | |
| <script src="https://d3js.org/d3-array.v1.min.js"></script> | |
| <script src="https://d3js.org/d3-geo.v1.min.js"></script> | |
| <script src="https://d3js.org/d3-selection.v1.min.js"></script> | |
| <script src="https://d3js.org/d3-collection.v1.min.js"></script> | |
| <script src="https://d3js.org/d3-dispatch.v1.min.js"></script> | |
| <script src="https://d3js.org/d3-request.v1.min.js"></script> | |
| <script src="http://d3js.org/topojson.v1.min.js"></script> | |
| <script src="http://d3js.org/queue.v1.min.js"></script> | |
| <script> | |
| var width = 910, | |
| height = 450 | |
| margin = 50; | |
| var projection = d3.geoAlbersUsa() | |
| .translate([margin/2 + width/2, margin/2 + height/2]) | |
| .scale(990); | |
| var path = d3.geoPath() | |
| .projection(projection); | |
| var canvas = d3.select("body").append("canvas") | |
| .attr("width", width + margin) | |
| .attr("height", height + margin); | |
| var context = canvas.node().getContext("2d"); | |
| var loadImage = function(src, cb) { | |
| var img = new Image(); | |
| img.src = src; | |
| var error = null; | |
| img.onload = function() { | |
| cb(null, img); | |
| }; | |
| img.onerror = function() { | |
| cb('ERROR LOADING IMAGE ' + src, null); | |
| }; | |
| }; | |
| var q = queue() | |
| .defer(d3.json, "us.json"); | |
| q.defer(loadImage, "chalkfilltexturesolidgreen.png"); | |
| q.defer(loadImage, "vignettethumbnail.png"); | |
| q.await(ready); | |
| function ready(error, us, background, overlay) { | |
| var states = topojson.feature(us, us.objects.states); | |
| context.drawImage(background, 0, 0, width + 50, height + 50); | |
| context.lineWidth = 2; | |
| context.strokeStyle = 'rgba(255,255,255, 0.6)'; | |
| context.setLineDash([4,3,1,6,1,4,8,1,2,3]); | |
| context.beginPath(); | |
| path.context(context)(states); | |
| context.stroke(); | |
| context.lineWidth = 5; | |
| context.strokeStyle = 'rgba(255,255,255, 0.2)'; | |
| context.setLineDash([3,2,4,5,2,3,2,5,4]); | |
| context.beginPath(); | |
| path.context(context)(states); | |
| context.stroke(); | |
| context.lineWidth = 2; | |
| context.strokeStyle = 'rgba(255,255,255, 0.6)'; | |
| context.fillStyle = 'rgba(255,255,255, 0.6)'; | |
| context.font = "30px mvboli"; | |
| context.fillText("States map", 150 + width/2, 50); | |
| context.strokeText("States map", 150 + width/2, 50); | |
| context.drawImage(overlay, 0, 0, width + margin, height + margin); | |
| }; | |
| </script> | |