タイトル : 駅別乗降人員の推移 MAP表示 その2 乗降人員を丸の大きさで表示
更新日 : 2024-04-29
カテゴリ : プログラミング
タグ :
opendata   
leaflet   
nextjs   

駅別乗降人員の推移 相模原市オープンデータ TOPページ

乗降人員を丸の大きさで表示してみましょう

MAP

  • 町田は乗降人数が別格ですね
  • JR相模線の少なさが際立つ(本数からして少ないけど)
  • 橋本、相模大野の次は、淵野辺が多い
  • 東林間は多くない
"use client"
import { Typography, Stack } from "@mui/material";
import dynamic from "next/dynamic";
import { useEffect , useMemo, useState} from "react";
import { Point } from "leaflet";

import { getCsvData } from "@/lib/csvdata"
import { MapProps, MapCircleProps } from "@/components/mapWithCircle";

function MapPage(props: MapProps) {
  const MapWithCircle = useMemo(
    () =>
      dynamic(() => import("../components/mapWithCircle"), {
        loading: () => <p>A map is loading</p>,
        ssr: false,
      }),
    []
  );
  return <MapWithCircle center={props.center} datas={props.datas}/>;
}

export default function Home() {

  const [csvDatas, setCsvData] = useState([]);

  const center : Point = new Point(35.555994, 139.419189)
  
  const getData = async () => {
    const csvRawData = await getCsvData()
    
    const datas:MapCircleProps[] = []
    csvRawData.map((dataR:any) => {
      const r =  dataR["2022年度"] / 50
      console.log(r)
      const mcp : MapCircleProps = 
        {
          center:new Point(dataR["lat"], dataR["lon"]),
          radius: r
        }
      datas.push(
        mcp
      )
    })

    setCsvData(datas as never[])
  }

  useEffect(() => {
    getData()
  }, []);

  return (
    <Stack padding={2} spacing={1}>
      <Typography color={"secondary"}>駅の位置 leafletでMAP表示</Typography>
      <Stack width={800}>
        <MapPage center={center} datas={csvDatas}></MapPage>
      </Stack>
    </Stack>
  );
}

MAPを表示するコンポーネント

"use client"
import { MapContainer, TileLayer, Circle } from "react-leaflet";
import "leaflet/dist/leaflet.css";
import { Point } from "leaflet";

export type MapCircleProps = {
  center: Point
  radius: number
};

export type MapProps = {
  center: Point
  datas: MapCircleProps[]
};

const MapWithCircle: React.FC<MapProps> = (props) => {
  return (
    <MapContainer
      center={[props.center.x, props.center.y]}
      zoom={12}
      scrollWheelZoom={false}
      style={{ height: "80vh", width: "100%" }}
    >
      <TileLayer
        attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
      {
        props.datas.map((data) =>{
          return (
            <Circle center={[data.center.x, data.center.y]} radius={data.radius} 
              pathOptions={{ color: 'blue' , fill: true, fillColor:'blue', fillOpacity:0.1}}/>
          )
        })
      }
    </MapContainer>
  );
};

export default MapWithCircle;

CSVの読み込み

"use server"
import * as fs from 'fs';
import { parse } from 'csv-parse/sync';

export const getCsvData = async () => {
    const fileData = fs.readFileSync('src/assets/csv/shtrain_utf8.csv');
    const csvdata = await parse(fileData, { columns: true });
    return csvdata
}