Timeline edits
Этот коммит содержится в:
родитель
85e95811ff
Коммит
f75f12e940
@ -1,55 +1,92 @@
|
|||||||
<script>
|
<script>
|
||||||
import { scaleUtc } from 'd3-scale';
|
import { scaleUtc, scalePoint, scaleOrdinal } from 'd3-scale';
|
||||||
import { extent } from 'd3-array';
|
import { extent } from 'd3-array';
|
||||||
import { utcFormat } from 'd3-time-format';
|
import { utcFormat } from 'd3-time-format';
|
||||||
|
import { fade } from 'svelte/transition'
|
||||||
|
|
||||||
export let cases;
|
export let cases;
|
||||||
|
|
||||||
const margins = {
|
const margins = {
|
||||||
top: 24,
|
top: 24,
|
||||||
right: 24,
|
right: 24,
|
||||||
bottom: 24,
|
bottom: 38,
|
||||||
left: 24
|
left: 120
|
||||||
};
|
};
|
||||||
|
|
||||||
let width;
|
let width;
|
||||||
let height = 120;
|
let height = 280;
|
||||||
|
|
||||||
$: dateExtent = extent(cases.map((d) => new Date(d.attribution_date)));
|
$: dateExtent = extent(cases.map((d) => new Date(d.attribution_date)));
|
||||||
|
|
||||||
$: xScale = scaleUtc(dateExtent, [0, width - margins.right - margins.left]);
|
$: xScale = scaleUtc(dateExtent, [0, width - margins.right - margins.left]);
|
||||||
$: ticks = xScale.ticks(5);
|
$: ticks = xScale.ticks(5);
|
||||||
|
|
||||||
|
const actorNations = ['China', 'Iran', 'North Korea', 'Russia'];
|
||||||
|
const colors = ['#0f4c8a', '#8a0f8a', '#8a4d0f', '#0f8a0f'];
|
||||||
|
|
||||||
|
let yScale = scalePoint(actorNations, [height - margins.bottom - margins.top, 0]).padding(1);
|
||||||
|
let colorScale = scaleOrdinal(actorNations, colors);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="timeline-container" bind:clientWidth={width}>
|
<div class="timeline-container" bind:clientWidth={width}>
|
||||||
<svg {width} {height}>
|
<svg {width} {height}>
|
||||||
{#if xScale}
|
{#if xScale}
|
||||||
<g transform={`translate(${margins.left},${margins.top})`}>
|
<g transform={`translate(${margins.left},${margins.top})`}>
|
||||||
<line x1={0} x2={width} y1={0} y2={0} stroke={'#000000'} stroke-width={2}></line>
|
<!--line
|
||||||
|
x1={0}
|
||||||
|
x2={width}
|
||||||
|
y1={height - margins.bottom - margins.top}
|
||||||
|
y2={height - margins.bottom - margins.top}
|
||||||
|
stroke={'#000000'}
|
||||||
|
stroke-width={2}
|
||||||
|
></line-->
|
||||||
|
{#each actorNations as nation}
|
||||||
|
<line
|
||||||
|
x1={0}
|
||||||
|
x2={width}
|
||||||
|
y1={yScale(nation)}
|
||||||
|
y2={yScale(nation)}
|
||||||
|
style:stroke={colorScale(nation)}
|
||||||
|
stroke-width={2}
|
||||||
|
opacity={0.3}
|
||||||
|
></line>
|
||||||
|
<text
|
||||||
|
class="country-label"
|
||||||
|
x={-10}
|
||||||
|
y={yScale(nation) + 4}
|
||||||
|
text-anchor={"end"}
|
||||||
|
fill={colorScale(nation)}
|
||||||
|
>{nation}</text>
|
||||||
|
{/each}
|
||||||
{#each ticks as tick}
|
{#each ticks as tick}
|
||||||
<line
|
<line
|
||||||
x1={xScale(tick)}
|
x1={xScale(tick)}
|
||||||
x2={xScale(tick)}
|
x2={xScale(tick)}
|
||||||
y1={0}
|
y1={height - margins.bottom - margins.top}
|
||||||
y2={12}
|
y2={height - margins.bottom - margins.top + 10}
|
||||||
stroke={'#000000'}
|
stroke={'#bbbbbb'}
|
||||||
stroke-width={2}
|
stroke-width={1}
|
||||||
></line>
|
></line>
|
||||||
<text x={xScale(tick)} y={32} text-anchor={'middle'}>{utcFormat('%b %d')(tick)}</text>
|
<text
|
||||||
|
class="time-axis-tick-label"
|
||||||
|
x={xScale(tick)}
|
||||||
|
y={height - margins.bottom - margins.top + 24}
|
||||||
|
text-anchor={'middle'}>{utcFormat('%b')(tick)}</text
|
||||||
|
>
|
||||||
{/each}
|
{/each}
|
||||||
{#each cases as attrCase}
|
{#each cases as attrCase}
|
||||||
{#if attrCase.show}
|
{#if attrCase.show}
|
||||||
<a href={'#case-' + attrCase.attribution_id}>
|
<a href={'#case-' + attrCase.attribution_id} transition:fade>
|
||||||
<circle
|
<circle
|
||||||
cx={xScale(new Date(attrCase.attribution_date))}
|
cx={xScale(new Date(attrCase.attribution_date))}
|
||||||
cy={0}
|
cy={yScale(attrCase.actor_nation[0])}
|
||||||
r={6}
|
r={6}
|
||||||
fill={'#000000'}
|
style:fill={colorScale(attrCase.actor_nation[0])}
|
||||||
stroke={'#ffffff'}
|
stroke={'#ffffff'}
|
||||||
stroke-width={2}
|
stroke-width={2}
|
||||||
></circle>
|
></circle>
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</g>
|
</g>
|
||||||
{/if}
|
{/if}
|
||||||
@ -60,4 +97,12 @@
|
|||||||
.timeline-container {
|
.timeline-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
.country-label {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
.time-axis-tick-label {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
fill: #888888;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -48,7 +48,7 @@
|
|||||||
methodFilter.init(cases, 'methods')
|
methodFilter.init(cases, 'methods')
|
||||||
$attributionScoreFilter = attributionScoreDef;
|
$attributionScoreFilter = attributionScoreDef;
|
||||||
|
|
||||||
//console.log(cases.map(d => d.attribution_date))
|
console.log(cases.map(d => d.campaign))
|
||||||
});
|
});
|
||||||
|
|
||||||
$: if (cases) {
|
$: if (cases) {
|
||||||
@ -104,8 +104,8 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="field has-addons">
|
<div class="field has-addons">
|
||||||
<div class="buttons has-addons">
|
<div class="buttons has-addons">
|
||||||
<button class={displayDataAs == "Table" ? "button is-success is-selected" : "button"} on:click={() => {displayDataAs = "Table"}}>Table</button>
|
<button class={displayDataAs == "Table" ? "button is-dark is-selected is-small" : "button is-small"} on:click={() => {displayDataAs = "Table"}}>Table</button>
|
||||||
<button class={displayDataAs == "Cards" ? "button is-success is-selected" : "button"} on:click={() => {displayDataAs = "Cards"}}>Cards</button>
|
<button class={displayDataAs == "Cards" ? "button is-dark is-selected is-small" : "button is-small"} on:click={() => {displayDataAs = "Cards"}}>Cards</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Загрузка…
x
Ссылка в новой задаче
Block a user