Skip to content

Instantly share code, notes, and snippets.

@kalebpace
Created May 2, 2023 20:03
Show Gist options
  • Save kalebpace/2b381bd7f75fd36324c1b5f881ae26b5 to your computer and use it in GitHub Desktop.
Save kalebpace/2b381bd7f75fd36324c1b5f881ae26b5 to your computer and use it in GitHub Desktop.
Rough implementation of SSR/CSR ECharts support in Svelte
<script lang="ts" context="module">
// ECharts does not export init options type, so we mirror
// https://echarts.apache.org/en/api.html#echarts.init
export type ContainerOpts =
| {
devicePixelRatio?: number;
renderer?: 'svg' | 'canvas';
useDirtyRect?: boolean;
useCoarsePointer?: boolean;
pointerSize?: number;
width?: number | string;
height?: number | string;
// we use svelte's browser module to determine ssr mode later
// ssr?: boolean
}
| undefined;
// https://echarts.apache.org/en/theme-builder.html
// Support default theme selection
export type ThemeOpts =
| 'vintage'
| 'dark'
| 'westeros'
| 'essos'
| 'wonderland'
| 'walden'
| 'chalk'
| 'infographic'
| 'macarons'
| 'roma'
| 'shine'
| 'purple-passion'
| 'halloween'
| string
| undefined;
</script>
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import { browser } from '$app/environment';
import { init } from 'echarts';
import type { ECharts, EChartsCoreOption } from 'echarts';
export let containerOpts: ContainerOpts;
export let chartOpts: EChartsCoreOption;
export let theme: ThemeOpts;
$: chartOpts &&
instance &&
instance.setOption({
...chartOpts,
// Ensure SVG is entirely rendered via SSR before returning response,
// but allow user to override this behavior
// https://echarts.apache.org/en/option.html#series-scatter.progressive
progressive: chartOpts?.progressive || 0
});
let container: any;
let instance: ECharts;
if (!browser) {
// Force SVG since this component doesnt implement canvas support yet
instance = init(null as any, theme, {
...containerOpts,
ssr: true,
renderer: "svg"
});
}
// We first render SSR and return a response, then ship the entire data set to the client to be hydrated for interactivity
// if using SSR with CSR in sveltekit
onMount(async () => {
instance = init(container as HTMLElement, theme, {
...containerOpts,
ssr: false
});
});
onDestroy(async () => {
instance.dispose();
});
</script>
<svelte:window on:resize={() => instance.resize()} />
<div bind:this={container}>
{#if !browser}
{@html instance.renderToSVGString() || ''}
{/if}
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment