Skip to content

Instantly share code, notes, and snippets.

@janwillemtulp
Last active March 15, 2023 07:39
Show Gist options
  • Save janwillemtulp/2194c035c76262de00eb6df18462e5c1 to your computer and use it in GitHub Desktop.
Save janwillemtulp/2194c035c76262de00eb6df18462e5c1 to your computer and use it in GitHub Desktop.
Axpo UXM Dataviz Workshop
<h1>This is the layout</h1>
<slot />
<footer>This is the footer</footer>
export async function load({ fetch, params, url }) {
const currency = url.searchParams.get('currency') || 'CHF';
const ratesResponse = await fetch(
`https://api.frankfurter.app/2022-01-01..2023-12-31?to=${currency}`
);
const ratesData = await ratesResponse.json();
const currenciesResponse = await fetch('https://api.frankfurter.app/currencies');
const currenciesData = await currenciesResponse.json();
return {
rates: ratesData,
currencies: currenciesData,
selectedCurrency: currency
};
}
<script>
import { range, max, extent } from 'd3-array';
import Chart from './../Chart.svelte';
import { setContext } from 'svelte';
import { scaleLinear, scaleTime } from 'd3-scale';
export let data;
$: console.log(data);
const width = 800;
const height = 400;
const margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
};
setContext('app', { width, height, margin });
const w = width - margin.left - margin.right;
const h = height - margin.top - margin.bottom;
let count = 25;
$: data2 = range(count).map((_, i) => ({
x: i,
y: Math.random() * h
}));
$: currencies = Object.entries(data.rates.rates).map(([date, rates]) => {
return {
date: new Date(date),
rates
};
});
$: xTime = scaleTime()
.domain(extent(currencies, (d) => d.date))
.range([0, w]);
$: yScale = scaleLinear()
.domain([0, max(currencies, (d) => d.rates[data.selectedCurrency])])
.range([h, 0]);
$: currenciesData = currencies.map((d) => ({
x: xTime(d.date),
y: yScale(d.rates[data.selectedCurrency]),
...d
}));
$: console.log(yScale.domain(), currenciesData);
</script>
<div class="currencies">
{#each Object.entries(data.currencies) as [code]}
<a href="?currency={code}" class:active={code === data.selectedCurrency}>{code}</a>
{/each}
</div>
<Chart data={currenciesData} title="Frankfurter API data" />
<Chart data={data2} title="This is overridden" />
<input type="range" min={1} max={50} bind:value={count} step={1} />
<style>
.currencies {
width: 600px;
}
.active {
background-color: rgb(60, 95, 166);
color: white;
}
a {
display: inline-flex;
width: 50px;
background-color: #d8e8fd;
border: none;
padding: 5px 10px;
margin: 2px;
border-radius: 5px;
cursor: pointer;
font-style: none;
color: black;
font-size: 12px;
justify-content: center;
}
a:hover {
background-color: rgb(138, 177, 255);
}
input[type='range'] {
width: 400px;
display: block;
}
</style>
<script>
import { extent } from 'd3-array';
import { scaleLinear } from 'd3-scale';
import { line, curveCardinal } from 'd3-shape';
import { getContext } from 'svelte';
import DataPoint from './DataPoint.svelte';
export let title = 'Chart';
export let data = [];
const { width, height, margin } = getContext('app');
const w = width - margin.left - margin.right;
$: xScale = scaleLinear()
.domain(extent(data, (d) => d.x))
.range([0, w]);
let active = false;
const l = line()
.x((d) => xScale(d.x))
.y((d) => d.y)
.curve(curveCardinal);
</script>
<h1>{title}</h1>
<svg {width} {height}>
<g transform="translate({margin.left}, {margin.top})">
<path d={l(data)} />
{#each data as d, i}
<DataPoint {i} x={xScale(d.x)} y={d.y} r={3} />
{/each}
</g>
</svg>
<style>
svg {
border: 1px solid black;
}
.active {
fill: blue;
}
path {
fill: none;
stroke: black;
stroke-width: 3;
}
</style>
<script>
import { tweened } from 'svelte/motion';
export let x = 0;
export let y = 0;
export let i;
const tween = tweened({ x, y }, { duration: 200, delay: i * 10 });
$: $tween = { x, y };
</script>
<circle cx={$tween.x} cy={$tween.y} r={3} />
<style>
circle {
fill: red;
stroke: black;
stroke-width: 2;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment