Public
Edited
Feb 7, 2024
Insert cell
# Nora's base map - UD Spring 2024
Insert cell
d3 = require("d3@6")
Insert cell
chart = {
const width = 860,
height = 800;
const svg = d3.create("svg")
.attr("viewBox", [50, 50, width-100, height-100]);

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

var p = svg.selectAll("polyline")
.data(yinyang)
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('class','iconTest')
.attr('points', function(d){return d})
.attr('transform', 'translate(200,200)')
//.attr('transform', 'scale(1)') //not working right now
.style('stroke','orangered')
.style('stroke-width','1')
.style('stroke-opacity','.1')
.style('fill','orangered')
.style('fill-opacity','.15')


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 path5 = d3.geoPath().projection(projection);


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




svg
.append("text")
.attr('x','260')
.attr('y','145')
.style('font-family','julee')
.style('font-size','60px')
// .style('font-weight','bold')//use 'fill' to change font color
.attr('fill','saddlebrown')
.attr('text-anchor','middle ')
.text('JAPAN TRIP')

svg
.append("text")
.attr('x','280')
.attr('y','175')
.style('font-family','julee')
.style('font-size','24px')
.style('font-weight','light')//use 'fill' to change font color
.attr('fill','peru')
.attr('text-anchor','middle ')
.text('Art, Culture, & Food Tour')

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

g.selectAll("path3") //d3 geopath
.data(outline.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", "ivory")
.style("fill-opacity", ".9")
.style('stroke-opacity','.8')
.style("stroke-width", '.6')
.style("stroke", "sienna")

g.selectAll("path2") //d3 geopath
.data(jpRoads.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", path2) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "none")
.style('stroke-opacity','.35')
.style("stroke-width", '.1')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path1") //d3 geopath
.data(jpRail.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", path2) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "none")
.style('stroke-opacity','.5')
.style("stroke-width", '.5')
.style("stroke", "orange")


p.enter().append("polyline")
.data(icon_test)
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('class','iconTest')
.attr('points', function(d){return d})
.attr('transform', 'translate(125,200)')
//.attr('transform', 'scale(1)') //not working right now
.style('stroke-opacity','.9')
.style("stroke-width", '.3')
.style("stroke", "peru")
.style('fill','peru')
.style('fill-opacity','.8')


/* p.enter().append("polyline") //d3 geopath
.data(icon_list)
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('class','iconTest')
.attr('points',function(d){return d.pts})
.attr('transform',function(d){return 'translate('+projection([d.data.Long,d.data.Lat])[0]+','+projection([d.data.Long,d.data.Lat])[1]+')'})
//.attr('transform', 'scale(1,0.5)') //not working right now
.style('stroke-opacity','.9')
.style("stroke-width", '.3')
.style("stroke", "peru")
.style('fill',fillColor)
.style('fill-opacity','.8')

*/
p.enter().append("polyline")
.data(icon_list)
.enter() //there are more data than elements, this selects them
.append("polyline")
.attr('class','icon')
.attr('points',function(d){return d.pts})
.attr('transform',function(d){return 'translate('+projection([d.data.Long,d.data.Lat])[0]+','+projection([d.data.Long,d.data.Lat])[1]+')'})
.style('stroke-opacity','.9')
.style("stroke-width", '.1')
.style("stroke", "peru")
.style('fill',fillColor)
.style('fill-opacity','.9')
.on('mouseover',spotsInfo)
.on('mouseout',spotsInfoOut)
function fillColor(d,i){

var color = 'peru'
if(d.data.Rated==5){color = 'orangered'
console.log("match")}
if(d.data.Rated==4){color = 'tomato'}
if(d.data.Rated==3){color = 'coral'}
if(d.data.Rated==2){color = 'salmon'}
if(d.data.Rated==1){color = 'lightsalmon'}

return color
}


var c = svg.selectAll("circle") //d3 geopath
/* .data(spots)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('class','spotsPts')
.attr("cx", function(d) {return projection([d.Long,d.Lat])[0]})
.attr("cy", function(d) {return projection([d.Long,d.Lat])[1]})
.attr('r',3.5)
.style('stroke-opacity','1')
.style("stroke-width", '.5')
.style("stroke", "rgb(0,0,0)")
.style('fill','peru')
.style('fill-opacity','.5')
*/



function spotsInfo(event,d){
d3.select(this).style('fill','brown')


svg.append('line')
.attr('class','spotLine')
.attr('x1','650')
.attr('y1','635')
.attr('x2','650')
.attr('y2',projection([d.data.Long,d.data.Lat])[1])
.attr('stroke-width','1')
.style('stroke-opacity','.5')
.attr('stroke','brown')
.attr('stroke-dasharray','2 2 4 2')

svg.append('line')
.attr('class','spotLine')
.attr('x1',projection([d.data.Long,d.data.Lat])[0])
.attr('y1',projection([d.data.Long,d.data.Lat])[1])
.attr('x2','650')
.attr('y2',projection([d.data.Long,d.data.Lat])[1])
.attr('stroke-width','1')
.style('stroke-opacity','.5')
.attr('stroke','brown')
.attr('stroke-dasharray','2 2 4 2')

svg.append("rect")
.attr("class","dRect")
.attr("x","550")
.attr("y","635")
.attr("rx","5")
.attr("ry","5")
.attr("height","55")
.attr("width","175")
.style("fill","white")
.style('fill-opacity','1')
.style("stroke-width","1")
.style("stroke","brown")
.style('stroke-opacity','.5')
svg
.append("text")
.attr('class','spotsDes')
.attr('x','710')
.attr('y','698')
.style('font-family','julee')
.style('font-size','8px')
.style('font-weight','light')//use 'fill' to change font color
.attr('fill','peru')
.attr('text-anchor','left')
.text('Info')
svg
.append('text')
.attr('class','spotsText')
.attr('x','650')
.attr('y','650')
.style('font-family','julee')
.attr('font-size','.75em')
.attr('fill','brown')
.attr('text-anchor','middle ')
.style('font-weight','bold')
.text(d.data.Name)

var wrap = svg.selectAll('text.spotsText')
.each(function(d,i) {wrap_text(d3.select(this),150)})

svg
.append('text')
.attr('class','spotsDes')
.attr('x','650')
.attr('y','660')
.attr('font-family','century gothic')
.attr('font-size','.45em')
.attr('fill','saddlebrown')
.attr('text-anchor','middle ')
.text(d.data.Description)

var wrap = svg.selectAll('text.spotsDes')
.each(function(d,i) {wrap_text(d3.select(this),150)})

svg
.append('text')
.attr('class','spotsRate')
.attr('x','570')
.attr('y','670')
.attr('font-family','julee')
.attr('font-size','1.2em')
.attr('fill','saddlebrown')
.style('fill-opacity','.4')
.attr('text-anchor','middle ')
.text(d.data.Rating)

var ratingList = []
if(d.data.Rated==1){ratingList = [shrine]}
if(d.data.Rated==2){ratingList = [shrine,shrine]}
if(d.data.Rated==3){ratingList = [shrine,shrine,shrine]}
if(d.data.Rated==4){ratingList = [shrine,shrine,shrine,shrine]}
if(d.data.Rated==5){ratingList = [shrine,shrine,shrine,shrine,shrine]}

p.enter().append("polyline")
.data(ratingList)
.enter() //there are more data than elements, this selects them
.append("polyline")
.attr('class','icon_rating')
.attr('points',function(d){return d})
.attr('transform',function(d,i){return 'translate('+(180+(i*25))+',205)'})
.style('stroke-opacity','.9')
.style("stroke-width", '.05')
.style("stroke", "saddlebrown")
.style('fill','saddlebrown')
.style('fill-opacity','.8')


}

function spotsInfoOut(event,d){
d3.selectAll('polyline.icon').style('fill',fillColor)
d3.selectAll('text.spotsText').remove()
d3.selectAll('text.spotsDes').remove()
d3.selectAll('text.spotsRate').remove()
d3.selectAll('rect.dRect').remove()
d3.selectAll('line.spotLine').remove()
d3.selectAll('polyline.icon_rating').remove()
}

return svg.node();
}
Insert cell
lantern1 = FileAttachment("lantern1@2.txt").tsv({array:true})
Insert cell
icon_list = {

///create empty list
var list = []

///loop through google sheets list
for (let i = 0; i < spots.length; i++) {
//function to add item to a list
list.push({data:spots[i],pts:lantern1})
}
//add icon points to each google sheet item
////addd combined data to empty list


//return new list
return list
}
Insert cell
jpBboxSm = FileAttachment("JP bbox sm.geojson").json()
Insert cell
icon_test = FileAttachment("lantern2@1.txt").tsv({array:true})
Insert cell
yinyang = FileAttachment("yinyang_lg@1.txt").tsv({array:true})
Insert cell
shrine = FileAttachment("shrine5@1.txt").tsv({array:true})
Insert cell
jpRail = FileAttachment("jp rail.geojson").json()
Insert cell
jpRoads = FileAttachment("jp roads.geojson").json()
Insert cell
outline = FileAttachment("jp coastline 2.geojson").json()
Insert cell
subSts = FileAttachment("sub_stops.geojson").json()
Insert cell
bldgs = FileAttachment("bldgs.geojson").json()
Insert cell
bbox = FileAttachment("site_boundary.geojson").json()
Insert cell
subLns = FileAttachment("subway_lines.geojson").json()
Insert cell
jpBbox = FileAttachment("JP bbox.geojson").json()
Insert cell
Insert cell
spots = d3.csv(spots_link,d3.autoType)
Insert cell
import { wrap_text, wrap_text_nchar } from "@ben-tanen/svg-text-and-tspan-word-wrapping"
Insert cell
Insert cell
Insert cell
GFontToDataURI(
// "https://fonts.googleapis.com/css2?family=Julee&display=swap"
"https://fonts.googleapis.com/css2?family=Julee&display=swap"
)
.then((cssRules) => {
let fontRules = cssRules.join("\n");
svg
.append("defs")
.append("style")
.attr("type", "text/css")
.text(fontRules);
console.log("Added Font");
})
.catch((reason) => console.log(reason));
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
test_dash = FileAttachment("test_dash@1.txt").tsv({array:true})
Insert cell
border1 = FileAttachment("dashboard-border1.txt").tsv({array:true})
Insert cell
dashboardGraphics = {

const width = 1060,
height = 1000;
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);

var p = svg.selectAll("polyline")
.data(border1)
.enter()
.append("polyline")
.attr('points',function(d){return d})
.attr('transform', 'translate(2,1)')
.attr('fill','grey')
.style('fill-opacity','.15')

p.enter().append("polyline")
.data(border1)
.enter()
.append("polyline")
.attr('points',function(d){return d})
.attr('fill','white')
.style('fill-opacity','1')

p.enter().append("polyline")
.data(border1)
.enter()
.append("polyline")
.attr('points',function(d){return d})
.attr('fill','orangered')
.style('fill-opacity','.1')
.style('stroke-opacity','.5')
.style("stroke-width", '.3')
.style('stroke','peru')


return svg.node();
}
Insert cell
dashboard =

html`
<div class='dashboardOuter' style='height:1000px;width:1060px'>


<div class='dashboardGraphics' style='position:absolute;width:1060px;top:0px;left:0px'>
${dashboardGraphics}
</div>

<div class='dashboardGraphics' style='position:absolute;width:860px;top:40px;left:110px'>
${chart}
</div>

<div class='text' style='position:absolute;top:790px;left:350px;font-family:helvetica;font-size:18px'>
${viewof gm}
${viewof sd}
${viewof is}
</div>
<div class='text' style='position:absolute;top:775px;left:290px;color:peru;font-family:julee;font-size:16px'>
${md`Art`}
</div>

<div class='text' style='position:absolute;top:800px;left:290px;color:peru;font-family:julee;font-size:16px'>
${md`Culture`}
</div>

<div class='text' style='position:absolute;top:824px;left:290px;color:peru;font-family:julee;font-size:16px'>
${md`Food`}
</div>

<div class='text' style='position:absolute;top:855px;left:290px;color:saddlebrown;font-family:century gothic;font-size:18px'>
${md`Anticipated Enjoyment: **${calculatedValues[0]}**`}
</div>

<div class='text' style='position:absolute;top:880px;left:290px;color:saddlebrown;font-family:century gothic;font-size:18px'>
${md`Anticipated Cost: **${calculatedValues[1]}**`}
</div>

<div class='shrineIcon' style='position:absolute;width:200px;top:760px;left:740px'>
${drawTotoro}
</div>

</div>


`
Insert cell
drawTotoro = {
var icon = ' '
if(calculatedValues[0]>10 && calculatedValues[1]<200){icon = totoroIcon}


return icon
}
Insert cell
viewof gm = Inputs.radio(["0", "1", "2"],)
Insert cell
viewof sd = Inputs.radio(["0", "1", "2"],)
Insert cell
viewof is = Inputs.radio(["0", "1", "2"],)
Insert cell
spotsDataset = [
{name:'gm',rating:4,cost:15},
{name:'sd',rating:3,cost:10},
{name:'is',rating:2,cost:20}
]
Insert cell
calculatedValues = {

var totalRating = 0
var totalCost = 0

totalRating = totalRating+spotsDataset[0].rating*gm
totalRating = totalRating+spotsDataset[1].rating*sd
totalRating = totalRating+spotsDataset[2].rating*is

totalCost = totalCost+spotsDataset[0].cost*gm
totalCost = totalCost+spotsDataset[1].cost*sd
totalCost = totalCost+spotsDataset[2].cost*is

return [totalRating,totalCost]
}
Insert cell
calculatedValues[0]
Insert cell
totoroIcon = {

const width = 100,
height = 100;
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);

var p = svg.selectAll("polyline")
.data(totoro)
.enter() //there are more data than elements, this selects them
.append("polyline")
.attr('points',function(d){return d})
.style('fill','saddlebrown')
//.style('stroke','black')
//.style('stroke-width','3')

return svg.node();
}
Insert cell
shrine_icon = FileAttachment("shrine_icon.txt").tsv({array:true})
Insert cell
totoro = FileAttachment("totoro.txt").tsv({array:true})
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