Mobile timeline, styling
Этот коммит содержится в:
родитель
193948142e
Коммит
947d5f184d
@ -8,7 +8,7 @@
|
||||
<div class="card" transition:fade id={'case-' + cardData.Attribution_ID}>
|
||||
<div class="card-header">
|
||||
<div class="card-header-title">
|
||||
<h2 class="is-size-3">{cardData.Short_Title}</h2>
|
||||
<h2 class="is-size-5">{cardData.Short_Title}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-image">
|
||||
|
||||
@ -104,6 +104,7 @@
|
||||
>
|
||||
{/each}
|
||||
{#each cases as attrCase}
|
||||
{console.log(attrCase.Attribution_ID)}
|
||||
{#if attrCase.show}
|
||||
<a href={'#case-' + attrCase.Attribution_ID} transition:fade>
|
||||
<Bubble
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<script>
|
||||
import { scaleUtc, scalePoint, scaleOrdinal } from 'd3-scale';
|
||||
import { extent } from 'd3-array';
|
||||
import { scaleUtc, scalePoint, scaleOrdinal, scaleLinear } from 'd3-scale';
|
||||
import { max, extent } from 'd3-array';
|
||||
import { utcFormat } from 'd3-time-format';
|
||||
import { fade } from 'svelte/transition'
|
||||
|
||||
@ -14,17 +14,20 @@
|
||||
};
|
||||
|
||||
let width;
|
||||
let height = 400;
|
||||
let height = 500;
|
||||
|
||||
$: dateExtent = extent(cases.map((d) => new Date(d.attribution_date)));
|
||||
|
||||
$: yScale = scaleUtc(dateExtent, [0, height - margins.top - margins.bottom]);
|
||||
$: opacityScale = scaleLinear()
|
||||
.domain([0, max(cases.map(d => d.attribution_total_score))])
|
||||
.range([0.2, 1])
|
||||
$: ticks = yScale.ticks(5);
|
||||
|
||||
const actorNations = ['China', 'Iran', 'North Korea', 'Russia'];
|
||||
const colors = ['#0f4c8a', '#8a0f8a', '#8a4d0f', '#0f8a0f'];
|
||||
|
||||
$: xScale = scalePoint(actorNations, [0, width - margins.left - margins.right]).padding(1);
|
||||
$: xScale = scalePoint(actorNations, [0, width - margins.left - margins.right]).padding(0.5);
|
||||
let colorScale = scaleOrdinal(actorNations, colors);
|
||||
</script>
|
||||
|
||||
@ -39,7 +42,7 @@
|
||||
y1={0}
|
||||
y2={height - margins.bottom - margins.top}
|
||||
style:stroke={colorScale(nation)}
|
||||
stroke-width={2}
|
||||
stroke-width={xScale.step()*0.9}
|
||||
opacity={0.3}
|
||||
></line>
|
||||
<text
|
||||
@ -68,14 +71,15 @@
|
||||
{/each}
|
||||
{#each cases as attrCase}
|
||||
{#if attrCase.show}
|
||||
<a href={'#case-' + attrCase.attribution_id} transition:fade>
|
||||
<a href={'#case-' + attrCase.Attribution_ID} transition:fade>
|
||||
<circle
|
||||
cy={yScale(new Date(attrCase.attribution_date))}
|
||||
cx={xScale(attrCase.actor_nation[0])}
|
||||
r={6}
|
||||
style:fill={colorScale(attrCase.actor_nation[0])}
|
||||
stroke={'#ffffff'}
|
||||
stroke-width={2}
|
||||
stroke-width={1}
|
||||
opacity={opacityScale(attrCase.attribution_total_score)}
|
||||
></circle>
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { csv } from 'd3-fetch';
|
||||
import { max, extent } from 'd3-array';
|
||||
import { base } from '$app/paths';
|
||||
import CaseCard from '$lib/components/CaseCard.svelte';
|
||||
import CaseTable from '$lib/components/CaseTable.svelte';
|
||||
import Timeline from '$lib/components/Timeline.svelte';
|
||||
@ -59,7 +58,8 @@
|
||||
d.Source,
|
||||
d.Source_Nation,
|
||||
d.Source_Category
|
||||
].flat()
|
||||
]
|
||||
.flat()
|
||||
.join('__')
|
||||
.toLowerCase();
|
||||
|
||||
@ -112,30 +112,29 @@
|
||||
}
|
||||
});
|
||||
|
||||
const sortFunction = (option) => function(a, b){
|
||||
if(option.type == 'string' || option.type == 'date' || option.type == 'number'){
|
||||
if(a[option.id] < b[option.id]){
|
||||
return -1
|
||||
const sortFunction = (option) =>
|
||||
function (a, b) {
|
||||
if (option.type == 'string' || option.type == 'date' || option.type == 'number') {
|
||||
if (a[option.id] < b[option.id]) {
|
||||
return -1;
|
||||
}
|
||||
if(b[option.id] < a[option.id]){
|
||||
return 1
|
||||
}
|
||||
else {
|
||||
return 0
|
||||
if (b[option.id] < a[option.id]) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if(option.type == 'array'){
|
||||
if(a[option.id][0] < b[option.id][0]){
|
||||
return -1
|
||||
}
|
||||
if(b[option.id][0] < a[option.id][0]){
|
||||
return 1
|
||||
}
|
||||
else {
|
||||
return 0
|
||||
if (option.type == 'array') {
|
||||
if (a[option.id][0] < b[option.id][0]) {
|
||||
return -1;
|
||||
}
|
||||
if (b[option.id][0] < a[option.id][0]) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$: if (cases) {
|
||||
cases = cases.map((d) => ({
|
||||
@ -151,8 +150,7 @@
|
||||
includesTextSearch($textSearchFilter, d.search)
|
||||
}));
|
||||
}
|
||||
$: sortedCases = [...cases].sort(sortFunction(selectedSorting))
|
||||
$: console.log(sortedCases.map(d => d[selectedSorting.id]))
|
||||
$: sortedCases = [...cases].sort(sortFunction(selectedSorting));
|
||||
|
||||
let width = 1200;
|
||||
let margin = {
|
||||
@ -172,15 +170,15 @@
|
||||
};
|
||||
|
||||
const sortOptions = [
|
||||
{id: 'attribution_date', label: 'Attribution Date', type: 'date'},
|
||||
{id: 'attribution_total_score', label: 'Attribution Score', type: 'number'},
|
||||
{id: 'actor_nation', label: 'Actor Nation', type: 'array'},
|
||||
{id: 'platform', label: 'Platform', type: 'array'},
|
||||
{id: 'source', label: 'Source', type: 'array'},
|
||||
{id: 'Source_Category', label: 'Source Category', type: 'string'},
|
||||
]
|
||||
{ id: 'attribution_date', label: 'Attribution Date', type: 'date' },
|
||||
{ id: 'attribution_total_score', label: 'Attribution Score', type: 'number' },
|
||||
{ id: 'actor_nation', label: 'Actor Nation', type: 'array' },
|
||||
{ id: 'platform', label: 'Platform', type: 'array' },
|
||||
{ id: 'source', label: 'Source', type: 'array' },
|
||||
{ id: 'Source_Category', label: 'Source Category', type: 'string' }
|
||||
];
|
||||
|
||||
let selectedSorting = {id: 'attribution_date', label: 'Attribution Date', type: 'date'}
|
||||
let selectedSorting = { id: 'attribution_date', label: 'Attribution Date', type: 'date' };
|
||||
</script>
|
||||
|
||||
<svelte:window bind:innerWidth />
|
||||
@ -225,8 +223,8 @@
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div class="container grid is-col-min-12">
|
||||
<div class="field has-addons">
|
||||
<div class="container cases-controls">
|
||||
<div class="field has-addons cases-control">
|
||||
<div class="buttons has-addons">
|
||||
<button
|
||||
class={displayDataAs == 'Table'
|
||||
@ -246,8 +244,10 @@
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cases-control">
|
||||
<label for="sort-select">Sort cases by </label>
|
||||
<div class="select is-small">
|
||||
<select bind:value={selectedSorting}>
|
||||
<select bind:value={selectedSorting} id="sort-select">
|
||||
{#each sortOptions as sortOpt}
|
||||
<option value={sortOpt}>
|
||||
{sortOpt.label}
|
||||
@ -256,13 +256,14 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{#if displayDataAs == 'Cards'}
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<div class="grid is-col-min-12">
|
||||
{#each cases as attrCase}
|
||||
{#each sortedCases as attrCase}
|
||||
{#if attrCase.show}
|
||||
<div class="cell">
|
||||
<CaseCard cardData={attrCase}></CaseCard>
|
||||
@ -315,4 +316,11 @@
|
||||
padding: 1rem;
|
||||
z-index: 750;
|
||||
}
|
||||
.cases-controls {
|
||||
text-align: center;
|
||||
}
|
||||
.cases-control {
|
||||
display: inline-block;
|
||||
margin-left: 3rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -7,3 +7,7 @@
|
||||
--usa-red: #b22234;
|
||||
--usa-lightred: #c5888f;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
Загрузка…
x
Ссылка в новой задаче
Block a user