A Basic Chart – Building a Geospacial App with SvelteKit, Deck.gl, and Mapbox – Part 4

We are going to add a D3.js bar chart that will interact with our geospacial data.

The Building a Geospacial App tutorial uses a data visualization library called React-Vis. Apparently React and D3 do not work together very easily, so you will see som…


This content originally appeared on DEV Community and was authored by Samuel Earl

We are going to add a D3.js bar chart that will interact with our geospacial data.

The Building a Geospacial App tutorial uses a data visualization library called React-Vis. Apparently React and D3 do not work together very easily, so you will see some data visualization libraries that combine React and D3 to make it easier for developers to incorporate D3 into a React app. Since we are using Svelte we don't have that problem and we can use D3 (along with all of its power and customizability) directly.

Svelte and D3 work really well together. However, to optimize the relationship between Svelte and D3 it is important to understand some basic concepts about these two great pieces of software. Please read this (short) post titled Making Visualizations Literally with Svelte & D3 and then come back here.

Update the processData() function

In your index.svelte file, find the processData() function and update it to look like this:

function processData() {
  let data = taxiData.reduce(
    (accu, curr) => {
      let pickupHour = new Date(curr.pickup_datetime).getUTCHours();
      let dropoffHour = new Date(curr.dropoff_datetime).getUTCHours();

      let pickupLongitude = Number(curr.pickup_longitude);
      let pickupLatitude = Number(curr.pickup_latitude);

      if (!isNaN(pickupLongitude) && !isNaN(pickupLatitude)) {
        accu.points.push({
          position: [pickupLongitude, pickupLatitude],
          hour: pickupHour,
          pickup: true
        });
      }

      let dropoffLongitude = Number(curr.dropoff_longitude);
      let dropoffLatitude = Number(curr.dropoff_latitude);

      if (!isNaN(dropoffLongitude) && !isNaN(dropoffLatitude)) {
        accu.points.push({
          position: [dropoffLongitude, dropoffLatitude],
          hour: dropoffHour,
          pickup: false
        });
      }

      let prevPickups = accu.pickupObj[pickupHour] || 0;
      let prevDropoffs = accu.dropoffObj[dropoffHour] || 0;

      accu.pickupObj[pickupHour] = prevPickups + 1;
      accu.dropoffObj[dropoffHour] = prevDropoffs + 1;

      return accu;
    },
    {
      points: [],
      pickupObj: {},
      dropoffObj: {}
    }
  );

  data.pickups = Object.entries(data.pickupObj).map(([hour, count]) => {
    return { hour: Number(hour), x: Number(hour) + 0.5, y: count };
  });
  data.dropoffs = Object.entries(data.dropoffObj).map(([hour, count]) => {
    return { hour: Number(hour), x: Number(hour) + 0.5, y: count };
  });

  taxiDataset = data;
}

Now find the pointsArray declaration and replace this:

let pointsArray = [];

...with this:

let taxiDataset = {
  points: [],
  pickups: [],
  pickupObj: {},
  dropoffs: [],
  dropoffObj: {}
};

Now find the renderLayers reactive property:

$: renderLayers({ data: pointsArray, settings: settings });

...and update it to look like this:

$: renderLayers({ data: taxiDataset.points, settings: settings });

It looks like there is a lot going on in the processData() function. It is just formatting the taxiData into an object that is shaped like the taxiDataset object that you used to replace the pointsArray variable.

  • The points property holds the scatterplot data, which will show how the distance and time of the trips are correlated.
  • The pickupObj property holds the number of pickups by hour.
  • The pickups property holds the x and y values of the pickup bars in the bar chart.
  • The dropoffObj property holds the number of dropoffs by hour.
  • The dropoffs property holds the x and y values of the dropoff bars in the bar chart.

Create the bar chart container

Create a new file inside your /src/components directory and name it BarChart.svelte. Paste the following code inside:

<div class="bar-chart">
  <h2>Pickups by hours</h2>
</div>

<style>
  .bar-chart {
    position: absolute;
    left: 10px;
    bottom: 10px;
    z-index: 100;
    width: 500px;
    height: 210px;
    padding: 10px;
    background-color: white;
    border-radius: 3;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
    font-size: 12px;
    line-height: 1.833;
  }
