TanStack
Catalog

Surface wind polar scatter

polar

104 lines · 2 files · 2.9 kB

cases/107-polar-scatter/example.tsx85 lines · entry
cases/107-polar-scatter/example.tsx
import { Chart } from '@tanstack/charts/react/tooltip'
import { tooltip as exampleTooltip } from '@tanstack/charts/tooltip'

import { defineChart } from '@tanstack/charts'
import { angleGrid, polar, radialDot, radialGrid } from '@tanstack/charts/polar'
import { scaleLinear } from 'd3-scale'
import { windDirection, windLatitudeBand, windSpeed } from './transform'

const angleDomain = [0, 360] as const
const radiusDomain = [0, 13] as const
const angleGridValues = [0, 45, 90, 135, 180, 225, 270, 315] as const
const radiusGridValues = [3, 6, 9, 12] as const
const dotColor = '#e11d48'
const gridColor = '#94a3b8'

export const createExampleChart = (input: ChartOptions) => {
  const rows = windLatitudeBand(input.revision)

  return defineChart(
    {
      marks: [
        polar({
          radiusRatio: 0.72,
          scales: {
            angle: { scale: scaleLinear().domain(angleDomain) },
            radius: { scale: scaleLinear().domain(radiusDomain) },
          },

          guides: [
            radialGrid({
              values: radiusGridValues,
              labels: false,
              stroke: gridColor,
              strokeOpacity: 0.35,
            }),
            angleGrid({
              values: angleGridValues,
              labels: false,
              stroke: gridColor,
              strokeOpacity: 0.35,
            }),
          ],
          marks: [
            radialDot(rows, {
              angle: windDirection,
              radius: windSpeed,
              r: 4.5,
              fill: dotColor,
              stroke: '#ffffff',
              strokeWidth: 1,
            }),
          ],
        }),
      ],
      scales: {
        x: null,
        y: null,
      },
      margin: 0,
    },
    {
      keyboard: true,
      tooltip: {
        use: exampleTooltip,
        ...{
          format: ({ datum }) =>
            `${datum.latitude}°N, ${datum.longitude}°E · ${windSpeed(datum).toFixed(1)} m/s`,
        },
      },
    },
  )
}
export interface ChartOptions {
  revision: number
}

export const exampleAriaLabel = 'Surface wind polar scatter'

export const chart = createExampleChart({
  revision: 0,
})

export default function Example() {
  return <Chart ariaLabel={exampleAriaLabel} definition={chart} height={480} />
}
cases/107-polar-scatter/transform.ts19 lines · dependency
cases/107-polar-scatter/transform.ts
import { wind } from '@tanstack/charts-data/wind'
import type { WindRow } from '@tanstack/charts-data/wind'

const selectableLatitudeBands = [48.125, 55.125] as const

export function windLatitudeBand(revision = 0): readonly WindRow[] {
  const latitude =
    selectableLatitudeBands[revision % selectableLatitudeBands.length] ??
    selectableLatitudeBands[0]
  return wind.filter((row) => row.latitude === latitude)
}

export function windDirection(row: WindRow): number {
  return (Math.atan2(row.v, row.u) * (180 / Math.PI) + 360) % 360
}

export function windSpeed(row: WindRow): number {
  return Math.hypot(row.u, row.v)
}