Public
Edited
Mar 14, 2023
Insert cell
# Portland Kidnap Map March 11 Backup
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
viewof pages= Inputs.radio(['Home', 'Profile', 'First Clue','Main Game'], {step: 1, label: "", value:0})
Insert cell


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

// 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', '340')
.attr('y','320')
.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', '340')
.attr('y','330')
.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', '340')
.attr('y1', '318')
.attr('x2', projection([d.longitude, d.latitude])[0])
.attr('y2', '318')
.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', '318')
.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', '500')
.attr('y','90')
.attr('width', 17)
.attr('height', 40)
.on('mouseover', spotProfile1)
.on('mouseout', removespotProfile)

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

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

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

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

svg.append("rect")
.attr('class','whitebox')
.attr("x", 150)
.attr("y", 100)
.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', '150')
.attr('y','103')
.attr('width', 300)
.attr('height', 150)
}



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

svg.append("rect")
.attr('class','whitebox')
.attr("x", 150)
.attr("y", 100)
.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', '155')
.attr('y','103')
.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", 150)
.attr("y", 100)
.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', '155')
.attr('y','103')
.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", 150)
.attr("y", 100)
.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', '155')
.attr('y','103')
.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 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('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')
}
return svg.node();
}


Insert cell
frame = {
const width = 1200,
height = 800;
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(footstepsBorder1) //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", "teal")
.style("fill-opacity", '1')
.style('stroke-opacity','1')
.style("stroke-width", '1.5')
.style("stroke", "deeppink")

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(footstepsBorder2) //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", "teal")
.style("fill-opacity", '1')
.style('stroke-opacity','1')
.style("stroke-width", '1.5')
.style("stroke", "deeppink")

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(footstepsBorder3) //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", "teal")
.style("fill-opacity", '1')
.style('stroke-opacity','1')
.style("stroke-width", '1.5')
.style("stroke", "deeppink")

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(timerBorder) //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", '3')
.style("stroke", "deeppink")

return svg.node();
}
Insert cell
Insert cell
rectangle = {
const svg = d4.create("svg")
svg.append("rect")
.attr('class','whitebox')
.attr("height", 350)
.attr("width", 200)
.style("fill", "snow")
.attr('fill-opacity', '1')
.attr('stroke','rosybrown')
.attr("stroke-width", '2')
.attr('stroke-opacity', '1')


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

html`




<div class='dashboardOuter' style='height:800px;width:1200px'>
<div class='border' style='position:absolute;width:1160px;top:0px;left:0px'>
${border}
</div>
<div class='frame' style='position:absolute;width:1160px;top:0px;left:0px'>
${frame}
</div>

<div class='profile' style='position:absolute;top:175px;left:85px;font-family:Helvetica;font-size:12px;font-weight:bold'>
${md`The Investigator`}
</div>
<div class='map' style='position:absolute;width:685px;top:95px;left:238px'>
${chart}
</div>

<div class='map' style='position:absolute;width:200px;height:350px;top:490px;left:700px'>
${rectangle}
</div>

<div class='border' style='position:absolute;width:200px;top:500px;left:700px'>
${smallmap}
</div>

<div class='pages' style='position:absolute;width:400px;top:40px;left:40px'>
${viewof pages}
</div>
<div class='starttime Button' style='position:absolute;width:200px;top:35px;left:535px'>
${viewof startTimerButton}
</div>
<div class='time' style='position:absolute; width:200px;top:3px;left:547px'>
${time}
</div>

<div class='clue' style='position:absolute;top:205px;left:129px;font-family:Helvetica;font-size:12px;font-weight:bold;color:deeppink'>
${md`Clue #1`}
</div>
//Street Address for August Erickson's Saloon
<div class='clue' style='position:absolute;top:225px;left:85px;font-family:TimesNewRoman;font-size:12px;font- weight:bold'>
${md`“Bars, food, and shows; oh the fun you could have! Along this popular strip, now referred to as 2nd Ave.”`}
</div>

<div class='clue' style='position:absolute;top:324px;left:99px;font-family:Helvetica;font-size:12px;font-weight:bold'>
${md`Clue #2`}
</div>
//August Erickson's Saloon
<div class='clue' style='position:absolute;top:344px;left:57px;font-family:TimesNewRoman;font-size:12px;font- weight:bold'>
${md`“The owner himself may have a month for a name. Beyond these walls you’ll find many a drinking game.”`}
</div>

<div class='clue' style='position:absolute;top:450px;left:129px;font-family:Helvetica;font-size:12px;font-weight:bold'>
${md`Clue #3`}
</div>


<div class='clue' style='position:absolute;top:600px;left:98px;font-family:Helvetica;font-size:12px;font-weight:bold'>
${md`Clue #4`}
</div>


`



Insert cell
Insert cell
Insert cell
border = {
const width = 1200,
height = 800;
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(colorUnderlay) //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", "peachpuff")
.style("fill-opacity", '.4')

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(mapFrame1) //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", "rbg(87,52,11)")
.style("fill-opacity", '1')
.style('stroke-opacity','1')
.style("stroke-width", '1.5')
.style("stroke", "rosybrown")

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(mapFrame2) //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", "rbg(87,52,11)")
.style("fill-opacity", '1')
.style('stroke-opacity','1')
.style("stroke-width", '1.5')
.style("stroke", "rosybrown")

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", "teal")

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", "mediumvioletred")
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("fill", "none")
.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")

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(rectCharacter) //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")

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(targetCircle) //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", "firebrick")

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(peopleBorder) //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.5')
.style("stroke", "deeppink")

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(clueBorder) //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.5')
.style("stroke", "teal")

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(targetLine1) //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", "firebrick")

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(targetLine2) //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", "firebrick")

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(profileBorder) //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.5')
.style("stroke", "black")

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(footsteps) //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", "teal")
.style("fill-opacity", '.5')



return svg.node();
}
Insert cell
Insert cell
mutable stops = 0
Insert cell
viewof seconds = Inputs.range([0, 59], {value: 0, step:1, label: "seconds"})
Insert cell
viewof minutes = Inputs.range([0, 59], {value: 0, step:2, label: "minutes", value:2})
Insert cell
hours = 0
Insert cell
function* timer(i = 0) {
yield i;
while (true) {
yield Promises.tick(1000).then(() => i++);
}
}
Insert cell
currentTime = {
if(startTimerButton>0){
return timer();
}else{mutable stops = 0}
}
Insert cell
countdownTime = {
return minutes*60 + seconds;
}
Insert cell
//mutable timesup = 0
Insert cell
time = {
let result = countdownTime - currentTime;
if (currentTime == undefined){result = 0}
if ( result < 0 )
result = "Time Up!";
else {
const remainHours = ""+parseInt(result/3600);
result = result - remainHours*3600;
const remainMinutes = ""+parseInt(result/60);
const remainSeconds = ""+parseInt(result%60);
result = remainMinutes.padStart(2,"0") + ":" +
remainSeconds.padStart(2,"0") ;
}

return html`
<style>
.countdown{ font-size: 23px;font-family:helvetica;font-weight:600; color: teal }
</style>
<span class="countdown">${result}</span>
`
}
Insert cell
viewof startTimerButton = Inputs.button([
["Start", value => value + 1],
["Reset", value => 0]
], {value: 0})

Insert cell
Insert cell
homepage1 = {
const width = 1200,
height = 800;
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);


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

svg.append('image')
.attr('href',buncoVillain)
.attr('class','spotImage')
.attr('x', '760')
.attr('y','450')
.attr('width', 140)
.attr('height', 290)

svg.append('image')
.attr('href',turkVillain)
.attr('class','spotImage')
.attr('x', '750')
.attr('y','140')
.attr('width', 160)
.attr('height', 320)

svg.append('image')
.attr('href',KidnapNews)
.attr('class','spotImage')
.attr('x', '295')
.attr('y','220')
.attr('width', 290)
.attr('height', 430)

svg.append('image')
.attr('href',kidnapBoatpic)
.attr('class','spotImage')
.attr('x', '590')
.attr('y','453')
.attr('width', 160)
.attr('height', 310)

svg.append('image')
.attr('href',kidnapPic)
.attr('class','spotImage')
.attr('x', '623')
.attr('y','217')
.attr('width', 80)
.attr('height', 160)

svg.append('image')
.attr('href',tunnelPic)
.attr('class','spotImage')
.attr('x', '740')
.attr('y','355')
.attr('width', 140)
.attr('height', 170)
var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(homepageRect) //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", "cadetblue")
.style("fill-opacity", '1')
.attr('stroke','rosybrown')
.attr("stroke-width", '4')
.attr('stroke-opacity', '1')

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(welcomeRect) //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", "teal")
.style("fill-opacity", '1')
.attr('stroke','deeppink')
.attr("stroke-width", '2')
.attr('stroke-opacity', '1')

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(welcome) //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", "deeppink")
.style("fill-opacity", '1')
.attr('stroke','snow')
.attr("stroke-width", '2')
.attr('stroke-opacity', '1')

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(welcomeO) //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", "teal")
.style("fill-opacity", '1')
.attr('stroke','snow')
.attr("stroke-width", '2FileAttachment("image@1.png").image()')
.attr('stroke-opacity', '1')


var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(missingclue) //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", "linen")
.style("fill-opacity", '1')
.attr('stroke','black')
.attr("stroke-width", '1')
.attr('stroke-opacity', '1')


var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(questionMark2) //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("fill-opacity", '1')
.attr('stroke','black')
.attr("stroke-width", '1')
.attr('stroke-opacity', '1')

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(questionMark1) //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", "deeppink")
.style("fill-opacity", '1')
.attr('stroke','teal')
.attr("stroke-width", '1')
.attr('stroke-opacity', '1')

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(pins) //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("fill-opacity", '1')
.attr('stroke','black')
.attr("stroke-width", '1')
.attr('stroke-opacity', '1')


var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(targetX) //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", "deeppink")
.style("fill-opacity", '1')
.attr('stroke','maroon')
.attr("stroke-width", '2')
.attr('stroke-opacity', '1')

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(tape) //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", "beige")
.style("fill-opacity", '1')
.attr('stroke','black')
.attr("stroke-width", '1')
.attr('stroke-opacity', '1')


return svg.node();
}
Insert cell
buncoVillain = FileAttachment("image@1.png").url()
Insert cell
turkVillain = FileAttachment("image@2.png").url()
Insert cell
tunnelPic = FileAttachment("image@3.png").url()
Insert cell
KidnapNews = FileAttachment("image@4.png").url()
Insert cell
kidnapPic = FileAttachment("image@5.png").url()
Insert cell
kidnapBoatpic = FileAttachment("image@6.png").url()
Insert cell
targetX = FileAttachment("target X.txt").tsv({array:true})
Insert cell
pins = FileAttachment("pins.txt").tsv({array:true})
Insert cell
questionMark1 = FileAttachment("question mark 1.txt").tsv({array:true})
Insert cell
questionMark2 = FileAttachment("question mark 2.txt").tsv({array:true})
Insert cell
missingclue = FileAttachment("missingclue.txt").tsv({array:true})
Insert cell
tape = FileAttachment("Tape.txt").tsv({array:true})
Insert cell
welcomeO = FileAttachment("welcome O.txt").tsv({array:true})
Insert cell
welcomeRect = FileAttachment("Welcome Rect.txt").tsv({array:true})
Insert cell
welcome = FileAttachment("welcome.txt").tsv({array:true})
Insert cell
homepageRect = FileAttachment("Homepage rect.txt").tsv({array:true})
Insert cell
Insert cell
profilepage = {
const width = 1200,
height = 800;
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(profilePageRect) //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", "cadetblue")
.style("fill-opacity", '1')
.attr('stroke','rosybrown')
.attr("stroke-width", '4')
.attr('stroke-opacity', '1')

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(profileTextframe) //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", "teal")
.style("fill-opacity", '1')
.attr('stroke','deeppink')
.attr("stroke-width", '2')
.attr('stroke-opacity', '1')


var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(investigatorText) //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", "deeppink")
.style("fill-opacity", '1')
.attr('stroke','black')
.attr("stroke-width", '1')
.attr('stroke-opacity', '1')

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(investigatorText2) //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", "teal")
.style("fill-opacity", '1')
.attr('stroke','black')
.attr("stroke-width", '1')
.attr('stroke-opacity', '1')

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(investigatorProfile) //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", "deeppink")
.style("fill-opacity", '1')
.attr('stroke','snow')
.attr("stroke-width", '2')
.attr('stroke-opacity', '1')

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(investigatorProfile2) //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", "teal")
.style("fill-opacity", '1')
.attr('stroke','snow')
.attr("stroke-width", '2')
.attr('stroke-opacity', '1')

svg.append('text')
.attr('class','layersText')
.attr('x', '540')
.attr('y','560')
.attr('font-family','Helvetica')
.attr('font-size', '1em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.style("fill", "mistyrose")
.text('The Investigator is ')


return svg.node();
}
Insert cell
investigatorProfile2 = FileAttachment("Investigator profile 2.txt").tsv({array:true})
Insert cell
investigatorProfile = FileAttachment("Investigator profile.txt").tsv({array:true})
Insert cell
investigatorText2 = FileAttachment("Investigator text 2.txt").tsv({array:true})
Insert cell
investigatorText = FileAttachment("Investigator text.txt").tsv({array:true})
Insert cell
profilePageRect = FileAttachment("Profile page rect.txt").tsv({array:true})
Insert cell
profileTextframe2 = FileAttachment("profile textframe 2.txt").tsv({array:true})
Insert cell
profileTextframe = FileAttachment("profile textframe.txt").tsv({array:true})
Insert cell
Insert cell
intropage = {
const width = 1200,
height = 800;
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(introClueRect) //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", "cadetblue")
.style("fill-opacity", '1')
.attr('stroke','rosybrown')
.attr("stroke-width", '4')
.attr('stroke-opacity', '1')

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(profileTextframe2) //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", "teal")
.style("fill-opacity", '1')
.attr('stroke','deeppink')
.attr("stroke-width", '2')
.attr('stroke-opacity', '1')

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(investigatorTinyprofile) //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", "deeppink")
.style("fill-opacity", '.8')
.attr('stroke','teal')
.attr("stroke-width", '1')
.attr('stroke-opacity', '.5')

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(magnifyingGlass1) //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", "teal")
.style("fill-opacity", '1')
.attr('stroke','deeppink')
.attr("stroke-width", '2')
.attr('stroke-opacity', '1')

var p = svg.selectAll('polyline')
g.selectAll("path3") //d3 geopath
.data(magnifyingGlass2) //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", "deeppink")
.style("fill-opacity", '1')
.attr('stroke','cadetblue')
.attr("stroke-width", '2')
.attr('stroke-opacity', '1')

svg.append('text')
.attr('class','layersText')
.attr('x', '440')
.attr('y','360')
.attr('font-family','Helvetica')
.attr('font-size', '1em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.style("fill", "mistyrose")
.text('Insert intro clue here')

svg.append('text')
.attr('class','layersText')
.attr('x', '440')
.attr('y','215')
.attr('font-family','Helvetica')
.attr('font-size', '1em')
.attr('text.anchor','start')
.attr('font-weight', 'bold')
.style("fill", "mistyrose")
.text('Catch the abductor before time runs out!')

svg.append('text')
.attr('class','layersText')
.attr('x', '390')
.attr('y','215')
.attr('font-family','Helvetica')
.attr('font-size', '1em')
.attr('text.anchor','start')
.attr('font-weight', 'bold')
.style("fill", "pink")
.text('Goal:')
svg.append('text')
.attr('class','layersText')
.attr('x', '390')
.attr('y','255')
.attr('font-family','Helvetica')
.attr('font-size', '1em')
.attr('text.anchor','start')
.attr('font-weight', 'bold')
.style("fill", "pink")
.text('Here is Your 1st Clue...')


return svg.node();
}
Insert cell
magnifyingGlass2 = FileAttachment("magnifying glass 2.txt").tsv({array:true})
Insert cell
magnifyingGlass1 = FileAttachment("magnifying glass 1.txt").tsv({array:true})
Insert cell
introClueRect = FileAttachment("Intro clue rect.txt").tsv({array:true})
Insert cell
investigatorTinyprofile = FileAttachment("investigator tinyprofile.txt").tsv({array:true})
Insert cell
Insert cell
buttons = {

function layersClick(event,d){
console.log(d)

var currentPage
if(buttons == 'Home'){
currentPage = html`
<div class='homepage' style='padding-top:25px'>
${homepage1}
</div>
`
}
if(buttons == 'Profile'){
currentPage = html`
<div class='profile' style='padding-top:25px'>
${profilepage}
</div>
`
}

if(buttons == 'First Clue'){
currentPage = html`
<div class='intropage' style='padding-top:25px'>
${intropage}
</div>
`
}

if(buttons == 'Main Game'){
currentPage = html`
<div class='chart' style='padding-top:25px'>
${chart}
</div>
`
}

return currentPage
}
Insert cell
Insert cell
*/ svg_embed = svg`<svg width=300 height=200 xmlns="http://www.w3.org/2000/svg">
<style>
@font-face {
font-family: 'Pacifico';
font-style: normal;
font-weight: 400;
src: url(${await toDataURL('https://fonts.gstatic.com/s/pacifico/v12/FwZY7-Qmy14u9lezJ-6H6M-Bp0u-.woff')}) format('woff'), url(${await toDataURL('https://rawcdn.githack.com/google/fonts/e9c0bd/ofl/pacifico/Pacifico-Regular.ttf')}) format('truetype');
}
rect { fill: lightsalmon }
text {
font-size: 40px;
font-family: Pacifico;
fill: black;
}
</style>
<rect x=0 y=0 width=300 height=200 />
<text x=35 y=100>Well, hello!</text>
</svg> /*
Insert cell
whitebox = FileAttachment("1280px-White_box_55x90.png").image()
Insert cell
test = FileAttachment("test.txt").tsv({array:true})
Insert cell
footsteps = FileAttachment("Footsteps@1.txt").tsv({array:true})
Insert cell
targetLine1 = FileAttachment("target line1.txt").tsv({array:true})
Insert cell
targetLine2 = FileAttachment("target line2.txt").tsv({array:true})
Insert cell
profileBorder = FileAttachment("profile border@1.txt").tsv({array:true})
Insert cell
clueBorder = FileAttachment("clue border.txt").tsv({array:true})
Insert cell
peopleBorder = FileAttachment("people border.txt").tsv({array:true})
Insert cell
rectCharacter = FileAttachment("rect character.txt").tsv({array:true})
Insert cell
targetCircle = FileAttachment("target circle@1.txt").tsv({array:true})
Insert cell
footstepsBorder3 = FileAttachment("Footsteps border3.txt").tsv({array:true})
Insert cell
timerBorder = FileAttachment("timer border.txt").tsv({array:true})
Insert cell
rectBorder = FileAttachment("rect border.txt").tsv({array:true})
Insert cell
footstepsBorder1 = FileAttachment("Footsteps border1.txt").tsv({array:true})
Insert cell
footstepsBorder2 = FileAttachment("Footsteps border2.txt").tsv({array:true})
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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more