</style>

Now in your index.svelte file, import that BarChart component:

import BarChart from "$/components/BarChart.svelte";

...and include it inside the <div> tag in your HTML as the last element/component in the <div> tag, like this:

<div class="deck-container">
  {#if hover.hoveredObject}
    <div class="tooltip" style:transform={`translate(${hover.x}px, ${hover.y}px)`}>
      <div>{hover.label}</div>
    </div>
  {/if}
  <MapStylePicker currentStyle={mapStyle} on:change={handleStyleChange}/>
  <LayerControls {settings} controls={CONTROLS} on:layerSettingsChange={updateLayerSettings} />
  <div id="map" bind:this={mapElement}></div>
  <canvas id="deck-canvas" bind:this={canvasElement}></canvas>
  <BarChart />
</div>

Make sure to save your files and refresh your browser, if necessary, to see the box for your bar chart.

Create the bar chart

First, we are going to create a simple bar chart of pickups by hour.

To do this, we are going to use the taxiDataset.pickups variable we prepared above. This is an array of objects of the form {hour: 0, x: 0.5, y: 246}. Each x is going to be the x-coordinate of the corresponding bar and each y is going to be y-coordinate of the corresponding bar for the pickups we want to plot.

We are going to create the bar chart by coding SVG elements, which are similar to HTML elements, directly into the HTML portion of our BarChart.svelte component.

In your BarChart.svelte file, update the HTML as follows:

TODO: Finish the rest of this tutorial.



This content originally appeared on DEV Community and was authored by Samuel Earl


Print Share Comment Cite Upload Translate Updates
APA

Samuel Earl | Sciencx (2022-07-13T21:32:43+00:00) A Basic Chart – Building a Geospacial App with SvelteKit, Deck.gl, and Mapbox – Part 4. Retrieved from https://www.scien.cx/2022/07/13/a-basic-chart-building-a-geospacial-app-with-sveltekit-deck-gl-and-mapbox-part-4/

MLA
" » A Basic Chart – Building a Geospacial App with SvelteKit, Deck.gl, and Mapbox – Part 4." Samuel Earl | Sciencx - Wednesday July 13, 2022, https://www.scien.cx/2022/07/13/a-basic-chart-building-a-geospacial-app-with-sveltekit-deck-gl-and-mapbox-part-4/
HARVARD
Samuel Earl | Sciencx Wednesday July 13, 2022 » A Basic Chart – Building a Geospacial App with SvelteKit, Deck.gl, and Mapbox – Part 4., viewed ,<https://www.scien.cx/2022/07/13/a-basic-chart-building-a-geospacial-app-with-sveltekit-deck-gl-and-mapbox-part-4/>
VANCOUVER
Samuel Earl | Sciencx - » A Basic Chart – Building a Geospacial App with SvelteKit, Deck.gl, and Mapbox – Part 4. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/07/13/a-basic-chart-building-a-geospacial-app-with-sveltekit-deck-gl-and-mapbox-part-4/
CHICAGO
" » A Basic Chart – Building a Geospacial App with SvelteKit, Deck.gl, and Mapbox – Part 4." Samuel Earl | Sciencx - Accessed . https://www.scien.cx/2022/07/13/a-basic-chart-building-a-geospacial-app-with-sveltekit-deck-gl-and-mapbox-part-4/
IEEE
" » A Basic Chart – Building a Geospacial App with SvelteKit, Deck.gl, and Mapbox – Part 4." Samuel Earl | Sciencx [Online]. Available: https://www.scien.cx/2022/07/13/a-basic-chart-building-a-geospacial-app-with-sveltekit-deck-gl-and-mapbox-part-4/. [Accessed: ]
rf:citation
» A Basic Chart – Building a Geospacial App with SvelteKit, Deck.gl, and Mapbox – Part 4 | Samuel Earl | Sciencx | https://www.scien.cx/2022/07/13/a-basic-chart-building-a-geospacial-app-with-sveltekit-deck-gl-and-mapbox-part-4/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.