Public
Edited
Apr 23, 2023
Insert cell
# Material Map
Insert cell
d3 = require("d3@6")
Insert cell
scSteps = ["Full Supply Chain","Concrete", "Glass", "Steel", "Aluminum", "Onyx","Marble"]
Insert cell
chart = {
const width = 960,
height = 900;
const svg = d3.create("svg")
.attr("viewBox", [25, 25, width-100, height-250]);

// Use Mercator projection
var projection = d3
.geoMercator()
.fitSize([width - 150, height - 150], worldboundary);

var path1 = d3.geoPath().projection(projection);
var path2 = d3.geoPath().projection(projection);
var path3 = d3.geoPath().projection(projection);
var path4 = d3.geoPath().projection(projection);

var g = svg.append("g").attr("id", "paths");

g.selectAll("path3") //d3 geopath
.data(customGeo.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("path") //appends path to data
.attr('class','outlines')
.attr("d", path3) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "black")
.style("fill-opacity", "1")
.style('stroke-opacity','0.15')
.style("stroke-width", '1')
.style("stroke", "white")

//material_factories
var cir = svg.selectAll("circle") //d3 geopath
.data(material_factories) //get data to define path
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('class','material_factories')
.attr("r", "3") //The d attribute defines a path to be drawn, only applies to appended elements
.attr("cx", function(d) {return projection([d.Long,d.Lat])[0]})
.attr("cy", function(d) {return projection([d.Long,d.Lat])[1]})
.style("fill", fillColor)
.style("fill-opacity", "1")
.style('stroke-opacity','1')
.style("stroke-width", '.5')
.style("stroke", "rgb(0,0,0)")

function fillColor(d,i){

var color = "rgb(0,0,0)"
if(d.Type=="Distributor"){color = "blue"}
if(d.Type=="Concrete"){color = "blue"}
if(d.Type=="Glass"){color = " blue"}
if(d.Type=="Steel"){color = "blue"}
if(d.Type=="Aluminum"){color = "blue"}
if(d.Type=="Marble"){color = "blue"}
if(d.Type=="Onyx"){color = "blue"}
return color
}
//jobsite
cir.enter().append("circle") //d3 geopath
.data(jobsite) //get data to define path
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
//.attr('class','outlines')
.attr("r", "5") //The d attribute defines a path to be drawn, only applies to appended elements
.attr("cx", function(d) {return projection([d.Long,d.Lat])[0]})
.attr("cy", function(d) {return projection([d.Long,d.Lat])[1]})
.style("fill", "cyan")
.style("fill-opacity", "1")
.style('stroke-opacity','1')
.style("stroke-width", '.5')
.style("stroke", "rgb(0,0,0)")


var tx = svg.selectAll("text") //d3 geopath
.data(scSteps) //get data to define path
.enter() //there are more data than elements, this selects them
.append("text") //appends path to data
.attr("x", "65")
.attr("y", function(d,i) {return 491+(i*20)})
.style("font-family", "Helvetica")
.style("font-weight", "light")
.style("text-anchor", "start")
.style("font-size", "10px")
.style("fill", "black")
.style("fill-opacity", "1")
.text(function(d) {return d})
cir.enter().append("circle") //d3 geopath
.data(scSteps) //get data to define path
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
//attr('class','extra1')
.attr("r", "6") //The d attribute defines a path to be drawn, only applies to appended elements
.attr("cx", "55")
.attr("cy", function(d,i) {return 487+(i*20)})
.style("fill", "white")
.style("fill-opacity", "1")
.style('stroke-opacity','1')
.style("stroke-width", '1')
.style("stroke", "black")
.on("mouseover", animateMap)
.on("mouseout", stopAnimateMap)

var xPush = 0
//horizontal
cir.enter().append("circle") //d3 geopath
.data(extra) //get data to define path
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('class','extra1')
.attr("r", "6") //The d attribute defines a path to be drawn, only applies to appended elements
.attr("cy", "610")
.attr("cx", function(d,i) {return 380+(i*30)})
.style("fill", "white")
.style("fill-opacity", "1")
.style('stroke-opacity','1')
.style("stroke-width", '1')
.style("stroke", "black")
.on("mouseover", animateMap)
.on("mouseout", stopAnimateMap)


function radSize(d,i){
var rad = 3
rad = d.Quantity/500000

if(rad<3){rad = 3}
return rad
}

function xSpacing(d,i){
//var xPush = 0
if(i>0){
xPush = xPush + (extra[i-1].Quantity/500000)
xPush = xPush+(20)

}
console.log(xPush)
return xPush + 380
}


function animateMap(event,d){

var tColor = "cyan"

if(d == "Concrete"){
tColor = "blue"
var p = svg.selectAll("polyline") //d3 geopath
.data(stone) //get data to define path
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('points', function(d){return d})
.attr('class','mouseIcon')
.style("fill", "none")
.style("fill-opacity", "0.5")
.style('stroke-opacity','1')
.style("stroke-width", '0.50')
.style("stroke", "blue")
.style("stroke-dasharray", "2,2")

p.enter().append("polyline") //d3 geopath
.data(stonetransport) //get data to define path
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('points', function(d){return d})
.attr('class','mouseIcon')
.style("fill", "blue")
.style("fill-opacity", "1")
.style('stroke-opacity','1')
.style("stroke-width", '0.1')
.style("stroke", "none")

svg.selectAll("circle.extra1").attr('r',changeR12)
svg.selectAll("circle.extra1").style('fill-opacity',changeFill)
}

function changeFill(d,i){
var fll = "white"
if(d.Name == "Concrete2"){fll="1"}
return fll
}
function changeR12(d,i){
var r = "6"
if(d.Name == "Concrete2"){r=16}
return r
}

function changeR13(d,i){
var r = "6"
if(d.Name == "Marble2"){r=13}
return r
}
function changeR14(d,i){
var r = "6"
if(d.Name == "Glass2"){r=9}
return r
}

function changeR15(d,i){
var r = "6"
if(d.Name == "Steel2"){r=11}
return r
}


function changeR16(d,i){
var r = "6"
if(d.Name == "Aluminum2"){r=9}
return r
}

function changeR17(d,i){
var r = "6"
if(d.Name == "Onyx2"){r=9}
return r
}
function changeRAll(d,i){
var r = "6"
if(d.Name == "Marble2"){r=13}
if(d.Name == "Concrete2"){r=16}
if(d.Name == "Glass2"){r=9}
if(d.Name == "Steel2"){r=11}
if(d.Name == "Aluminum2"){r=9}
if(d.Name == "Onyx2"){r=9}
return r
}

if(d == "Marble"){
tColor = "blue"

svg.selectAll("circle.extra1").attr('r',changeR13)
var p = svg.selectAll("polyline") //d3 geopath
.data(marblepath) //get data to define path
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('points', function(d){return d})
.attr('class','mouseIcon')
.style("fill", "none")
.style("fill-opacity", "0.5")
.style('stroke-opacity','1')
.style("stroke-width", '0.5')
.style("stroke", "blue")
.style("stroke-dasharray", "2,2")

p.enter().append("polyline") //d3 geopath
.data(marbletransport) //get data to define path
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('points', function(d){return d})
.attr('class','mouseIcon')
.style("fill", "blue")
.style("fill-opacity", "1")
.style('stroke-opacity','1')
.style("stroke-width", '0.1')
.style("stroke", "none")

svg.selectAll("circle.material_factories").attr('r',changeR2)
svg.selectAll("circle.extra1").style('fill-opacity',changeFill)

function changeFill(d,i){
var fll = "white"
if(d.Name == "Marble2"){fll="1"}
return fll
}
}
if(d == "Glass"){
tColor = "blue"
svg.selectAll("circle.extra1").attr('r',changeR14)
var p = svg.selectAll("polyline") //d3 geopath
.data(glasspath) //get data to define path
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('points', function(d){return d})
.attr('class','mouseIcon')
.style("fill", "none")
.style("fill-opacity", "0.5")
.style('stroke-opacity','1')
.style("stroke-width", '0.5')
.style("stroke", "blue")
.style("stroke-dasharray", "2,2")
p.enter().append("polyline") //d3 geopath
.data(glasstransport) //get data to define path
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('points', function(d){return d})
.attr('class','mouseIcon')
.style("fill", "blue")
.style("fill-opacity", "1")
.style('stroke-opacity','1')
.style("stroke-width", '0.1')
.style("stroke", "none")

svg.selectAll("circle.material_factories").attr('r',changeR3)
svg.selectAll("circle.extra1").style('fill-opacity',changeFill)

function changeFill(d,i){
var fll = "white"
if(d.Name == "Glass2"){fll="1"}
return fll
}
}

if(d == "Steel"){
tColor = "blue"
svg.selectAll("circle.extra1").attr('r',changeR15)

var p = svg.selectAll("polyline") //d3 geopath
.data(steelpath) //get data to define path
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('points', function(d){return d})
.attr('class','mouseIcon')
.style("fill", "none")
.style("fill-opacity", "0.5")
.style('stroke-opacity','1')
.style("stroke-width", '0.5')
.style("stroke", "blue")
.style("stroke-dasharray", "2,2")

p.enter().append("polyline") //d3 geopath
.data(steeltransport) //get data to define path
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('points', function(d){return d})
.attr('class','mouseIcon')
.style("fill", "blue")
.style("fill-opacity", "1")
.style('stroke-opacity','1')
.style("stroke-width", '0.1')
.style("stroke", "none")

svg.selectAll("circle.material_factories").attr('r',changeR4)
svg.selectAll("circle.extra1").style('fill-opacity',changeFill)

function changeFill(d,i){
var fll = "white"
if(d.Name == "Steel2"){fll="1"}
return fll
}
}

if(d == "Aluminum"){
tColor = "blue"
svg.selectAll("circle.extra1").attr('r',changeR16)
var p = svg.selectAll("polyline") //d3 geopath
.data(aluminumpath) //get data to define path
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('points', function(d){return d})
.attr('class','mouseIcon')
.style("fill", "none")
.style("fill-opacity", "0.5")
.style('stroke-opacity','1')
.style("stroke-width", '0.5')
.style("stroke", "blue")
.style("stroke-dasharray", "2,2")

p.enter().append("polyline") //d3 geopath
.data(aluminumtransport) //get data to define path
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('points', function(d){return d})
.attr('class','mouseIcon')
.style("fill", "blue")
.style("fill-opacity", "1")
.style('stroke-opacity','1')
.style("stroke-width", '0.1')
.style("stroke", "none")

svg.selectAll("circle.material_factories").attr('r',changeR5)
svg.selectAll("circle.extra1").style('fill-opacity',changeFill)
function changeFill(d,i){
var fll = "white"
if(d.Name == "Aluminum2"){fll="1"}
return fll
}
}


if(d == "Onyx"){
tColor = "blue"
svg.selectAll("circle.extra1").attr('r',changeR17)
var p = svg.selectAll("polyline") //d3 geopath
.data(onyxpath) //get data to define path
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('points', function(d){return d})
.attr('class','mouseIcon')
.style("fill", "none")
.style("fill-opacity", "0.5")
.style('stroke-opacity','1')
.style("stroke-width", '0.5')
.style("stroke", "blue")
.style("stroke-dasharray", "2,2")

p.enter().append("polyline") //d3 geopath
.data(onyxtransport) //get data to define path
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('points', function(d){return d})
.attr('class','mouseIcon')
.style("fill", "blue")
.style("fill-opacity", "1")
.style('stroke-opacity','1')
.style("stroke-width", '0.1')
.style("stroke", "none")

svg.selectAll("circle.material_factories").attr('r',changeR6)
svg.selectAll("circle.extra1").style('fill-opacity',changeFill)

function changeFill(d,i){
var fll = "white"
if(d.Name == "Onyx2"){fll="1"}
return fll
}
}

if(d == "Full Supply Chain"){
tColor = "blue"

var p = svg.selectAll("polyline") //d3 geopath
.data(fullpath) //get data to define path
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('points', function(d){return d})
.attr('class','mouseIcon')
.style("fill", "none")
.style("fill-opacity", "0.5")
.style('stroke-opacity','1')
.style("stroke-width", '0.5')
.style("stroke", "blue")
.style("stroke-dasharray", "2,2")

p.enter().append("polyline") //d3 geopath
.data(fulltransport) //get data to define path
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('points', function(d){return d})
.attr('class','mouseIcon')
.style("fill", "blue")
.style("fill-opacity", "1")
.style('stroke-opacity','1')
.style("stroke-width", '0.1')
.style("stroke", "none")

svg.selectAll("circle.material_factories" , "circle.extra").attr('r',changeR7)
svg.selectAll("circle.extra1").style('fill-opacity',changeFill)
svg.selectAll("circle.extra1").attr('r', changeRAll)
function changeFill(d,i){
var fll = "white"
if("circle.extra1"){fll="1"}
return fll
}
}

}

function changeR(d,i){
var rad = "3"
if(d.Type=="Concrete"){rad = "5"}
return rad}
function changeR2(d,i){
var rad = "3"
if(d.Type=="Marble"){rad = "5"}
return rad}

function changeR3(d,i){
var rad = "3"
if(d.Type=="Glass"){rad = "5"}
return rad}
function changeR4(d,i){
var rad = "3"
if(d.Type=="Steel"){rad = "5"}
return rad}

function changeR5(d,i){
var rad = "3"
if(d.Type=="Aluminum"){rad = "5"}
return rad}

function changeR6(d,i){
var rad = "3"
if(d.Type=="Onyx"){rad = "5"}
return rad}

function changeR7(d,i){
var rad = "3"
if(d){rad = "5"}
return rad}

function stopAnimateMap(event,d){
svg.selectAll("text.mouseText").remove()
svg.selectAll("polyline.mouseIcon").remove()
svg.selectAll("circle.material_factories").attr('r','3')
svg.selectAll("circle.extra1").style("fill", "blue")
svg.selectAll("circle.extra1").style("fill-opacity", ".01")
svg.selectAll("circle.extra1").attr('r','6')
}





return svg.node();
}

