오픈 소스 모험: 에피소드 32: D3 및 Svelte를 사용한 더 나은 러시아 탱크 손실 그래프

14951 단어 svelted3javascript
러시아인의 탱크가 바닥날 때 질문에 대답하기 전에 코드를 약간 리팩토링하고 개선해 봅시다.

우리는 다음을 달성하고자 합니다.
  • 별도의 구성 요소에 어색한 축 코드 넣기
  • 탱크 축을 약간 확장하여 어림수
  • 로 끝납니다.
  • 날짜 축의 눈금을 변경하여 2월 24일에 시작하도록 합니다
  • .
  • 전체 데이터에 대한 추세선 추가
  • 그래프 주변의 데드 스페이스 감소

  • src/Axis.svelte



    이 구성 요소는 어떤 논리도 수행하지 않고 D3 DOM 조작을 Svelte와 연결하기만 하므로 기본 구성 요소에 덜 어색한 코드가 있습니다.

    <script>
    import * as d3 from "d3"
    export let axis
    
    let axisNode
    
    $: {
      d3.select(axisNode).selectAll("*").remove()
      d3.select(axisNode).call(axis)
    }
    </script>
    
    <g bind:this={axisNode}></g>
    


    Y 스케일의 반올림된 숫자



    이를 위해 특별한 코드가 필요하지 않습니다. D3에는 이미 양쪽의 도메인을 가장 가까운 어림수로 채우는 편리한.nice() 기능이 포함되어 있기 때문입니다. 0은 이미 둥글기 때문에 상단에 약간만 채워집니다. 이 경우에는 700입니다.

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


    X 스케일의 날짜 형식



    이것은 좀 더 복잡합니다. 규모는 양호하며 추가 날짜로 채우고 싶지 않습니다. 2월 24일에 시작하여 데이터가 있는 마지막 날에 종료됩니다.

    우리는 수동으로 D3에게 틱을 배치할 위치(with .ticks(d3.timeThursday) - 2월 24일은 목요일)와 형식 지정 방법(with .tickFormat(d3.timeFormat("%d %b")) )으로 해결할 수 있습니다.

    오늘은 자체 진드기가 없기 때문에 완벽하지는 않지만 지금은 가능합니다.

    let xAxis = d3.axisBottom()
      .scale(xScale)
      .ticks(d3.timeThursday)
      .tickFormat(d3.timeFormat("%b %d"))
    


    추세선



    여기에 멋진 것은 없습니다. 점선으로 첫 번째 데이터 포인트와 마지막 데이터 포인트를 연결하십시오.

    let trendPathData = d3.line()
      .x(d => xScale(d.date))
      .y(d => yScale(d.tank))
      ([data[0], data.at(-1)])
    


    src/Graph.svelte



    그리고 여기에 완전한 src/Graph.svelte가 있습니다. 다른 모든 파일은 이전 에피소드에서 변경되지 않았습니다.

    <script>
    import * as d3 from "d3"
    import Axis from "./Axis.svelte"
    
    export let data
    
    let xScale = d3.scaleTime()
      .domain(d3.extent(data, d => d.date))
      .range([0, 700])
    
    let yScale = d3.scaleLinear()
      .domain(d3.extent(data, d => d.tank))
      .nice()
      .range([500, 0])
    
    let pathData = d3.line()
      .x(d => xScale(d.date))
      .y(d => yScale(d.tank))
      (data)
    
    let trendPathData = d3.line()
      .x(d => xScale(d.date))
      .y(d => yScale(d.tank))
      ([data[0], data.at(-1)])
    
    let xAxis = d3.axisBottom()
      .scale(xScale)
      .ticks(d3.timeThursday)
      .tickFormat(d3.timeFormat("%b %d"))
    let yAxis = d3
      .axisLeft()
      .scale(yScale)
    </script>
    
    <h1>Russian Tank Losses</h1>
    <svg>
      <g class="graph"><path d={pathData}/></g>
      <g class="trendline"><path d={trendPathData}/></g>
      <g class="x-axis"><Axis axis={xAxis}/></g>
      <g class="y-axis"><Axis axis={yAxis}/></g>
    </svg>
    
    <style>
    svg {
      height: 600px;
      width: 800px;
    }
    .graph {
      transform: translate(50px, 20px);
    }
    .graph path {
      fill: none;
      stroke: red;
      stroke-width: 1.5;
    }
    .trendline {
      transform: translate(50px, 20px);
    }
    .trendline path {
      fill: none;
      stroke: red;
      stroke-width: 1.5;
      stroke-dasharray: 3px;
    }
    .x-axis {
      transform: translate(50px, 520px);
    }
    .y-axis {
      transform: translate(50px, 20px);
    }
    </style>
    


    지금까지의 이야기



    All the code is on GitHub .

    저는 이것을 GitHub Pagesyou can see it here에 배포했습니다.

    다음에 온다



    다음 에피소드에서는 앱에 몇 가지 기능을 추가하겠습니다. 최종 목표는 러시아가 탱크가 바닥날 때까지 얼마나 걸릴지 알아내는 것이지만, 에피소드보다 오래 걸릴 수 있습니다.

    좋은 웹페이지 즐겨찾기