7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SvelteのコンポーネントライブラリーであるLayerChartを触ってみた

Last updated at Posted at 2024-10-28

はじめに

SvelteのコンポーネントライブラリーであるLayerChartを触ってみようと思い立ち、触ってみましたので、その記録を記したいと思います

LayerChartは、Svelte向けのデータ視覚化ライブラリーであり、折れ線グラフや棒グラフなど、データの視覚化に必要なコンポーネント群を提供しています

単体での利用は可能ですが、Svelte UXというUIコンポーネントライブラリのインストール時にLayerChartのオプションがありますので、今回はそちらを利用してすぐに触ってみようという形で進めました

インストール

※パッケージマネージャーにpnpmを利用していますが、npmに読み替えてもOKです

pnpm create svelte-ux@latest

これで対話型のインストールが始まります
テンプレート選択時にLayerChartがありますので、そちらを選択して進めます
スクリーンショット 2024-10-23 13.46.58.png

最後にSvelte5使うかを聞かれますが今回は4のまま進めます
(既にstableでしたが追いついていないのでした、次の記事からは5でいきたい気持ちです)
スクリーンショット 2024-10-23 13.47.41.png

ローカルサーバーを起動すると以下のような画面が出ます
若干崩れていますが、 TaiwindCSSなども同時にセットアップしてくれています
スクリーンショット 2024-10-23 13.55.45.png

ちなみに、上記は実はCSSの設定が壊れていて、手直しすると以下のような感じになります
こちらは修正のPRを送ってマージされたので、以下のデザインになると思います
スクリーンショット 2024-10-29 4.17.08.png

LayerChartのコンポーネントを使ってみる

せっかくなのでGeo系のコンポーネントを使ってみようとしたのですが、その前に簡単な例をやってみようということで、Examplesの Cartesian & Polarの先頭にある、Arcの例をそのまま追加してみます

routes/arc/+page.svelte
<script lang="ts">
	import { Arc, Chart, Svg, Group, LinearGradient, Text } from 'layerchart';
	import { RangeField } from 'svelte-ux';

	let value = 50;
</script>

<main class="p-2">
	<div class="mb-2">
		<RangeField label="Value" bind:value />
	</div>
	<div class="h-[120px] p-4 border rounded">
		<Chart>
			<Svg center>
				<Group y={16}>
					<LinearGradient class="from-secondary to-primary" let:url>
						<Arc
							{value}
							range={[-120, 120]}
							outerRadius={60}
							innerRadius={50}
							cornerRadius={5}
							spring
							let:value
							fill={url}
							track={{ class: 'fill-none stroke-surface-content/10' }}
						>
							<Text
								value={Math.round(value) + '%'}
								textAnchor="middle"
								verticalAnchor="middle"
								class="text-3xl tabular-nums"
							/>
						</Arc>
					</LinearGradient>
				</Group>
			</Svg>
		</Chart>
	</div>
</main>

左のメニューに追加して、見てみるとこんな感じで出来ています(グラデーションがかかるはずでしたが、色の設定をちゃんとしていないのでうまくいってないっぽいですが)
Svelte UXのRangeFieldコンポーネントとの相性も良いですね
Kapture 2024-10-29 at 01.32.59.gif

こんな感じで大量のコンポーネントが用意されていますが、中身を見るとD3を利用しているものが多そうです
D3をSvelteでいい感じに使えるライブラリーみたいなイメージでしょうか?

Geoの例

最後にGeoのコンポーネントの例をやってみます
まず、d3-geoの追加が必要です

pnpm add d3-geo

例ではtopojson-clientも利用していたので追加しています

pnpm add topojson-client

型定義も入れておきます

pnpm add -D @types/d3-geo
pnpm add -D @types/topojson-client
pnpm add -D @types/topojson-specification

データ読み込み箇所

routes/geoTile/+page.ts
import type { GeometryCollection, Topology } from 'topojson-specification';
import pageSource from './+page.svelte?raw';

export async function load() {
	return {
		geojson: (await fetch('https://cdn.jsdelivr.net/npm/us-atlas@3/states-10m.json').then((r) =>
			r.json()
		)) as Topology<{
			states: GeometryCollection<{ name: string }>;
		}>,
		meta: {
			pageSource,
			related: ['examples/ZoomableTileMap']
		}
	};
}

GeoTile使用例

routes/geoTile/+page.svelte
<script lang="ts">
	import { geoMercator } from 'd3-geo';
	import { feature } from 'topojson-client';
	import { Canvas, Chart, GeoPath, GeoTile } from 'layerchart';

	export let data;
	const states = feature(data.geojson, data.geojson.objects.states);

	$: filteredStates = {
		...states,
		features: states.features.filter(
			(d) => Number(d.id) < 60 && d.properties.name !== 'Alaska' && d.properties.name !== 'Hawaii'
		)
	};
	let zoomDelta = 0;

	let selectedFeature: typeof filteredStates | (typeof filteredStates.features)[0];
	$: selectedFeature = filteredStates;
</script>

<main class="p-2">
	<div class="h-[600px]">
		<Chart
			geo={{
				projection: geoMercator,
				fitGeojson: selectedFeature
			}}
		>
			<Canvas>
				<GeoTile
					url={(x, y, z) => {
						return `https://tile.openstreetmap.org/${z}/${x}/${y}.png`;
					}}
					{zoomDelta}
				/>
			</Canvas>
			<Canvas>
				<GeoPath geojson={filteredStates} class="stroke-black/20" />
			</Canvas>
		</Chart>
	</div>
</main>

スクリーンショット 2024-10-29 3.59.30.png
こんな感じで地図が出ます
(LayerChartのExampleをそのまま利用したので、場所はアメリカです)
タイルURLの指定の仕方がちょっと分かりづらくてハマりました

感想

触ってみた感想ですが、D3をラップして使いやすくしているような感じを受けました
グラフ描画が必要であれば、選択肢としてなかなか良いのではないかと思います
Geo系のコンポーネントは個人的には使いづらくて、使い慣れているMaplibre GL JSの方が良いかも…と思いました

7
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?