Insert cell
fullpath = FileAttachment("fullpath.txt").tsv({array:true})
Insert cell
fulltransport = FileAttachment("fulltransport.txt").tsv({array:true})
Insert cell
onyxtransport = FileAttachment("onyxtransport.txt").tsv({array:true})
Insert cell
onyxpath = FileAttachment("onyxpath.txt").tsv({array:true})
Insert cell
aluminumpath = FileAttachment("aluminumpath.txt").tsv({array:true})
Insert cell
aluminumtransport = FileAttachment("aluminumtransport.txt").tsv({array:true})
Insert cell
steelpath = FileAttachment("steelpath@1.txt").tsv({array:true})
Insert cell
steeltransport = FileAttachment("steeltransport.txt").tsv({array:true})
Insert cell
glasspath = FileAttachment("GLASSPATH@1.txt").tsv({array:true})
Insert cell
glasstransport = FileAttachment("glasstransport@1.txt").tsv({array:true})
Insert cell
marblepath = FileAttachment("marblepath.txt").tsv({array:true})
Insert cell
marbletransport = FileAttachment("marbletransport.txt").tsv({array:true})
Insert cell
stone = FileAttachment("stonepath@4.txt").tsv({array:true})
Insert cell
customGeo = FileAttachment("custom.geo.json").json()
Insert cell
worldboundary = FileAttachment("WB_Adm0_boundary_lines_10m_lowres.geojson").json()
Insert cell
Insert cell
material_factories = d3.csv(mapLink,d3.autoType())
Insert cell
Insert cell
jobsite = d3.csv(jobsiteLink,d3.autoType())
Insert cell
stonetransport = FileAttachment("stonetransport@2.txt").tsv({array:true})
Insert cell
Insert cell
extra = d3.csv(extraLink,d3.autoType())
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