Skip to content

Instantly share code, notes, and snippets.

@pfirpfel
Last active April 20, 2021 12:42
Show Gist options
  • Select an option

  • Save pfirpfel/407e41f591fdd60b0fb4e65d66435106 to your computer and use it in GitHub Desktop.

Select an option

Save pfirpfel/407e41f591fdd60b0fb4e65d66435106 to your computer and use it in GitHub Desktop.
[HTML5 Canvas] Clip-Mask
<html>
<head>
<title>Canvas Clip Mask</title>
</head>
<body>
<input id="karma" type="range" min="0" max="100" value="50" style="width: 500px;"/>
<br>
<canvas id="canvas"></canvas>
<script src="knot.js" type="text/javascript"></script>
<script src="main.js" type="text/javascript"></script>
<script>
init();
</script>
</body>
</html>
var generateKnot = function(a, b){
var transformPath = function(path, transX, transY){
return path.map(function(coord){
return [coord[0] + transX, coord[1] + transY];
});
};
var rotatePath = function(path, centerX, centerY, angle){
return path.map(function(coord){
var s = Math.sin(angle);
var c = Math.cos(angle);
var x = coord[0] - centerX;
var y = coord[1] - centerY;
var newX = x * c - y * s;
var newY = x * s + y * c;
return [newX + centerX, newY + centerY];
});
};
var c = 3*a + 2*b;
var d = 4*a + 3*b;
var e = a + b;
var baseP = [[0,0],[c,0],[c,c],[a+b,c],[a+b,c-a],[c-a,c-a],[c-a,a],[a,a],[a,d],[0,d]];
var baseI = [[0,0],[a,0],[a,c],[0,c]];
var baseJ = [[0,0],[c,0],[c,e+a],[c-a,e+a],[c-a,a],[a,a],[a,d],[0,d]];
var knot = [];
// Ps
knot.push(transformPath(rotatePath(baseP, 0, 0, Math.PI*1.5), 0, c));
knot.push(transformPath(rotatePath(baseP, 0, 0, Math.PI*0.5), d+d+2*b+a, d+2*b+a+e));
// Js
knot.push(transformPath(baseJ, d+b, 0));
knot.push(transformPath(rotatePath(baseJ, 0, 0, Math.PI*0.5), d+d+2*b+a, c-a));
knot.push(transformPath(rotatePath(baseJ, 0, 0, Math.PI), c+e+a+b, d+d+2*b+a));
knot.push(transformPath(rotatePath(baseJ, 0, 0, Math.PI*1.5), 0, c+d+b));
//Is
knot.push(transformPath(rotatePath(baseI, 0, 0, Math.PI*0.5), c+c+b, d+b));
knot.push(transformPath(baseI, c-a, c+b));
knot.push(transformPath(baseI, 6*a+6*b, c+b));
var height = 2*d+2*b+a;
var hypo = height*Math.pow(2,1/2);
// rotate knot around center
knot = knot.map(function(path){
return rotatePath(path, height/2, height/2, Math.PI*0.25);
});
// move knot to visible canvas
knot = knot.map(function(path){
return transformPath(path, (hypo-height)/2-((2*a+2*b)*Math.pow(2,1/2)/2), (hypo-height)/2);
});
return knot;
}
var init = function(){
var thinkness = 20;
var padding = 7;
var shape = generateKnot(thinkness, padding);
var height = (9 * thinkness + 8 * padding) * Math.pow(2, 1/2);
var cutoffEdges = (2 * thinkness + 2 * padding) * Math.pow(2, 1/2);
var animate = false;
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
var img = document.createElement('IMG');
canvas.width = Math.ceil(height - cutoffEdges);
canvas.height = Math.ceil(height);
var drawPath = function(path){
var i;
ctx.moveTo(path[0][0], path[0][1]);
for(i = 0; i < path.length; i++){
ctx.lineTo(path[i][0], path[i][1]);
}
ctx.closePath();
};
ctx.fillStyle = "#e0e0e0";
ctx.strokeStyle = "#303030";
ctx.lineWidth = 2;
var render = function(timestamp){
var karma = document.getElementById('karma').value;
ctx.save();
ctx.beginPath();
shape.forEach(drawPath);
ctx.clip();
ctx.fill();
var animX = (animate) ? 5 * Math.sin(timestamp * 0.002) : 0;
var animY = (animate) ? 5 * Math.sin(timestamp * 0.001) : 0;
var karmaPercentage = (100 - karma) / 100;
ctx.drawImage(img, -100 + animX, height * karmaPercentage + animY);
ctx.stroke();
ctx.restore();
if(animate) window.requestAnimationFrame(render);
}
img.onload = function () {
window.requestAnimationFrame(render);
}
document.getElementById('karma').onchange = document.getElementById('karma').oninput = function () {
if(!animate) window.requestAnimationFrame(render);
}
img.src = "http://i.imgur.com/IkwQKXL.jpg";
}
canvas.ondblclick = function(){
animate = !animate;
if(animate) window.requestAnimationFrame(render);
}
}
@pfirpfel
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment