オープンソース冒険:エピソード31:ロシアのタンク損失を視覚化するためにD 3とSvelteを使うこと


前の2つのエピソードでは、私は同じD 3アプリを任意のツーリングせずにしたし、小包で.再びそれをしましょう、しかし、Svelteを使用して、データ・クランチのためにだけD 3を使用して、DOM操作のためにでなく.
D 3はまだグラフ上の軸と線を描画するようなインターフェイスの一部を行いますが、そのデータをSvelteに渡します.

新しいsvelteアプリを作成します


svelteとd 3でアプリケーションを起動するには、次のようにします.
$ npx degit sveltejs/template myapp
$ cd myapp
$ npm install d3
これは私があまり気にしないいくつかの余分なものを含んでいるので、私は不適切なファイルの束を削除し、いくつかの厄介なセミコロンを削除することによって残っているものの構文をクリーンアップしました.

パブリックインデックス。HTML


これは、いくつかのマイナーなクリーンアップとボイラー板から来ている.最も重要な部分は、絶対値から相対URLへの切り替えで、GITHUBページで動作します.
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <link rel="stylesheet" href="./build/bundle.css">
  <script defer src="./build/bundle.js"></script>
</head>
<body>
</body>
</html>

src / mainjs


これは、いくつかのマイナーなクリーンアップで、ボイラー板から来ています
import App from "./App.svelte"

let app = new App({target: document.body})

export default app

src / appスベルト


このコンポーネントはデータを読み込み、実際のグラフ描画コードを呼び出します.
また、いくつかのグローバルスタイリングを行います.これは間違いなく別の静的なCSSファイルに代わりに入れられます.
<script>
import * as d3 from "d3"
import Graph from "./Graph.svelte"

let parseRow = ({date,tank}) => ({date: new Date(date), tank: +tank})

let loadData = async () => {
    let url = "./russia_losses_equipment.csv"
    let data = await d3.csv(url, parseRow)
    data.unshift({date: new Date("2022-02-24"), tank: 0})
    return data
}

let dataPromise = loadData()
</script>

{#await dataPromise then data}
    <Graph {data} />
{/await}

<style>
:global(body) {
    margin: 0;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}
</style>

src / graphスベルト


最後に、主なコンポーネント:
<script>
import * as d3 from "d3"

export let data

let xScale = d3.scaleTime()
    .domain(d3.extent(data, d => d.date))
    .range([0, 600])

let yScale = d3.scaleLinear()
  .domain(d3.extent(data, d => d.tank))
  .range([400, 0])

let pathData = d3.line()
  .x(d => xScale(d.date))
  .y(d => yScale(d.tank))
  (data)

let xAxis, yAxis

$: {
  d3.select(xAxis).selectAll("*").remove()
  d3.select(xAxis).call(d3.axisBottom(xScale))
}
$: {
  d3.select(yAxis).selectAll("*").remove()
  d3.select(yAxis).call(d3.axisLeft(yScale))
}
</script>

<h1>Russian Tank Losses</h1>
<svg>
  <g class="graph">
    <path d={pathData}/>
  </g>
  <g class="x-axis" bind:this={xAxis}></g>
  <g class="y-axis" bind:this={yAxis}></g>
</svg>

<style>
svg {
  height: 600px;
  width: 800px;
}
.graph {
  transform: translate(100px, 100px);
}
path {
  fill: none;
  stroke: red;
  stroke-width: 1.5;
}
.x-axis {
  transform: translate(100px, 500px);
}
.y-axis {
  transform: translate(100px, 100px);
}
</style>
ここにはたくさんのことがあります.
  • 私たちはasyncのものに対処する必要はありません、我々が得るdataとして、我々はすでにきちんと準備されています、そして、我々がする必要があるすべてはそれを
  • 我々は前と同じようにスケールを作成し、ここではsvelte特定の
  • はありません
  • 線グラフは、SvelteパートからD 3部分をきれいに分離します.d3.line().x(d => xScale(d.date)).y(d => yScale(d.tank))で関数を構築し、(data)と呼びます.そして、このデータを<path d={pathData}/>に渡します
  • 私たちはすべての静的な視覚属性をCSS
  • で扱うことができます
    各軸は多くのSVG要素であるので、D 3は若干のDOMアクセスをここで必要とします.Svelteはこれでかなり柔軟ですが、この混乱を<Axis position="bottom" scale={xScale} x=100 y=500 />のような別のコンポーネントに動かす方が良いかもしれません

    今までの話


    All the code is on GitHub .
    私は、githubページ(you can see it here)でこれを配備しました.

    今度来る


    次のエピソードでは、我々はアプリにいくつかの機能を追加します.最後のゴールはロシアが戦車から逃れるまでどれくらいの時間を見つけようとすることです、しかし、それはエピソードより長くかかるかもしれません.