|
1 | 1 | <script>
|
| 2 | +
|
2 | 3 | import { blur } from "svelte/transition"
|
3 | 4 | import { extent } from "d3-array"
|
4 | 5 | import { scaleLinear, scaleSequential } from "d3-scale"
|
5 |
| - import { interpolateYlGnBu, interpolateYlOrRd, select, axisLeft, axisBottom, format, tickFormat, formatLocale } from "d3" |
6 |
| -
|
7 |
| - // should be an array of objects with: |
8 |
| - // year |
9 |
| - // value |
10 |
| - export let data = [] |
11 |
| - export let valueSuffix = "°C" |
12 |
| - export let colourScheme = "cool" // or warm |
13 |
| - $: console.log(colourScheme) |
14 |
| - $: colourRamp = (colourScheme == "cool") ? |
| 6 | + import { interpolateYlGnBu, interpolateYlOrRd, select, axisLeft, axisBottom, format, formatLocale } from "d3" |
| 7 | +
|
| 8 | + // `data` should be an array of objects with: |
| 9 | + // - year |
| 10 | + // - value |
| 11 | + let { data = [], valueSuffix = "°C", colourScheme = "cool" } = $props(); |
| 12 | + |
| 13 | + let colourRamp = $derived((colourScheme == "cool") ? |
15 | 14 | interpolateYlGnBu :
|
16 |
| - interpolateYlOrRd |
| 15 | + interpolateYlOrRd) |
17 | 16 |
|
18 | 17 | // dimensions bound to size of container
|
19 |
| - let height = 500 |
20 |
| - let width = 300 |
| 18 | + let height = $state(500) |
| 19 | + let width = $state(300) |
21 | 20 |
|
22 | 21 | // add padding to chart
|
23 |
| - $: padX = [60, width - 10] |
24 |
| - $: padY = [height - 30, 10] |
| 22 | + let padX = $derived([60, width - 10]) |
| 23 | + let padY = $derived([height - 30, 10]) |
25 | 24 |
|
26 |
| - $: xDomain = extent(data.map(d => d.year)) |
27 |
| - $: yDomain = extent(data.map(d => d.value)) |
| 25 | + let xDomain = $derived(extent(data.map(d => d.year))) |
| 26 | + let yDomain = $derived(extent(data.map(d => d.value))) |
28 | 27 |
|
29 | 28 | // scales (flip the colours if they're cool)
|
30 |
| - $: xScale = scaleLinear() |
| 29 | + let xScale = $derived(scaleLinear() |
31 | 30 | .domain(xDomain)
|
32 |
| - .range(padX) |
33 |
| - $: yScale = scaleLinear() |
| 31 | + .range(padX)) |
| 32 | + let yScale = $derived(scaleLinear() |
34 | 33 | .domain(yDomain)
|
35 |
| - .range(padY) |
36 |
| - $: colourScale = scaleSequential() |
| 34 | + .range(padY)) |
| 35 | + let colourScale = $derived(scaleSequential() |
37 | 36 | .domain(colourScheme == "cool" ? yDomain.reverse() : yDomain)
|
38 |
| - .interpolator(colourRamp) |
| 37 | + .interpolator(colourRamp)) |
39 | 38 |
|
40 | 39 | // temperature formatter (for x-axis)
|
41 | 40 | const tempFormat = formatLocale({
|
42 | 41 | currency: ["", valueSuffix]
|
43 | 42 | });
|
44 | 43 |
|
45 | 44 | // axes
|
46 |
| - let xAxisGroup |
47 |
| - let yAxisGroup |
48 |
| - $: select(xAxisGroup) |
49 |
| - .transition() |
50 |
| - .duration(500) |
51 |
| - .call(axisBottom(xScale).tickFormat(format(".0f"))) |
52 |
| - $: select(yAxisGroup) |
53 |
| - .transition() |
54 |
| - .duration(500) |
55 |
| - .call(axisLeft(yScale).tickFormat(tempFormat.format("$.1f"))) |
| 45 | + let xAxisGroup = $state() |
| 46 | + let yAxisGroup = $state() |
| 47 | + $effect(() => { |
| 48 | + select(xAxisGroup) |
| 49 | + .transition() |
| 50 | + .duration(500) |
| 51 | + .call(axisBottom(xScale).tickFormat(format(".0f"))) |
| 52 | + }); |
| 53 | + $effect(() => { |
| 54 | + select(yAxisGroup) |
| 55 | + .transition() |
| 56 | + .duration(500) |
| 57 | + .call(axisLeft(yScale).tickFormat(tempFormat.format("$.1f"))) |
| 58 | + }); |
56 | 59 |
|
57 | 60 | </script>
|
58 | 61 |
|
| 62 | +{@debug colourScheme} |
| 63 | + |
59 | 64 | <style>
|
60 | 65 |
|
61 | 66 | svg circle {
|
|
70 | 75 | font-size: 14px;
|
71 | 76 | }
|
72 | 77 |
|
73 |
| -
|
74 | 78 | </style>
|
75 | 79 |
|
76 | 80 | <main bind:clientHeight={height} bind:clientWidth={width}>
|
|
0 commit comments