Public
Edited
Oct 17, 2023
1 fork
Insert cell
Insert cell
map = {
const svg = d3.create("svg");
const fontFamily = "'Helvetica Neue', Helvetica, Arial, sans-serif";
let cities = d3.selectAll(null);

var width = 960,
height = 500,
centered;

// Define color scale
var color = d3
.scaleLinear()
.domain([1, 10])
.clamp(true)
.range(["#fff", "#409A99"]);

// Projection
var projectionFylker = d3
.geoMercator()
.fitSize([width, height], GeoJSONfylker);
var projectionKommuner = d3
.geoMercator()
.fitSize([width, height], GeoJSONkommuner);

var projection = projectionKommuner;
var path = d3.geoPath().projection(projection); // Geo path, not to be confused with d3.path

// Geo data
var featuresFylker = GeoJSONfylker.features;
var featuresKommuner = GeoJSONkommuner.features;
var features = featuresKommuner;

// Set svg width & height
svg.attr("width", width).attr("height", height);

// Add background
svg
.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height)
.on("click", clicked);

var g = svg.append("g");

var kommuneLayer = g
.append("g")
.classed("kommune-layer", true)
.style("overflow", "hidden");
var fylkeLayer = g.append("g").classed("fylker-layer", true);

var captionKommuner = g
.append("text")
.classed("big-text", true)
.attr("x", 20)
.attr("y", 45);

// Get province name
function nameFn(d) {
return d && d.properties ? d.properties.navn : null;
}

// Get province name length
function nameLength(d) {
var n = nameFn(d);
return n ? n.length : 0;
}

// Get province color
function fillFn(d) {
return color(nameLength(d));
}

// When clicked, zoom in
function clicked(d) {
var x,
y,
k,
delay = 0;

// Compute centroid of the selected path

if (d && centered !== d) {
// City
cities = kommuneLayer.selectAll("g").data([point1]).enter();

console.log("zoom in");
var centroid = path.centroid(d);
x = centroid[0];
y = centroid[1];
k = 4;
centered = d;
} else {
console.log("zoom out");
cities = kommuneLayer.selectAll("a").remove();
x = width / 2;
y = height / 2;
k = 1;
centered = null;
}

// Highlight the clicked province
kommuneLayer.selectAll("path").style("fill", function (d) {
return centered && d === centered ? "#D5708B" : fillFn(d);
});

const cit = d3.selectAll(".city-link");
cit._groups[0].length == 0 ? (delay = 750) : (delay = 0);
placeCity(d);

// Zoom
g.transition()
.duration(750)
.delay(delay)
.attr(
"transform",
"translate(" +
width / 2 +
"," +
height / 2 +
")scale(" +
k +
")translate(" +
-x +
"," +
-y +
")"
);
//placeCity(d);
}
// inprogress

function placeCity(d) {
const textAndCircle = cities
.append("a")
.attr(
"href",
(d) =>
"https://www.fjordnorway.com/en/destinations/the-stavanger-region"
)
.attr("target", "_blank")
.style("z-index", 10);

// City circle
const circle = textAndCircle.append("circle");

circle
.classed("city-link", true)
.attr("cx", (d) => {
return projection(d.geometry.coordinates)[0];
})
.attr("cy", (d) => {
return projection(d.geometry.coordinates)[1];
})
.transition()
.duration(750)
.ease(d3.easeBounce)
.attr("r", 10)
.attr("fill", "blue");

// City text
textAndCircle
.append("text")
.attr("x", (d) => {
return projection(d.geometry.coordinates)[0] + 10;
})
.attr("y", (d) => {
return projection(d.geometry.coordinates)[1];
})
.attr("dy", "0.35em")
.style("font-family", fontFamily)
.style("font-size", 10)
// .text(d => d.name)
.text((d) => "Stavanger")
.style("z-index", 9)
.style("background", "white");
}

