This experiment is about how to zoom the timeline.
It uses an <input type=range/> to adjust the current zoom level.
<input type=range bind:value={zoom}/>
The scale factor is calculated as a reactive statement:
$: scale = zoom / 100
Then we can adjust the left and width position of each timeline element based on the scale factor:
<button class="step" style="width: {step.duration*scale}px; left: {step.offset*scale}px">
<span>{step.label}</span>
</button>
Keyboard event
It also handles keyboard events:
CTRL+plusto zoom in.CTRL+minusto zoom out.CTRL+0to zoom out.
All it took was handling on:keydown with <svelte:window>:
<svelte:window on:keydown={keydown}/>
And the keydown() function looks like this:
function keydown(event) {
// handle CTRL+plus
if (event.key == '+' && event.ctrlKey) {
if (zoom + increment > max) {
zoom = max
} else {
zoom += increment
}
event.preventDefault()
}
// handle CTRL+minus
if (event.key == '-' && event.ctrlKey) {
if (zoom - increment < min) {
zoom = min
} else {
zoom -= increment
}
event.preventDefault()
}
// handle CTRL+0
if (event.key == '0' && event.ctrlKey) {
zoom = 100
event.preventDefault()
}
}
Text wrapping
One final touch was handling word wrapping. When the zoom level is very high, the text is chopped and ... is added.
It’s great that there is a pure css solution for that. In the old days that would have required code.
.step {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
Code
https://svelte.dev/repl/266f525f77c647cb97c655608df4c56e?version=3.37.0
Demo
Notes
- Figure out how to make this work for tick marks as well.