Lijndiagram met Svelte en D3

Het volgende grafiektype in de cursus is een lijndiagram op basis van temperatuurgegevens in San Francisco, die hier beschikbaar zijn. We zullen hier de scatterplotcode uit de laatste grafiek gebruiken. Enkele interessante dingen over de dataset, het is tijdelijk van aard, dus het diagramtype moet die verandering goed kunnen laten zien.

De row functie in de laatste post is hier erg handig. Laten we de temperature . converteren kolom in getallen. Een van de kolommen is ook een tijdstempel, dus laten we de JS Date . gebruiken constructeur om dat aan te pakken.

const  row  =  function  (data)  {
    data.temperature  =  +data.temperature;
    data.timestamp  =  new  Date(data.timestamp);
    return data;
};

onMount(async  ()  => {
    dataset  =  await  csv(
"https://gist.githubusercontent.com/curran/60b40877ef898f19aeb8/raw/9476be5bd15fb15a6d5c733dd79788fb679c9be9/week_temperature_sf.csv",
    row).then((data)  => {
        return  data;
    });
});

Ik wil de temperatuur plotten op de Y-as en de tijdstempel op de X-as. Aangezien de X-as een tijdstempel is, gaan we scaleTime gebruiken van D3. Ik ga de weegschaal dienovereenkomstig aanpassen

$: xScale  =  scaleTime()
    .domain(extent(dataset, (d)  =>  d.timestamp))
    .range([0, innerWidth]);

$: yScale  =  scaleLinear()
    .domain(extent(dataset, (d)  =>  d.temperature))
    .range([innerHeight, 0]);

Laten we de temperatuur- en tijdstempelpunten doorgeven aan deze schalen in de spreidingsplotlogica die we eerder hadden. De Axis hoeft niet veranderd te worden. Laten we de circle . veranderen logica als volgt:

<circle
    cx={xScale(data.timestamp)}
    cy={yScale(data.temperature)}
    r="5"
    style="fill:firebrick"
/>

Nu moeten we deze punten alleen nog verbinden. En het is gewoon zo dat D3 een functie heeft om precies dat te doen. De line functie in D3 geeft een pad op voorwaarde dat een reeks punten. We kunnen ook de curveNatural . specificeren naar de lijnfunctie.

$: line_gen  =  line()
    .curve(curveNatural)
    .x((d)  =>  xScale(d.timestamp))
    .y((d)  =>  yScale(d.temperature))(dataset);

Laten we deze regel als padelement toevoegen aan de svg <g> element. En stijl het ook zodat het wordt weergegeven als een lijn en niet als een gesloten pad.

<path  d={line_gen} />
<style>
    path {
        fill: transparent;
        stroke: rgb(18, 153, 90);
    }
</style>


Ja, ik ben ook geen fan van die rode stippen. De lijn moet waarschijnlijk ook een beetje dikker zijn. Op dezelfde manier moeten we het formaat van de vinkjes in de onderste as wijzigen. Er zijn ook een paar andere stilistische veranderingen en ik ga ze in één keer doen. Dit is de uiteindelijke grafiek die is gemaakt:

En hier is de code voor hetzelfde:

Als u een eenvoudig lijndiagram wilt of een lijndiagram als basis voor iets anders wilt gebruiken, dan is dit waarschijnlijk wat u zoekt. Ik wil eigenlijk een beetje dieper gaan en een soort van handtekeningachtig effect bereiken.

De eigenschap die we nodig hebben is stroke-dasharray en stroke-dashoffset . Zie het zo, in plaats van een doorlopend pad te tekenen, tekenen we een gestippeld pad. De streepjes zelf zijn echter behoorlijk groot, zo groot als het pad dat nodig is voor deze gegevens of zelfs meer. Oké, in plaats van die vreselijke uitleg te lezen, kun je hier de fantastische, interactieve uitleg van Cassie Evans lezen.

Ik stel de stroke-dasharray in naar een mooi groot getal.stroke-dashoffset staat op 0.

path {
    fill: transparent;
    stroke: rgb(18, 153, 90);
    stroke-width: 2.5;
    stroke-linejoin: round;
    stroke-dasharray: 4400;
    stroke-dashoffset: 0;
}

Visueel is er absoluut geen verschil. De onderliggende wijzigingen stellen ons echter in staat om de animatie te maken. Laten we dat gewoon doen:

path {

    fill: transparent;
    stroke: rgb(18, 153, 90);
    stroke-width: 2.5;
    stroke-linejoin: round;
    stroke-dasharray: 4400;
    stroke-dashoffset: 0;
    animation: draw 8.5s  ease;

}
@keyframes  draw {
    from {
        stroke-dashoffset: 4400;
    }
    to {
        stroke-dashoffset: 0;
    }
}

Aanvankelijk de stroke-dashoffset is ingesteld op 4400. Vandaar dat het streepje buiten de SVG valt, aangezien elk streepje ook 4400 is. Naarmate de overgang vordert, wordt het streepje langzaam zichtbaar in de SVG-viewBox.

Nu wilde ik eigenlijk iets meer dan dit. Ik wilde dat de cirkels die we eerder hadden, op het pad zouden verschijnen terwijl de lijn vooruitgaat. Ik kon het effect niet perfect nabootsen, maar het effect is nog steeds aangenaam, dus hier gaat het. Ik gebruik de fly overgang van Svelte. Laten we circle aanpassen overeenkomstig.

<circle
    cx={xScale(data.timestamp)}
    cy={yScale(data.temperature)}
    r="3"
    in:fly={{ duration: 5000, delay: i  *  15 }}
/>

En dit is de grafiek die wordt geproduceerd door die code toe te voegen

Mooi!! Ik hou echt van het plagende effect van de stippen, die tegelijkertijd allemaal samen maar toch gescheiden lijken.

Hier is de laatste code voor de grafiek -

Dat is alles voor vandaag! Fijne dag nog!