Public
Edited
Feb 22, 2023
Insert cell
# Portland Map Feb.20 Sample Graphics and Layout
Insert cell
portlandBoundary = FileAttachment("Portland Boundary.geojson").json()
Insert cell
sideWater = FileAttachment("side water.geojson").json()
Insert cell
water = FileAttachment("water@1.geojson").json()
Insert cell
d3 = require("d3@6")
Insert cell
mutable Loadcount = 0; //if 0, load welcome,will be made 1 when start button is pressed
Insert cell
mutable ProfileSelect = 0; //if 0, load profile select screen, made the value of the profile chosen

Insert cell
mutable ClueSolveState = 1 //if 1, clue1 screen shown and continue button sets to 101. if 101, show map with clue 1 active. Correct choice sets value to 2. if 2, clue2 screen is shown, etc
Insert cell
mutable Lose = 0; //lose screen Back to Start button will reset all values
Insert cell


chart = {
const width = 700,
height = 600;
const svg = d3.create("svg")
.attr("viewBox", [50, 50, width-120, height-100]);


/*
var Loadcount = 0; //if 0, load welcome,will be made 1 when start button is pressed
var ProfileSelect = 0; //if 0, load profile select screen, made the value of the profile chosen
var ClueSolveState = 1; //if 1, will present clue 1. Will be made 101 when clicking continue button. Will be made 2 when correct location is selected. if 2, will show clue 2 and be made 102 when clicking continue button, etc.

var Lose = 0; //lose screen Back to Start button will reset all values




//Start Lose Screen

if (Lose==1) {


}

//End Lose Screen



//Start Main Screen
else if (Loadcount == 0) {

svg.append('image')
.attr('href',jamesTurk)
.attr('class','spotImage')
.attr('x', '500')
.attr('y','90')
.attr('width', 17)
.attr('height', 40)
// .on('mouseover', spotProfile1)
// .on('mouseout', removespotProfile)

svg.append('text')
.attr('class','spots')
.attr('x', '550')
.attr('y','730')
.attr('font-family','Helvetica')
.attr('font-size', '.7em')
.attr('text.anchor','start')
.attr('font-weight', 'bold')
.text('Welcome')

svg.append('text')
.attr('class','spots')
.attr('x', '550')
.attr('y','750')
.attr('font-family','Helvetica')
.attr('font-size', '.65em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text('Basic Info')
}

//End Main Screen




//Start Profile Select
else if (ProfileSelect == 0) {


}

//End Profile Select


//Start Clue 1
else if (ClueSolveState == 1) {


}
//End Clue 1


//START Main Chart

else if (ClueSolveState == 101,201,301,401) {
*/


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

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

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

g.selectAll("path2") //d3 geopath
.data(streets.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", '.2')
.style("stroke", "rgb(0,0,0)")

g.selectAll("path2") //d3 geopath
.data(highwaylines.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','1')
.style("stroke-width", '2')
.style("stroke", "palevioletred")

g.selectAll("path3") //d3 geopath
.data(portlandBoundary.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", "floralwhite")
.style("fill-opacity", '.2')
.style('stroke-opacity','.6')
.style("stroke-width", '1')
.style("stroke", "rgb(119,94,148)")

g.selectAll("path3") //d3 geopath
.data(parks.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", "mediumvioletred")
.style("fill-opacity", ".5")
.style('stroke-opacity','1')
.style("stroke-width", '.6')
.style("stroke", "lightslategrey")

g.selectAll("path3") //d3 geopath
.data(water.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", "teal")
.style("fill-opacity", ".5")
.style('stroke-opacity','1')
.style("stroke-width", '1')
.style("stroke", "lightslategrey")

g.selectAll("path3") //d3 geopath
.data(sideWater.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", "slategrey")
.style("fill-opacity", ".05")
.style('stroke-opacity','.1')
.style("stroke-width", '.1')
.style("stroke", "black")

g.selectAll("path2") //d3 geopath
.data(ferryline.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','1')
.style("stroke-width", '2')
.style("stroke", "blueviolet")
.style('stroke-dasharray','2 2')



var c = svg.selectAll("circle") //d3 geopath
.data(locs)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr("cx", function(d) {return projection([d.longitude, d.latitude])[0]})
.attr("cy", function(d) {return projection([d.longitude, d.latitude])[1]})
.attr('r',4)
.attr('fill',colorType)
.style('fill-opacity','2')
.style('stroke','darkviolet')
.style('stroke-width','1')
.on('mouseover', spotText)
.on('mouseout', removespotText)

function colorType(d,i){
var color = 'gold'
if(d.type=='morgue'){color = 'gold'}
if(d.type=='house'){color = 'gold'}
if(d.type=='house'){color = 'gold'}
if(d.type=='house'){color = 'gold'}
if(d.type=='saloon'){color = 'gold'}
if(d.type=='scow'){color = 'gold'}
return color

}
function spotText(event,d){
d3.select(this).attr('fill','mediumslateblue')
.attr('r', 6)
.style('stroke', 'mediumslateblue')
.style("stroke-opacity",'.5')
.style("stroke-width", '5')
svg.append('text')
.attr('class','spots')
.attr('x', '550')
.attr('y','530')
.attr('font-family','Helvetica')
.attr('font-size', '.7em')
.attr('text.anchor','start')
.attr('font-weight', 'bold')
.text(d.name)

svg.append('text')
.attr('class','spots')
.attr('x', '550')
.attr('y','550')
.attr('font-family','Helvetica')
.attr('font-size', '.65em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text(d.description)

svg.append('line')
.attr('class','spotLine')
.attr('x1', '550')
.attr('y1', '538')
.attr('x2', projection([d.longitude, d.latitude])[0])
.attr('y2', '538')
.style('stroke-width','.5')
.style('stroke','black')
.style('stroke-dasharray','2 2')
svg.append('line')
.attr('class','spotLine')
.attr('x1', projection([d.longitude, d.latitude])[0])
.attr('y1', '538')
.attr('x2', projection([d.longitude, d.latitude])[0])
.attr('y2', projection([d.longitude, d.latitude])[1])
.style('stroke-width','.7')
.style('stroke','darkblue')
.style('stroke-dasharray','2 2')
}
function removespotText(event,d){
d3.select(this).attr('fill',colorType)
d3.select(this).attr('r', 4)
d3.select(this).style('stroke-opacity','.65')
d3.select(this).style('stroke-width', '1')
d3.selectAll('text.spots').remove()
d3.selectAll('line.spotLine').remove()
}







/*
svg.append("rect")
.attr("x", 497)
.attr("y", 97)
.attr("width", 85)
.attr("height", 27)
.attr('fill', 'white')
.style('fill-opacity','.5')
.style('stroke', 'teal')
.style('stroke-width', '1.5')
*/

svg.append('image')
.attr('href',jamesTurk)
.attr('class','spotImage')
.attr('x', '545')
.attr('y','50')
.attr('width', 17)
.attr('height', 40)
.on('mouseover', spotProfile1)
.on('mouseout', removespotProfile)

svg.append('image')
.attr('href',bridgetGrant)
.attr('class','spotImage')
.attr('x', '565')
.attr('y','50')
.attr('width', 17)
.attr('height', 40)
.on('mouseover', spotProfile2)
.on('mouseout', removespotProfile)

svg.append('image')
.attr('href',larrySullivan)
.attr('class','spotImage')
.attr('x', '585')
.attr('y','50')
.attr('width', 17)
.attr('height', 40)
.on('mouseover', spotProfile3)
.on('mouseout', removespotProfile)

svg.append('image')
.attr('href',buncoKelly)
.attr('class','spotImage')
.attr('x', '605')
.attr('y','50')
.attr('width', 17)
.attr('height', 40)
.on('mouseover', spotProfile)
.on('mouseout', removespotProfile)

svg.append('image')
.attr('href',name4)
.attr('class','spotImage')
.attr('x', '525')
.attr('y','50')
.attr('width', 17)
.attr('height', 40)
.on('mouseover', spotProfile4)
.on('mouseout', removespotProfile)

svg.append('image')
.attr('href',name5)
.attr('class','spotImage')
.attr('x', '505')
.attr('y','50')
.attr('width', 17)
.attr('height', 40)
.on('mouseover', spotProfile5)
.on('mouseout', removespotProfile)

svg.append('image')
.attr('href',name6)
.attr('class','spotImage')
.attr('x', '485')
.attr('y','50')
.attr('width', 17)
.attr('height', 40)
.on('mouseover', spotProfile6)
.on('mouseout', removespotProfile)




function spotProfile(i,d){
d3.select(this).attr('fill','lavenderblush')

svg.append("rect")
.attr('class','whitebox')
.attr("x", 320)
.attr("y", 90)
.attr("height", 154)
.attr("width", 300)
.attr('stroke','gold')
.attr("stroke-width", '2')
.attr('stroke-opacity', '1')
.style("fill", 'white');

svg.append('image')
.attr('href',joeBuncoKelly)
.attr('class','spotProfile')
.attr('x', '320')
.attr('y','93')
.attr('width', 300)
.attr('height', 150)
}



function spotProfile1(i,d){
d3.select(this).attr('fill','lavenderblush')

svg.append("rect")
.attr('class','whitebox')
.attr("x", 320)
.attr("y", 90)
.attr("height", 154)
.attr("width", 300)
.attr('stroke','gold')
.attr("stroke-width", '2')
.attr('stroke-opacity', '1')
.style("fill", 'white');

svg.append('image')
.attr('href',jamesTurkProfile)
.attr('class','spotProfile1')
.attr('x', '320')
.attr('y','93')
.attr('width', 295)
.attr('height', 145)
}
/*
function removespotProfile1(event,d){
d3.select(this).attr('fill',colorType)
d3.selectAll('image.spotProfile1').remove()
d3.selectAll('rect.whitebox').remove()
}
*/
function spotProfile2(event,d){
d3.select(this).attr('fill','lavenderblush')

svg.append("rect")
.attr('class','whitebox')
.attr("x", 320)
.attr("y", 90)
.attr("height", 154)
.attr("width", 300)
.attr('stroke','gold')
.attr("stroke-width", '2')
.attr('stroke-opacity', '1')
.style("fill", 'white');

svg.append('image')
.attr('href',grantProfile)
.attr('class','spotProfile2')
.attr('x', '320')
.attr('y','93')
.attr('width', 295)
.attr('height', 145)
}
/*
function removespotProfile2(event,d){
d3.select(this).attr('fill',colorType)
d3.selectAll('image.spotProfile2').remove()
d3.selectAll('rect.whitebox').remove()
}
*/
function spotProfile3(event,d){
d3.select(this).attr('fill','lavenderblush')

svg.append("rect")
.attr('class','whitebox')
.attr("x", 320)
.attr("y", 90)
.attr("height", 154)
.attr("width", 300)
.attr('stroke','gold')
.attr("stroke-width", '2')
.attr('stroke-opacity', '1')
.style("fill", 'white');

svg.append('image')
.attr('href',larryProfile)
.attr('class','spotProfile3')
.attr('x', '320')
.attr('y','93')
.attr('width', 295)
.attr('height', 145)
}
/*
function removespotProfile3(event,d){
d3.select(this).attr('fill',colorType)
d3.selectAll('image.spotProfile3').remove()
d3.selectAll('rect.whitebox').remove()
}
*/


function spotProfile4(event,d){
d3.select(this).attr('fill','lavenderblush')

svg.append("rect")
.attr('class','whitebox')
.attr("x", 320)
.attr("y", 90)
.attr("height", 154)
.attr("width", 300)
.attr('stroke','gold')
.attr("stroke-width", '2')
.attr('stroke-opacity', '1')
.style("fill", 'white');

svg.append('image')
.attr('href',profile4)
.attr('class','spotProfile4')
.attr('x', '320')
.attr('y','93')
.attr('width', 295)
.attr('height', 145)
}

function spotProfile5(event,d){
d3.select(this).attr('fill','lavenderblush')

svg.append("rect")
.attr('class','whitebox')
.attr("x", 320)
.attr("y", 90)
.attr("height", 154)
.attr("width", 300)
.attr('stroke','gold')
.attr("stroke-width", '2')
.attr('stroke-opacity', '1')
.style("fill", 'white');

svg.append('image')
.attr('href',profile5)
.attr('class','spotProfile5')
.attr('x', '320')
.attr('y','93')
.attr('width', 295)
.attr('height', 145)
}

function spotProfile6(event,d){
d3.select(this).attr('fill','lavenderblush')

svg.append("rect")
.attr('class','whitebox')
.attr("x", 320)
.attr("y", 90)
.attr("height", 154)
.attr("width", 300)
.attr('stroke','gold')
.attr("stroke-width", '2')
.attr('stroke-opacity', '1')
.style("fill", 'white');

svg.append('image')
.attr('href',profile6)
.attr('class','spotProfile6')
.attr('x', '320')
.attr('y','93')
.attr('width', 295)
.attr('height', 145)
}

function removespotProfile(i,d){

d3.selectAll('image.spotProfile').remove()
d3.selectAll('image.spotProfile1').remove()
d3.selectAll('image.spotProfile2').remove()
d3.selectAll('image.spotProfile3').remove()
d3.selectAll('image.spotProfile4').remove()
d3.selectAll('image.spotProfile5').remove()
d3.selectAll('image.spotProfile6').remove()
d3.selectAll('rect.whitebox').remove()
}

setInterval(myTimer, 1800);

function myTimer() {
const d = new Date();
document.getElementById("demo").innerHTML = d.toLocaleTimeString();
svg.append('timer')
.attr('class','myTimer')
.attr('x', '450')
.attr('y','100')
}



svg.append('svg')
.attr('href',smallmap)
.attr('class','spotImage')
.attr('x', '110')
.attr('y','210')
.attr('width', 100)

if (ProfileSelect == 1){
svg.append('image')
.attr('href', playerProfile1)
.attr('class','spotImage')
.attr('x', '60')
.attr('y','60')
.attr('width', 40)
}

else if (ProfileSelect == 2){
svg.append('image')
.attr('href', playerProfile2)
.attr('class','spotImage')
.attr('x', '60')
.attr('y','60')
.attr('width', 40)
}

else {
svg.append('image')
.attr('href', playerProfile3)
.attr('class','spotImage')
.attr('x', '60')
.attr('y','60')
.attr('width', 40)
}

return svg.node();



//END Main Chart











}

Insert cell
startpage = {
const width = 700,
height = 600;
const svg = d3.create("svg")
.attr("viewBox", [50, 50, width-120, height-100]);

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

svg.append('text')
.attr('class','spots')
.attr('x', '340')
.attr('y','210')
.attr('font-family','Helvetica')
.attr('font-size', '3em')
.attr('text.anchor','middle')
.attr('font-weight', 'bold')
.text('Welcome')

svg.append('text')
.attr('class','spots')
.attr('x', '160')
.attr('y','250')
.attr('font-family','Helvetica')
.attr('font-size', '.65em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text(' Basic Info')


svg.append('image')
.attr('href',infopanel)
.attr('class','button')
.attr('x', '70')
.attr('y','270')
.attr('width', 220)








svg.append('image')
.attr('href',start)
.attr('class','button')
.attr('x', '340')
.attr('y','270')
.attr('width', 200)
.on('click', startgame)
function startgame(event,d){
mutable Loadcount = 1;
}


svg.append('image')
.attr('href',learnMore)
.attr('class','button')
.attr('x', '340')
.attr('y','370')
.attr('width', 200)
.on('click', Learnmore)
function Learnmore(event,d){
window.open("https://www.oregonencyclopedia.org/articles/shanghai_tunnels_myth/#.Y_XqE3bMJD8");
}

return svg.node();
}
Insert cell
losepage = {
const width = 700,
height = 600;
const svg = d3.create("svg")
.attr("viewBox", [50, 50, width-120, height-100]);

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





svg.append('image')
.attr('href',continue1)
.attr('class','button')
.attr('x', '240')
.attr('y','400')
.attr('width', 200)
.on('click', cont)
function cont(event,d){
mutable Lose = 0;
mutable Loadcount = 0;
mutable ClueSolveState = 1;
mutable ProfileSelect = 0;
}
return svg.node();
}
Insert cell
profileselectpage = {
const width = 700,
height = 600;
const svg = d3.create("svg")
.attr("viewBox", [50, 50, width-120, height-100]);

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

svg.append('text')
.attr('class','spots')
.attr('x', '180')
.attr('y','150')
.attr('font-family','Helvetica')
.attr('font-size', '2em')
.attr('text.anchor','middle')
.attr('font-weight', 'bold')
.text('Choose Your Player')

svg.append('image')
.attr('href',playerProfile1)
.attr('class','button')
.attr('x', '60')
.attr('y','200')
.attr('width', 200)
.on('click', prof1)
function prof1(event,d){
mutable ProfileSelect = 1;
}

svg.append('image')
.attr('href',playerProfile2)
.attr('class','button')
.attr('x', '240')
.attr('y','200')
.attr('width', 200)
.on('click', prof2)
function prof2(event,d){
mutable ProfileSelect = 2;
}

svg.append('image')
.attr('href',playerProfile3)
.attr('class','button')
.attr('x', '420')
.attr('y','200')
.attr('width', 200)
.on('click', prof3)
function prof3(event,d){
mutable ProfileSelect = 3;
}


return svg.node();
}
Insert cell
cluepage1 = {
const width = 700,
height = 600;
const svg = d3.create("svg")
.attr("viewBox", [50, 50, width-120, height-100]);
var g = svg.append("g").attr("id", "paths");


svg.append('image')
.attr('href',clue1)
.attr('class','button')
.attr('x', '100')
.attr('y','80')
.attr('width', 450)






svg.append('image')
.attr('href',continue1)
.attr('class','button')
.attr('x', '240')
.attr('y','400')
.attr('width', 200)
.on('click', cont)
function cont(event,d){
mutable ClueSolveState = 101
}

return svg.node();
}
Insert cell
cluepage2 = {
const width = 700,
height = 600;
const svg = d3.create("svg")
.attr("viewBox", [50, 50, width-120, height-100]);

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


svg.append('image')
.attr('href',clue2)
.attr('class','button')
.attr('x', '100')
.attr('y','80')
.attr('width', 450)






svg.append('image')
.attr('href',continue1)
.attr('class','button')
.attr('x', '240')
.attr('y','400')
.attr('width', 200)
.on('click', cont)
function cont(event,d){
mutable ClueSolveState = 102
}





return svg.node();
}
Insert cell
cluepage3 = {
const width = 700,
height = 600;
const svg = d3.create("svg")
.attr("viewBox", [50, 50, width-120, height-100]);

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



svg.append('image')
.attr('href',clue3)
.attr('class','button')
.attr('x', '100')
.attr('y','80')
.attr('width', 450)






svg.append('image')
.attr('href',continue1)
.attr('class','button')
.attr('x', '240')
.attr('y','400')
.attr('width', 200)
.on('click', cont)
function cont(event,d){
mutable ClueSolveState = 103
}





return svg.node();
}
Insert cell
cluepage4 = {

const width = 700,
height = 600;
const svg = d3.create("svg")
.attr("viewBox", [50, 50, width-120, height-100]);

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



svg.append('image')
.attr('href',clue4)
.attr('class','button')
.attr('x', '100')
.attr('y','80')
.attr('width', 450)






svg.append('image')
.attr('href',continue1)
.attr('class','button')
.attr('x', '240')
.attr('y','400')
.attr('width', 200)
.on('click', cont)
function cont(event,d){
mutable ClueSolveState
}





return svg.node();
}
Insert cell
smallmap = {
const width = 1152,
height = 768;
const svg = d4.create("svg")
.attr("viewBox", [20, 50, width-100, height-100]);

// Use Mercator projection
var projection = d4
.geoModifiedStereographicLee()
// .fitSize([width - 60, height - 50], bbox);

var path1 = d4.geoPath().projection(projection);
var path2 = d4.geoPath().projection(projection);
var path3 = d4.geoPath().projection(projection);

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

g.selectAll("path2") //d3 geopath
.data(pdcBase.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", "black")
.style("fill-opacity", '1')
.style('stroke-opacity','.5')
.style("stroke-width", '.2')
.style("stroke", "rgb(0,0,0)")

g.selectAll("path3") //d3 geopath
.data(allRoutes.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", "none")
.style('stroke-opacity','.6')
.style("stroke-width", '1')
.style("stroke", "rgb(119,94,148)")

return svg.node();
}
Insert cell
Insert cell
bool = {
var page = chart

if (Loadcount == 0) {page = startpage}
else if (Lose == 1) {page = losepage}
else if (ProfileSelect == 0) {page = profileselectpage}
else if (ClueSolveState == 1) {page = cluepage1}
else if (ClueSolveState == 2) {page = cluepage2}
else if (ClueSolveState == 3) {page = cluepage3}
else if (ClueSolveState == 4) {page = cluepage4}

return page
}
Insert cell



<head>
<style>
.whole{
/* border: 1px solid red; **old don't use** */
width:100%;
height:800px;
}
.int{
width: 700px;
height: 600px;
margin: 0 auto;
border: 1px solid black;
outline: 4px solid red;
outline-offset: 15px;
}

.title{
margin: 0 auto;
}
</style>
</head>



<!-- **USE the above css to control border lines for the map. margin is what centers it appropriately, regardless of screen resolution** -->



<body>

<div class='whole'>
<div class='title' style='height:100px;'>
${title}
</div>
<div class='int'>

<!-- **We shouldn't need this anymore I think**
<div class='dashboardOuter' style='height:800px;width:1200px'>
<div class='border' style='position:absolute;width:1160px;top:0px;left:0px'>
${border}
</div>
<div class='timer' style='position:absolute;top:8px;left:580px;font-family:Helvetica;font-size:20px;font-weight:bold'>
${md`TIMER`}
</div>
</div>
-->

<div class='map' style='position:absolute;width:700px;'>
${bool}
</div>


</div>
</div>


</body>
Insert cell
title = {
const width = 300,
height = 100;
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);


var g = svg.append("g").attr("id", "paths");
var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(portlandtittle) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline') //appends path to data
.attr('class','outlines')
.attr('points', function(d) {return d})
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1.2')
.style("stroke", "black")

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(kidnapstitle) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline') //appends path to data
.attr('class','outlines')
.attr('points', function(d) {return d})
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '.5')
.style("stroke", "black")
var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(lTitle) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline') //appends path to data
.attr('class','outlines')
.attr('points', function(d) {return d})
.style('stroke-opacity','1')
.style("stroke-width", '.5')
.style("stroke", "darkturquoise")

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(paTitle) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline') //appends path to data
.attr('class','outlines')
.attr('points', function(d) {return d})
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '.5')
.style("stroke", "orange")

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

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



return svg.node();
}
Insert cell
Insert cell
highwaylines = FileAttachment("HighwayLines.geojson").json()
Insert cell
kidnapstitle = FileAttachment("kidnapstitle.txt").tsv({array:true})
Insert cell
lTitle = FileAttachment("L title.txt").tsv({array:true})
Insert cell
onTitle = FileAttachment("ON title.txt").tsv({array:true})
Insert cell
paTitle = FileAttachment("PA title.txt").tsv({array:true})
Insert cell
rdTitle = FileAttachment("RD title.txt").tsv({array:true})
Insert cell
portlandtittle = FileAttachment("PortlandTittle@1.txt").tsv({array:true})
Insert cell
mapFrame2 = FileAttachment("Map Frame2.txt").tsv({array:true})
Insert cell
mapFrame1 = FileAttachment("Map Frame1@1.txt").tsv({array:true})
Insert cell
colorUnderlay = FileAttachment("Color underlay.txt").tsv({array:true})
Insert cell
mapFrame = FileAttachment("Map Frame.txt").tsv({array:true})
Insert cell
image = FileAttachment("image.png").url()
Insert cell
allRoutes = FileAttachment("all routes@4.geojson").json()
Insert cell
bridgetGrant = FileAttachment("Bridget Grant PNG 2.png").url()
Insert cell
buncoKelly = FileAttachment("Bunco Kelly PNG 2.png").url()
Insert cell
jamesTurk = FileAttachment("James Turk png 2.png").url()
Insert cell
larrySullivan = FileAttachment("Larry Sullivan PNG 2.png").url()
Insert cell
larryProfile = FileAttachment("Larry profile.png").url()
Insert cell
grantProfile = FileAttachment("Grant profile.png").url()
Insert cell
jamesTurkProfile = FileAttachment("James Turk profile.png").url()
Insert cell
buncoEstablishment = FileAttachment("Bunco-s establishment.PNG").url()
Insert cell
sailorBoardinghouses = FileAttachment("Sailor-s boardinghouses.PNG").url()
Insert cell
turkSailorsBoardinghouses = FileAttachment("Turk-s sailors boardinghouses.PNG").url()
Insert cell
import {skullTest} from "@mariamth/shanghai"
Insert cell
Insert cell
locs = d3.csv(locslink, d3.autoType)
Insert cell
bbox = FileAttachment("BBox@2.geojson").json()
Insert cell
streets = FileAttachment("Streets@1.geojson").json()
Insert cell
parks = FileAttachment("parks@2.geojson").json()
Insert cell
pdcBase = FileAttachment("pdc base.geojson").json()
Insert cell
ferryline = FileAttachment("Ferryline.geojson").json()
Insert cell
joeBuncoKelly = FileAttachment("Joe Bunco kelly@1.png").url()
Insert cell
import {map} with {projection, outline} from "@d3/world-map"
Insert cell
d4 = require("d3@6", "d3-geo-projection@3")
Insert cell
name4 = FileAttachment("Name 4.jpg").url()
Insert cell
name5 = FileAttachment("Name 5.jpg").url()
Insert cell
name6 = FileAttachment("Name 6.jpg").url()
Insert cell
profile4 = FileAttachment("Profile 4.jpg").url()
Insert cell
profile5 = FileAttachment("Profile 5.jpg").url()
Insert cell
profile6 = FileAttachment("Profile 6.jpg").url()
Insert cell
continue1 = FileAttachment("Continue.jpg").url()
Insert cell
learnMore = FileAttachment("Learn More.jpg").url()
Insert cell
infopanel = FileAttachment("I for panel.jpg").url()
Insert cell
playerProfile2 = FileAttachment("Player Profile 1 2.jpg").url()
Insert cell
playerProfile3 = FileAttachment("Player Profile 1 3.jpg").url()
Insert cell
playerProfile1 = FileAttachment("Player Profile 1.jpg").url()
Insert cell
start = FileAttachment("Start.jpg").url()
Insert cell
clue1 = FileAttachment("Clue 1.PNG").url()
Insert cell
clue2 = FileAttachment("Clue 2.PNG").url()
Insert cell
clue3 = FileAttachment("Clue 3.PNG").url()
Insert cell
clue4 = FileAttachment("Clue 4.PNG").url()
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