Этот коммит содержится в:
Maarten 2024-10-04 22:38:03 +02:00
родитель dfb3ca9b36
Коммит 568e040cd2
4 изменённых файлов: 84 добавлений и 27 удалений

22
package-lock.json сгенерированный
Просмотреть файл

@ -17,6 +17,7 @@
"d3-array": "^3.2.4",
"d3-fetch": "^3.0.1",
"d3-scale": "^4.0.2",
"d3-shape": "^3.2.0",
"d3-time-format": "^4.1.0",
"eslint": "^9.0.0",
"eslint-config-prettier": "^9.1.0",
@ -1289,6 +1290,15 @@
"node": ">=12"
}
},
"node_modules/d3-path": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
"integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
"dev": true,
"engines": {
"node": ">=12"
}
},
"node_modules/d3-scale": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
@ -1305,6 +1315,18 @@
"node": ">=12"
}
},
"node_modules/d3-shape": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
"integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
"dev": true,
"dependencies": {
"d3-path": "^3.1.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/d3-time": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",

Просмотреть файл

@ -20,6 +20,7 @@
"d3-array": "^3.2.4",
"d3-fetch": "^3.0.1",
"d3-scale": "^4.0.2",
"d3-shape": "^3.2.0",
"d3-time-format": "^4.1.0",
"eslint": "^9.0.0",
"eslint-config-prettier": "^9.1.0",

Просмотреть файл

@ -1,7 +1,9 @@
<script>
import { scaleUtc, scalePoint, scaleOrdinal } from 'd3-scale';
import { scaleUtc, scalePoint, scaleOrdinal, scaleLinear, scaleTime } from 'd3-scale';
import { extent } from 'd3-array';
import { utcFormat } from 'd3-time-format';
import { area, stack, curveNatural } from 'd3-shape';
import { max, union, index } from 'd3-array';
import { fade } from 'svelte/transition';
import Bubble from '$lib/components/Bubble.svelte';
import Square from '$lib/components/Square.svelte';
@ -9,6 +11,7 @@
export let cases;
export let events;
export let metrics;
const margins = {
top: 24,
@ -17,30 +20,12 @@
left: 120
};
const keyEvents = [
{
date: new Date('2024-03-21'),
title: 'Key event number 1',
description: 'A very interesting event that happened somewhere.'
},
{
date: new Date('2024-04-25'),
title: 'Key event number 2',
description: 'A somewhat less interesting event, still interesting, though.'
},
{
date: new Date('2024-08-01'),
title: 'Key event number 3',
description: 'Yet another key event.'
}
];
let width;
let height = 280;
$: dateExtent = extent(cases.map((d) => new Date(d.attribution_date)));
$: xScale = scaleUtc(dateExtent, [0, width - margins.right - margins.left]);
$: xScale = scaleTime(dateExtent, [0, width - margins.right - margins.left]);
$: ticks = xScale.ticks(5);
const actorNations = ['Key event', 'China', 'Iran', 'North Korea', 'Russia'];
@ -49,6 +34,29 @@
let yScale = scalePoint(actorNations, [height - margins.bottom - margins.top, 0]).padding(1);
let colorScale = scaleOrdinal(actorNations, colors);
$: stackedMetrics = stack()
.keys(union(metrics.map((d) => d.country)))
//.keys(["China", "Iran", "Russia"])
.value(([, D], key) => D.get(key).posts)
(index(metrics, d => d.date, d => d.country));
$: console.log(stackedMetrics)
let stackMax = 0;
$: if (stackedMetrics.length > 0) {
stackMax = max(stackedMetrics[stackedMetrics.length - 1].map((d) => d[1]));
}
$: yScaleStack = scaleLinear([0, stackMax], [800 - margins.bottom - margins.top, 0]);
let areaGenerator
$: if(xScale && yScaleStack) {
areaGenerator = area()
.x((d) => xScale(d.data[0]))
.y0((d) => yScaleStack(d[0]))
.y1((d) => yScaleStack(d[1]))
.curve(curveNatural)
}
// Tooltip
let showTooltip = false;
let tooltipContent;
let tooltipX;
@ -142,16 +150,28 @@
stroke-width={2}
ttContent={`<p style='font-weight; bold;'>${event.Title}</p>
<p>${event.Description}</p>`}
bind:tooltipContent
bind:tooltipX
bind:tooltipY
bind:showTooltip
bind:tooltipContent
bind:tooltipX
bind:tooltipY
bind:showTooltip
></Square>
{/each}
{/if}
</g>
{/if}
</svg>
<svg {width} height={800}>
{#if xScale}
<g transform={`translate(${margins.left},${margins.top})`}>
{#if stackedMetrics.length > 0 && areaGenerator}
{#each stackedMetrics as serie}
<path d={areaGenerator(serie)} stroke={'white'} stroke-width={1} fill={colorScale(serie.key)}>
</path>
{/each}
{/if}
</g>
{/if}
</svg>
{#if showTooltip}
<Tooltip {tooltipX} {tooltipY} {tooltipContent} />
{/if}

Просмотреть файл

@ -28,8 +28,8 @@
$: displayDataAs = isMobile ? "Cards" : "Table"
let cases = [];
let events = [];
let metrics = [];
onMount(async function () {
const response = await csv(`https://fiat-2024-processed-data.s3.us-west-2.amazonaws.com/Demo_Attribution_Data.csv`);
@ -60,7 +60,21 @@
events.forEach(d => {
d.date = new Date(d.Date)
})
const metricsResponse = await csv('https://fiat-2024-processed-data.s3.us-west-2.amazonaws.com/fiat_country_metrics.csv')
//metrics = metricsResponse
//console.log(metrics)
metrics = metricsResponse.map(d => {
let obj = {}
obj.date = new Date(d.Date),
obj.posts = +d.Posts
obj.country = d.Country
return obj
}
)
metrics.sort((a, b) =>{
return a.date - b.date
})
});
$: if (cases) {
@ -127,7 +141,7 @@
{#if isMobile}
<TimelineMobile {cases}></TimelineMobile>
{:else}
<Timeline {cases} {events}></Timeline>
<Timeline {cases} {events} {metrics}></Timeline>
{/if}
</div>
</section>