D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
Andrew-Reid
Full window
Github gist
Artistic World Map
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v4.min.js"></script> <script src="https://d3js.org/topojson.v1.min.js"></script> </head> <body> <script> var width = 960; var canvas = d3.select("body").append("canvas") .attr("width",width) .attr("height",width); var context = canvas.node().getContext("2d"); var projection = d3.geoMercator() .translate([width/2,width/2]) .scale(width/Math.PI/2); var path = d3.geoPath() .projection(projection) .context(context); d3.json("https://unpkg.com/world-atlas@1/world/110m.json", function (error, world) { var features = (topojson.feature(world, world.objects.countries).features); var ice = features.filter(function(d) { return d.id == "010" || d.id == "304" }); // Draw everything as water: watercolor("blue"); // Draw all land masses: var land = topojson.feature(world, world.objects.land); context.beginPath(); path(land); context.clip(); watercolor("green"); // Draw Greenland and Antarctica: context.beginPath(); path(features) path(ice[0] ) path(ice[1] ) context.clip(); watercolor("white"); }); // algorithm implementation from greentecq, changes shown here are superficial and for different colouration. // source: https://www.reddit.com/r/proceduralgeneration/comments/6mta0f/watercolor_simple_noise_algorithm/ - // function watercolor(channel) { var points = {}; var nowMax = 2; for (var x = 0; x < 2 + 1; x += 1) { for (var y = 0; y < 2 + 1; y += 1) { points[x + '#' + y] = {r:Math.random(), g:Math.random(), b:Math.random()}; } } for (var i = 0; i < 5; i += 1) { doOneStep(); } var cellWidth = Math.ceil(width / (nowMax + 1)); for (var p in points) { var xy = p.split('#'); var b = points[p].b; var r = points[p].r; var g = points[p].g; if (channel == "blue") { b = Math.pow(b,0.2)*255; r = Math.pow(r,0.6)*10+125; g = g*50+125; } else if (channel == "white") { b = Math.pow(b,0.5)*65+190; r = r*65+190; g = g*65+190; } else { r *= 50; g = Math.sqrt(g)*200; b *= 25; } context.fillStyle = 'RGB(' + parseInt(r) + ',' + parseInt(g) + ',' + parseInt(b) + ')'; context.fillRect(+xy[0]*cellWidth, +xy[1]*cellWidth, cellWidth, cellWidth); } function doOneStep() { nowMax *= 2; var newPoints = {}; for (var p in points) { var xy = p.split('#'); var x =+xy[0] * 2; var y =+xy[1] * 2; newPoints[x + '#' + y] = points[p]; } for (var p in newPoints) { var xy = p.split("#"); var x = +xy[0]; var y = +xy[1]; if (x < nowMax && y < nowMax) { newPoints[(x+1)+"#"+y] = {}; newPoints[x+"#"+(y+1)] = {}; newPoints[(x+2)+"#"+(y+1)] = {}; newPoints[(x+1)+"#"+(y+2)] = {}; newPoints[(x+1)+"#"+(y+1)] = {}; ["r","g","b"].forEach(function(color) { var a = newPoints[p][color]; var b = newPoints[(x+2) + "#" + y][color]; var c = newPoints[(x+2) + "#" + (y+2)][color]; var d = newPoints[x + "#" + (y+2)][color]; var average = (a+b+c+d)/4; newPoints[(x+1)+"#"+y][color] = Math.random() < 0.5 ? (a + average) / 2 : (b + average) / 2; newPoints[x+"#"+(y+1)][color] = Math.random() < 0.5 ? (a + average) / 2 : (c + average) / 2; newPoints[(x+2)+"#"+(y+1)][color] = Math.random() < 0.5 ? (b + average) / 2 : (d + average) / 2; newPoints[(x+1)+"#"+(y+2)][color] = Math.random() < 0.5 ? (c + average) / 2 : (d + average) / 2; newPoints[(x+1)+"#"+(y+1)][color] = Math.random() < 0.5 ? (Math.random() < 0.5 ? a : b) : (Math.random() < 0.5 ? c : d); }); } } points = newPoints; } } </script>
https://d3js.org/d3.v4.min.js
https://d3js.org/topojson.v1.min.js