I'm struggling to make uPlot work with svelte. I can't find any minimal working example, so I'm crafting one myself and it does not render. Repro goes as follows:
npm create svelte repro
# y
# skeleton
# yes TypeScript
# yes ESLing
# yes Prettier
# yes Playwright
npm install
npm i uplot
npm run dev -- --open
And then I modify index.svelte
to contain the following (best I could come up with, thanks to this answer In SvelteKit, how do you conditionally include a `<script>` block in `app.html`?)
<script lang="ts">
import { browser } from '$app/env';
import { onMount } from 'svelte';
import "uplot/dist/uPlot.min.css"
let uPlot;
function redraw(uPlot) {
if(!uPlot) return;
let data = [new Float32Array([1, 2, 3, 4, 5]), new Float32Array([1, 3, 2, 5, 4])];
const opts = {
width: 600,
height: 300,
scales: {x: {time: false}},
series: [{label: "x"}, {label: "y", stroke: "red"}],
};
new uPlot(opts, data, document.getElementById("uPlot"));
}
onMount(async () => {
if (browser) {
const uplotModule = await import('uplot');
uPlot = uplotModule.default;
console.log("uplot loaded", uplotModule, uPlot);
}
})
$: redraw(uPlot)
</script>
<h1>Welcome to SvelteKit</h1>
<div id="uPlot"></div>
It does not render the plot :( What am I missing?
There are several things to fix or improve:
bind:this
or events insteadonMount
already executes only in the browser<script lang="ts">
import { onMount } from 'svelte';
import 'uplot/dist/uPlot.min.css';
let plotContainer;
function redraw(uPlot) {
let data = [[1, 2, 3, 4, 5], [1, 3, 2, 5, 4]];
const opts = {
width: 600,
height: 300,
scales: {x: {time: false}},
series: [{label: "x"}, {label: "y", stroke: "red"}],
};
new uPlot(opts, data, plotContainer);
}
onMount(async () => {
const uplotModule = await import('uplot');
const uPlot = uplotModule.default;
redraw(uPlot);
})
</script>
<div bind:this={plotContainer}></div>