function mouseover(d) {
// Highlight hovered province
d3.select(this).style("fill", "orange");
// Draw effects
textCaption(nameFn(d));
}

function mouseout(d) {
// Reset province color
kommuneLayer.selectAll("path").style("fill", function (d) {
return centered && d === centered ? "#D5708B" : fillFn(d);
});

// Clear province name
captionKommuner.text("");
}

function textCaption(text) {
captionKommuner.style("font-family", fontFamily).text(text);
}
// Fylke color oerlay filter
var filter = d3
.select("svg")
.append("defs")
.append("filter")
.attr("id", "my-filter")
.append("feGaussianBlur")
.attr("stdDeviation", 2);

// Update color scale domain based on data
color.domain([0, d3.max(features, nameLength)]);

// Draw each kommune as a path
kommuneLayer
.selectAll("path")
.data(features)
.enter()
.append("path")
.attr("d", path)
.attr("vector-effect", "non-scaling-stroke")
.style("fill", fillFn)
.on("mouseover", mouseover)
.on("mouseout", mouseout)
.on("click", clicked);

fylkeLayer
.selectAll("path")
.data(featuresFylker)
.enter()
.append("path")
.attr("d", path)
.attr("vector-effect", "non-scaling-stroke")
// .style("stroke", "none")
.style("fill", "none")
.attr("stroke", "#777")
//.attr("stroke-dasharray", "10,2")
.attr("stroke-linejoin", "round");

// Apply filters to fylker
// fylkeLayer.attr("filter", "url(#my-filter)");
//fylkeLayer
// .selectAll("path")
// .filter(function (d, i) {
// return i === 0;
// })
// .attr("filter", "url(#my-filter)");

return svg.node();
}
Insert cell
Insert cell
point1 = ({
type: "Feature",
geometry: {
type: "Point",
coordinates: [5.733107, 58.969975] // Stavanger
}
})
Insert cell
Insert cell
Insert cell
GeoJSONkommuner = {
// 2. Filtrerte kommuner
topojsonKommuner.features = topojsonKommuner.features.filter((komm) => {
const firstTwoDigits = komm.properties.kommunenummer
.toString()
.substr(0, 2);
return (
firstTwoDigits === "11" || // Rogaland
firstTwoDigits === "12" ||
firstTwoDigits === "14" ||
firstTwoDigits === "15" ||
firstTwoDigits === "16" ||
firstTwoDigits === "46"
);
});
// 3. Filtrerte kommuner > GeoJson
const GeoJSONkommuner = { ...topojsonKommuner };
GeoJSONkommuner.features = GeoJSONkommuner.features.map((f) =>
turf.rewind(f, { reverse: true })
);
return GeoJSONkommuner;
}
Insert cell
Insert cell
// 1) Filtrerte fylker
GeoJSONfylker = {
// norgesFylker.features = norgesFylker.features.filter((fylke) => {
// const fylkeNavn = fylke.properties.navn;
//* return (
//* fylkeNavn === "Rogaland" ||
//* fylkeNavn === "Møre og Romsdal" ||
//* fylkeNavn === "Vestland" ||
//* fylkeNavn === "Innlandet" ||
//* fylkeNavn === "Trøndelag"
// );
// });
// 2) Filtre fylker to GeoJson
const GeoJSONfylker = { ...norgesFylker };
GeoJSONfylker.features = GeoJSONfylker.features.map((f) =>
turf.rewind(f, { reverse: true })
);
return GeoJSONfylker;
}
Insert cell
Insert cell
Insert cell
Insert cell
norgesFylker = (
await fetch(
"https://raw.githubusercontent.com/robhop/fylker-og-kommuner-2020/master/Fylker-small.json"
)
).json()
Insert cell
norgesKommuner = (
await fetch(
"https://raw.githubusercontent.com/robhop/fylker-og-kommuner-2020/master/Kommuner-large.topojson"
)
).json()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more