You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

deck.gl数据使用求助:API/JSON/CSV无效仅数组数据可用

Fixing deck.gl ScatterplotLayer Data Loading Issues

Hey there! Let’s break down why your ScatterplotLayer isn’t playing nice with API URLs, local JSON/CSV files, and how to get it running smoothly.

Why Your Current Setup Isn’t Working

Let’s start with the core reasons:

  • URL data requires specific formatting + handling: While deck.gl does support passing URLs directly to data, it expects the response to be a GeoJSON FeatureCollection by default. The envirocar API returns an array of measurement objects, not a FeatureCollection—so your getPosition: d => d.features.geometry.coordinates is looking for data that doesn’t exist in the API response. Also, cross-origin (CORS) restrictions might block browser requests to external APIs during local development.
  • Local files need proper pathing + parsing: Local JSON files might be in the wrong location (React has specific rules for asset paths) or not structured correctly for your getPosition accessor. CSV files aren’t automatically parsed by deck.gl—you need to convert them to JSON first.
  • Feature arrays work because they match deck.gl’s expectations: When you pass a pre-formatted Feature array, deck.gl can immediately read the coordinate data via your accessor, hence it works.

Step-by-Step Solutions

1. Fix API Data Loading

The easiest fix is to manually fetch and process the API data to match what your layer expects:

Option A: Manual Fetch + Data Transformation

Update your component to fetch the data explicitly, adjust its structure, and pass it to the layer:

import React, { Component } from 'react';
import { render } from 'react-dom';
import { StaticMap } from 'react-map-gl';
import DeckGL from '@deck.gl/react';
import { ScatterplotLayer } from '@deck.gl/layers';

const MAPBOX_TOKEN = process.env.MapboxAccessToken;
const INITIAL_VIEW_STATE = {
  longitude: 6.4847174678758375,
  latitude: 51.22546715521443,
  zoom: 11,
  maxZoom: 16,
  pitch: 0,
  bearing: 0
};

export default class App extends Component {
  state = {
    measurements: []
  };

  componentDidMount() {
    // Fetch data from the API
    fetch('https://envirocar.org/api/stable/measurements')
      .then(response => {
        if (!response.ok) throw new Error('Failed to load data');
        return response.json();
      })
      .then(rawData => {
        // Store the raw data (we can access coordinates directly from each item)
        this.setState({ measurements: rawData });
      })
      .catch(err => console.error('Data load error:', err));
  }

  _renderLayers() {
    return [
      new ScatterplotLayer({
        id: 'scatter-plot',
        data: this.state.measurements,
        radiusScale: 10,
        radiusMinPixels: 0.25,
        // Correct the position accessor to match the API's structure
        getPosition: d => d.geometry.coordinates,
        getFillColor: [255, 0, 255],
      })
    ];
  }

  render() {
    const mapStyle = 'mapbox://styles/mapbox/light-v9';
    return (
      <DeckGL layers={this._renderLayers()} initialViewState={INITIAL_VIEW_STATE} controller={true}>
        <StaticMap reuseMaps mapStyle={mapStyle} preventStyleDiffing={true} mapboxApiAccessToken={MAPBOX_TOKEN} />
      </DeckGL>
    );
  }
}

export function renderToDOM(container) {
  render(<App />, container);
}

Option B: Fix CORS Issues

If you see a CORS error in your browser console, set up a proxy in your React project:

  • Add this line to your package.json:
    "proxy": "https://envirocar.org"
    
  • Change your fetch URL to /api/stable/measurements—this routes the request through your local dev server, bypassing CORS restrictions.

2. Use Local JSON Files Correctly

If you’re using a local JSON file with the same structure as the API response:

  • Option 1: Place the file in the public folder and fetch it like this:
    componentDidMount() {
      fetch('/data_file.json')
        .then(res => res.json())
        .then(data => this.setState({ measurements: data }));
    }
    
  • Option 2: Import the file directly (if it’s in your src folder):
    import measurements from './data_file.json';
    
    // Then use it directly in your layer:
    data: measurements,
    

3. Handle CSV Files

deck.gl doesn’t parse CSV automatically—use a library like papaparse to convert it to JSON:

  1. Install the library:
    npm install papaparse
    
  2. Update your component to load and parse the CSV:
    import Papa from 'papaparse';
    
    componentDidMount() {
      fetch('../data_file.csv')
        .then(res => res.text())
        .then(csvText => {
          const parsedData = Papa.parse(csvText, { header: true }).data;
          // Convert CSV columns to deck.gl-compatible positions (adjust column names as needed)
          const processedData = parsedData.map(item => ({
            geometry: {
              coordinates: [parseFloat(item.longitude), parseFloat(item.latitude)]
            }
          }));
          this.setState({ measurements: processedData });
        });
    }
    

Quick Check to Avoid Future Issues

  • Always verify the structure of your data: Open the API URL in your browser or inspect your local file to confirm where the coordinates are stored—this ensures your getPosition accessor points to the right path.
  • If you prefer functional components, you can rewrite this using useState and useEffect for cleaner code:
    export default function App() {
      const [measurements, setMeasurements] = useState([]);
    
      useEffect(() => {
        fetch('/api/stable/measurements')
          .then(res => res.json())
          .then(data => setMeasurements(data))
          .catch(err => console.error(err));
      }, []);
    
      const layers = [
        new ScatterplotLayer({
          id: 'scatter-plot',
          data: measurements,
          radiusScale: 10,
          radiusMinPixels: 0.25,
          getPosition: d => d.geometry.coordinates,
          getFillColor: [255, 0, 255],
        })
      ];
    
      return (
        <DeckGL layers={layers} initialViewState={INITIAL_VIEW_STATE} controller={true}>
          <StaticMap reuseMaps mapStyle={'mapbox://styles/mapbox/light-v9'} preventStyleDiffing={true} mapboxApiAccessToken={MAPBOX_TOKEN} />
        </DeckGL>
      );
    }
    

内容的提问来源于stack exchange,提问作者Prateek kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 22:17:40