|
<!doctype html> |
|
<html lang=""> |
|
<head> |
|
<meta charset="utf-8"> |
|
<title>Canvas watercolour</title> |
|
<meta name="description" content=""> |
|
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|
|
|
<script src="https://unpkg.com/d3/build/d3.min.js"></script> |
|
<script src="https://unpkg.com/d3-selection-multi"></script> |
|
<script src="randgen.js"></script> |
|
|
|
<style> |
|
canvas{border: 1px solid #aaaaaa;} |
|
</style> |
|
</head> |
|
<body> |
|
<canvas></canvas> |
|
<script type='text/javascript'> |
|
|
|
let width = 600, |
|
height = 600, |
|
PR = window.devicePixelRatio || 1, |
|
scaledWidth = width*PR, |
|
scaledHeight = height*PR; |
|
|
|
const canvas = d3.select('canvas') |
|
.attrs({ |
|
width: scaledWidth, |
|
height: scaledHeight, |
|
}) |
|
.styles({ |
|
width: `${width}px`, |
|
height: `${height}px` |
|
}); |
|
|
|
const context = d3.select('canvas').node().getContext("2d"); |
|
context.scale(PR, PR); |
|
context.clearRect(0,0, scaledWidth, scaledHeight); |
|
|
|
context.lineWidth = 1; |
|
|
|
context.globalCompositeOperation = 'multiply;' |
|
|
|
function makeShape(x, y, radius){ |
|
return [ |
|
[x, y-radius], |
|
[x+(radius*.65), y-(radius*.65)], |
|
[x+radius, y], |
|
[x+(radius*.65), y+(radius*.65)], |
|
[x, y+radius], |
|
[x-(radius*.65), y+(radius*.65)], |
|
[x-radius, y], |
|
[x-(radius*.65), y-(radius*.65)], |
|
] |
|
} |
|
|
|
function deform(points, factor){ |
|
let newPoints = [], |
|
midX, midY, rangeX, rangeY; |
|
for(let p=0; p<points.length; p++){ |
|
newPoints.push(points[p]); |
|
if(p == points.length-1){ |
|
midX = d3.mean([points[p][0], points[0][0]]); |
|
midY = d3.mean([points[p][1], points[0][1]]); |
|
rangeX = Math.abs(points[p][0]-points[0][0]); |
|
rangeY = Math.abs(points[p][1]-points[0][1]); |
|
}else{ |
|
midX = d3.mean([points[p][0], points[p+1][0]]); |
|
midY = d3.mean([points[p][1], points[p+1][1]]); |
|
rangeX = Math.abs(points[p][0]-points[p+1][0]); |
|
rangeY = Math.abs(points[p][1]-points[p+1][1]); |
|
} |
|
let newX = rnorm(midX, rangeX*factor), |
|
newY = rnorm(midY, rangeY*factor); |
|
newPoints.push([newX, newY]); |
|
} |
|
newPoints.push(points[0]); |
|
return newPoints; |
|
} |
|
|
|
function draw(points){ |
|
context.beginPath(); |
|
context.moveTo(points[0][0], points[0][1]); |
|
for(let v=1; v<points.length; v++){ |
|
context.lineTo(points[v][0], points[v][1]); |
|
} |
|
context.closePath(); |
|
context.fill(); |
|
} |
|
|
|
function paint(shape, colour, deforms, layers){ |
|
context.fillStyle = colour; |
|
for(let l=0; l<layers; l++){ |
|
let layer = shape; |
|
for(let it=0; it<=deforms; it++){ |
|
layer = deform(layer, 0.8); |
|
if(it == deforms){ |
|
draw(layer); |
|
} |
|
} |
|
} |
|
} |
|
|
|
d3.select(window).on('dblclick', () => { |
|
let trans = d3.mouse(canvas.node()); |
|
let shape = makeShape(trans[0], trans[1], 50), |
|
maxIt = 1; |
|
for(let it=0; it<=maxIt; it++){ |
|
shape = deform(shape, 0.5); |
|
if(it == maxIt){ |
|
paint(shape, `hsla(${Math.random()*150+150},70%,50%,0.005)`, 8, 50); |
|
} |
|
} |
|
}); |
|
|
|
</script> |
|
</body> |
|
</html> |