I'm quite new to svelte and I'm trying to get a canvas to render on the full screen using svelte. Sounds quite easy to do, but I can't get it to work properly. I'm binding a width
and height
variable to the clientWidth
/clientHeight
of the parent and using these variables to set the dimensions of the canvas. The issue now is that when onMount
is called, the width
and height
variables are set but they are not applied to the canvas element yet. This means when the canvas renders for the first time, it still has the initial dimensions and not the ones of the parent. Only when I render it a second time it has the proper dimensions. How can get the canvas to have the right dimensions on the first render or render the canvas again when it has the proper dimensions?
Here you can find a "working" version.
<script>
import { onMount } from "svelte";
let canvas;
let ctx;
let width = 1007;
let height = 1140;
const draw = () => {
ctx.clearRect(0, 0, width, height);
ctx.beginPath();
ctx.moveTo(width/2 - 50, height/2);
ctx.arc(width/2, height/2, 50, 0, 2 * Math.PI);
ctx.fill();
}
onMount(() => {
ctx = canvas.getContext("2d");
draw();
setTimeout(draw, 5000);
});
</script>
<style>
.container {
width: 100%;
height: 100%;
}
</style>
<div
class="container"
bind:clientWidth={width}
bind:clientHeight={height}>
<canvas bind:this={canvas} {width} {height} />
</div>
I'm quite new to svelte and I'm trying to get a canvas to render on the full screen using svelte. Sounds quite easy to do, but I can't get it to work properly. I'm binding a width
and height
variable to the clientWidth
/clientHeight
of the parent and using these variables to set the dimensions of the canvas. The issue now is that when onMount
is called, the width
and height
variables are set but they are not applied to the canvas element yet. This means when the canvas renders for the first time, it still has the initial dimensions and not the ones of the parent. Only when I render it a second time it has the proper dimensions. How can get the canvas to have the right dimensions on the first render or render the canvas again when it has the proper dimensions?
Here you can find a "working" version.
<script>
import { onMount } from "svelte";
let canvas;
let ctx;
let width = 1007;
let height = 1140;
const draw = () => {
ctx.clearRect(0, 0, width, height);
ctx.beginPath();
ctx.moveTo(width/2 - 50, height/2);
ctx.arc(width/2, height/2, 50, 0, 2 * Math.PI);
ctx.fill();
}
onMount(() => {
ctx = canvas.getContext("2d");
draw();
setTimeout(draw, 5000);
});
</script>
<style>
.container {
width: 100%;
height: 100%;
}
</style>
<div
class="container"
bind:clientWidth={width}
bind:clientHeight={height}>
<canvas bind:this={canvas} {width} {height} />
</div>
Share
Improve this question
asked Jul 31, 2020 at 13:28
FlavioFlavio
1,5975 gold badges20 silver badges30 bronze badges
2
- Your code seems to be working fine as far as I'm concerned. svelte.dev/repl/49b8091d3d5c400b8c912be90d03c93e?version=3.24.0 the canvas is always full client width & height, be it on initial load, page refresh or after a resize. I even tried it in different browsers, always worked as expected? – Thomas Hennes Commented Aug 1, 2020 at 11:13
- Hey, thanks for you ment. Yes the size of the canvas is adjusted correctly. The issue is that when onMount is called the width and height variables are set correctly but they are not applied to the canvas yet. This means that when draw() is called the width/height variables don't correspond to the width/height of the canvas. Only on the next render the dimensions of the canvas are set which causes the black circle from draw() to disappear. – Flavio Commented Aug 2, 2020 at 11:10
1 Answer
Reset to default 6You can solve this by waiting for the next 'tick'
import { onMount, tick } from 'svelte';
onMount(async () => {
ctx = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
await tick()
draw();
});
What await tick()
does is to effectively pause execution until all current changes have been applied to the dom
tick in the docs