I'm trying to create a blank map in a Django app (via a JS script) to fill in some data. I'm not looking for anything more than a div with statelines drawn.
This tutorial attempts to do exactly that with d3. Unfortunately, it appears that the local file reference to a json file here is outdated and no longer works.
All things considered, I gave it a shot with the modular -m flag from tghe command line. My code for loading the basemap and json file looks like this (the json file is stashed in the saem directory as the html that calls this)
/*
Functions for graphing Terra data on basemap
Uses d3 library
*/
async function init() {
let data = [0, 1, 2, 3, 4]
// Set some specifications for the basemap
let basemap_width = 960
let basemap_height = 500
// Build d3 projection
// Scale in size to fit entire US
let projection = d3.geo.albersUsa()
.translate([basemap_width/2, basemap_height/2])
.scale([1000]);
// Define path generator
let path = d3.geo.path()
.projection(projection)
// Define scale and legend for basemap
let color = d3.scale.linear()
.range(["rgb(213,222,217)","rgb(69,173,168)","rgb(84,36,55)","rgb(217,91,67)"]);
let legendText = ["Some range of values"];
// Create SVG element and append map to the SVG
let svg = d3.select("body")
.append("svg")
.attr("width", basemap_width)
.attr("height", basemap_height);
// Append Div for tooltip to SVG
let div = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// Load GeoJSON data into basemap
d3.json("../us-states.json", function(json) { // I've tried this without the .. in the relative path as well
// Loop through each state data value in the .csv file
for (var i = 0; i < data.length; i ) {
// Find the corresponding state inside the GeoJSON
for (var j = 0; j < json.features.length; j ) {
var jsonState = json.features[j].properties.name;
if (dataState == jsonState) {
// Copy the data value into the JSON
json.features[j].properties.visited = dataValue;
// Stop looking through the JSON
break;
}
}
}
// Bind the data to the SVG and create one path per GeoJSON feature
svg.selectAll("path")
.data(json.features)
.enter()
.append("path")
.attr("d", path)
.style("stroke", "#fff")
.style("stroke-width", "1")
//.style("fill", function(d) {
// Some code to fill in color
//});
});
}
init();
What's the simplest way to accomplish this so I can start rtrying to load in my data?
CodePudding user response:
The code fails to work because the url path is incorrect. You are stating the location of file like a file in local hard drive. ../
is not a valid url path for async request.
d3.json("../us-states.json", () => { /* ... */})
d3.json()
is just an asynchronous data fetcher. Internally, d3.json
is a stupidly simple wrapper. Looking at the code, it is not outdated at all. Even the D3 team does not say it is outdated.
// https://github.com/d3/d3-fetch/blob/main/src/json.js
function responseJson(response) {
if (!response.ok) throw new Error(response.status " " response.statusText);
if (response.status === 204 || response.status === 205) return;
return response.json();
}
export default function(input, init) {
return fetch(input, init).then(responseJson);
}
Solution
Check how the local json file is served over url path. It can't be a relative directory(folder). Javascript and your web browser does not know the file location of javascript that is running. It only knows the absolute root of given domain.
"../file.json" --> wrong❌
"/resources/file.json" --> correct✅ the absolute root(/) of current domain is understood.
"https://example.com/resources/file.json" --> correct✅ full url was given.
before running the code, try check if the file is correctly served by accessing them from browser or try download it via shell.
$ curl https://example.com/resources/file.json
CodePudding user response:
I have checked your question regarding below code.
/*
Functions for graphing Terra data on basemap
Uses d3 library
*/
async function init() {
let data = [0, 1, 2, 3, 4]
// Set some specifications for the basemap
let basemap_width = 960
let basemap_height = 500
// Build d3 projection
// Scale in size to fit entire US
let projection = d3.geo.albersUsa()
.translate([basemap_width/2, basemap_height/2])
.scale([1000]);
// Define path generator
let path = d3.geo.path()
.projection(projection)
// Define scale and legend for basemap
let color = d3.scale.linear()
.range(["rgb(213,222,217)","rgb(69,173,168)","rgb(84,36,55)","rgb(217,91,67)"]);
let legendText = ["Some range of values"];
// Create SVG element and append map to the SVG
let svg = d3.select("body")
.append("svg")
.attr("width", basemap_width)
.attr("height", basemap_height);
// Append Div for tooltip to SVG
let div = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// Load GeoJSON data into basemap
d3.json("../us-states.json", function(json) { // I've tried this without the .. in the relative path as well
// Loop through each state data value in the .csv file
for (var i = 0; i < data.length; i ) {
// Find the corresponding state inside the GeoJSON
for (var j = 0; j < json.features.length; j ) {
var jsonState = json.features[j].properties.name;
if (dataState == jsonState) {
// Copy the data value into the JSON
json.features[j].properties.visited = dataValue;
// Stop looking through the JSON
break;
}
}
}
// Bind the data to the SVG and create one path per GeoJSON feature
svg.selectAll("path")
.data(json.features)
.enter()
.append("path")
.attr("d", path)
.style("stroke", "#fff")
.style("stroke-width", "1")
//.style("fill", function(d) {
// Some code to fill in color
//});
});
}
init();