xxxxxxxxxx
<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