Skip to content

Instantly share code, notes, and snippets.

@smagch
Last active December 20, 2016 19:35
Show Gist options
  • Save smagch/9f23fb04bbc3a52bebc9d03f1416e4a7 to your computer and use it in GitHub Desktop.
Save smagch/9f23fb04bbc3a52bebc9d03f1416e4a7 to your computer and use it in GitHub Desktop.
zoomable canvas
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
body {
margin: 0;
}
.box {
display: block;
margin: 0 auto;
background-color: tomato;
width: 300px;
height: 300px;
border: 2px solid gray;
}
.wrapper {
margin: 0 auto;
}
canvas {
display: block;
margin: 0 auto;
/* width: 100%;
max-height: 100%;*/
}
li {
list-style: none;
}
ul {
position: relative;
overflow: hidden;
transition: transform 0.2s;
margin: 0 auto;
/*transform-origin: 50% 50%;*/
}
.hidden {
display: none;
}
</style>
</head>
<body>
<ul>
<li class="wrapper">
<canvas width="600" height="600"></canvas>
</li>
<li class="wrapper">
<canvas width="600" height="600"></canvas>
</li>
<li class="wrapper">
<canvas width="600" height="600"></canvas>
</li>
<li class="wrapper">
<canvas width="600" height="600"></canvas>
</li>
<li class="wrapper">
<canvas width="600" height="600"></canvas>
</li>
</ul>
<script>
const ul = document.querySelector('ul');
const canvases = Array.from(document.querySelectorAll('canvas'));
function render(canvas, text = 'hello', scale = 1) {
const ctx = canvas.getContext('2d');
const radius = 300 * scale;
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'skyblue';
ctx.fill();
ctx.font = 90 * scale + "px Arial";
ctx.fillStyle = 'white';
ctx.fillText(text, centerX, centerY);
}
let scale = 1;
let zooming = false;
let currentSize = 600;
function zoom(delta) {
if (zooming) {
return;
}
zooming = true;
console.log('clicked');
if (delta < 0 && scale + delta < 0.1) {
return;
}
scale += delta;
const size = Math.floor(600 * scale);
const relSize = size / currentSize;
currentSize = size;
const centerOffset = window.innerHeight * 0.5;
const origHeight = document.body.scrollHeight;
const origTop = document.body.scrollTop;
const centerRatio = (origTop + centerOffset) / origHeight;
const c = origHeight * centerRatio;
const expected = origTop + centerOffset;
ul.style.transform = `scale(${relSize})`;
ul.style.transformOrigin = `50% ${100*centerRatio}%`;
setTimeout(() => {
const height = size * canvases.length;
ul.style.height = height + 'px';
canvases.forEach((canvas, i) => {
canvas.classList.add('hidden');
canvas.width = size;
canvas.height = size;
render(canvas, i + ' hello', scale);
});
const top = height * centerRatio - centerOffset;
document.body.scrollTop = top;
ul.style.transform = '';
ul.style.transformOrigin = '';
zooming = false;
setTimeout(() => {
canvases.forEach(canvas => {
canvas.classList.remove('hidden');
});
}, 100);
}, 1000);
}
document.addEventListener('click', () => {
zoom(0.4);
});
document.addEventListener('keydown', () => {
zoom(-0.2);
});
Array.from(document.querySelectorAll('canvas')).forEach((canvas, i) => {
render(canvas, i + ' hello');
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment