Public
Edited
Dec 13, 2022
Insert cell
# Berlin U & S Bahn Interactive update
Insert cell
bbox2 = FileAttachment("Berlin BB 10-13-22.geojson")
Insert cell
d3 = require("d3@6")
Insert cell
chart = {
const width = 1000,
height = 900;
const svg = d3.create("svg")
.attr("viewBox", [100, 10, width-150, height-150]);

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

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");

var clickYear = 2000
//i'm not using the boundary lines, so I'm going to comment them out
/*
g.selectAll("path1") //d3 geopath
.data(boundary.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", path1) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '.5')
.style("stroke", "rgb(0,0,0)")
*/


// display roads
//show current transit sytems
//display connected parks
//display proposed sytem
//Movable object across an array of points along a single curve
//select parks for information
//hover over tram to get information on it
g.selectAll("path2") //d3 geopath
.data(Current.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", '.3')
.style("stroke", "black")





g.selectAll("path2") //d3 geopath
.data(berlinTransportStops1.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("path") //appends path to data
.attr('class','stops')
.attr("d", path2) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "black")
.style("fill-opacity", ".6")
.style('stroke-opacity','.8')
.style("stroke-width", '.5')
.style("stroke", "black")

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

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

g.selectAll("path3") //d3 geopath
.data(bldgs2.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("path") //appends path to data
.attr('class','buildings')
.attr("d", path3) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "beige")
.style("fill-opacity", ".3")
.style('stroke-opacity','.4')
.style("stroke-width", '.5')
.style("stroke", "rgb(0,0,0)")



var c = svg.selectAll("path3") //d3 geopath
.data(bldgs)
.enter() //there are more data than elements, this selects them
.append("path") //appends path to data
.attr('class','outlines')
.attr('d',path3)
.style("fill", "blue")
.style('fill-opacity','0.2')
.style('stroke-opacity','0.1')
.style("stroke-width", '.6')
.style("stroke", "rgb(0,0,0)")

var c = svg.selectAll("circle")
.data(berlinTransportStops1.features)
.enter()
.append("circle")
.attr("cx", function(d) {return path1.centroid(d)[0]})
.attr("cy", function(d) {return path1.centroid(d)[1]})
.attr('r',2)
.attr('fill','rgb(120,120,120)')
.style('fill-opacity','1')
.style("stroke-width", '0.5')
.style("stroke", "blue")

var t = svg.selectAll("text")
.data(layers)
.enter()
.append('text')
.attr('x',120)
.attr('y',function(d,i) {return 200+20*i})
.attr('fill','black')
.attr('font-family','Helvetica')
.attr('font-size', '.65em')
.attr('text.anchor','start')
.attr('font-weight', 'bold')
.text(function(d) {return d})
c.enter().append('circle')
.data(layers)
.enter()
.append('circle')
.attr('cx',110)
.attr('cy',function(d,i) {return 195+20*i})
.attr('r',5)
.attr('fill','aqua')
.style("stroke-width", '.5')
.style("stroke", "black")
.on('click',layersClick)
function layersClick(event,d){
console.log(d)
if(d=='1902'){
clickYear = 1902
d3.selectAll('path.outlines').remove()
d3.selectAll('path.stops').remove()
d3.selectAll('text.layersText').remove()

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','70')
.attr('font-family','Helvetica')
.attr('font-size', '.65em')
.attr('text.anchor','start')
.attr('font-weight', 'Bold')
.text('Untergrundbahn (Now U1 & U2)')

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','85')
.attr('font-family','Helvetica')
.attr('font-size', '.55em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text('Berlins First Unntergrund or Underground Railway')

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','95')
.attr('font-family','Helvetica')
.attr('font-size', '.55em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text('Opened Between Warshauer, Brucke and Potsdamer Platz')
}
if(d=='1910'){
clickYear = 1910
d3.selectAll('path.outlines').remove()
d3.selectAll('path.stops').remove()
d3.selectAll('text.layersText').remove()


g.selectAll("path2")
.data(Line2.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1.5')
.style("stroke", "rgb(0,0,0)")

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','70')
.attr('font-family','Helvetica')
.attr('font-size', '.65em')
.attr('text.anchor','start')
.attr('font-weight', 'Bold')
.text('U1 & U2 Extend further West & East')

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','85')
.attr('font-family','Helvetica')
.attr('font-size', '.55em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text('More Cities are connected by the underground rail')
}
if(d=='1920'){
clickYear = 1920
d3.selectAll('path.outlines').remove()
d3.selectAll('path.stops').remove()
d3.selectAll('text.layersText').remove()

g.selectAll("path2")
.data(Line3.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1.5')
.style("stroke", "rgb(0,0,0)")

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','70')
.attr('font-family','Helvetica')
.attr('font-size', '.65em')
.attr('text.anchor','start')
.attr('font-weight', 'Bold')
.text('The U3 is added')

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','85')
.attr('font-family','Helvetica')
.attr('font-size', '.55em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text('Wittenbergplatz is now connected to uhlandstrabe & Theilplatz')

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','95')
.attr('font-family','Helvetica')
.attr('font-size', '.55em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text('')
}
if(d=='1930'){
clickYear = 1930
d3.selectAll('path.outlines').remove()
d3.selectAll('path.stops').remove()
d3.selectAll('text.layersText').remove()

g.selectAll("path2")
.data(Line4.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1.5')
.style("stroke", "rgb(0,0,0)")

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','70')
.attr('font-family','Helvetica')
.attr('font-size', '.65em')
.attr('text.anchor','start')
.attr('font-weight', 'Bold')
.text('Line 6 (now U6) opens and connects to 8 new cities)')

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','85')
.attr('font-family','Helvetica')
.attr('font-size', '.55em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text('Berlins First electric railway opens in 1924')

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','95')
.attr('font-family','Helvetica')
.attr('font-size', '.55em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text('The U2 & U7 extend to new cities and the system scales up dramaticaly')
}

if(d=='1940'){
clickYear = 1940
d3.selectAll('path.outlines').remove()
d3.selectAll('path.stops').remove()
d3.selectAll('text.layersText').remove()
g.selectAll("path2")
.data(Line5.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1.5')
.style("stroke", "rgb(0,0,0)")

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','70')
.attr('font-family','Helvetica')
.attr('font-size', '.65em')
.attr('text.anchor','start')
.attr('font-weight', 'Bold')
.text('Bombing of berlin results in many stations to cease operations')

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','85')
.attr('font-family','Helvetica')
.attr('font-size', '.55em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text('Berlin is divided into occupation zones controlled by allied powers that later becomes east and west berlin')

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','95')
.attr('font-family','Helvetica')
.attr('font-size', '.55em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text(' East and west Germany were established and Berlin officially split into two.')
}

if(d=='1970'){
clickYear = 1970
d3.selectAll('path.outlines').remove()
d3.selectAll('path.stops').remove()
d3.selectAll('text.layersText').remove()
g.selectAll("path2")
.data(Line6.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1.5')
.style("stroke", "rgb(0,0,0)")

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','70')
.attr('font-family','Helvetica')
.attr('font-size', '.65em')
.attr('text.anchor','start')
.attr('font-weight', 'Bold')
.text('1961 marks the construction of berlin wall completely cut off west berlin from the rest of east germany')

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','85')
.attr('font-family','Helvetica')
.attr('font-size', '.55em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text('s-bahn ridership in west berlin significantly drops as west berliners boycotts east berlin controlled s-bahn')

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','95')
.attr('font-family','Helvetica')
.attr('font-size', '.55em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text('s-bahn opens service from Blankenburg to Hohen Neuendorf replace connection lost from the wall')
}

if(d=='1995'){
clickYear = 1970
d3.selectAll('path.outlines').remove()
d3.selectAll('path.stops').remove()
d3.selectAll('text.layersText').remove()
g.selectAll("path2")
.data(Line7.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1.5')
.style("stroke", "rgb(0,0,0)")

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','70')
.attr('font-family','Helvetica')
.attr('font-size', '.65em')
.attr('text.anchor','start')
.attr('font-weight', 'Bold')
.text('With German reunification closed railways begin restoration')

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','85')
.attr('font-family','Helvetica')
.attr('font-size', '.55em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text('')

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','95')
.attr('font-family','Helvetica')
.attr('font-size', '.55em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text('')
}
if(d=='Current'){
clickYear = Current
d3.selectAll('path.outlines').remove()
d3.selectAll('text.layersText').remove()
g.selectAll("path2") //d3 geopath
.data(Current.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", '.5')
.style("stroke", "black")
svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','70')
.attr('font-family','Helvetica')
.attr('font-size', '.65em')
.attr('text.anchor','start')
.attr('font-weight', 'Bold')
.text('The system continues to grow and the restorations also continue')

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','85')
.attr('font-family','Helvetica')
.attr('font-size', '.55em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text('')

svg.append('text')
.attr('class','layersText')
.attr('x', '110')
.attr('y','95')
.attr('font-family','Helvetica')
.attr('font-size', '.55em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text('')
}
}
svg
.append('rect')
.attr('fill', "white")
.attr('opacity','.8')
.attr('stroke',"rgb(0,0,0)")
.attr('stroke-width',"1px")
.attr('x', 67)
.attr('y', 60)
.attr('width', 600)
.attr('height', 40)


function removespotText(event,d)
{d3.select(this).attr('fill','green')
d3.selectAll('text.spots').remove()
d3.selectAll('line.spotLine').remove()
}




return svg.node();
}
Insert cell
layers = ['1902', '1910', '1920','1930','1940','1970','1995','Current']
Insert cell
Line7 = FileAttachment("1995.geojson").json()
Insert cell
berlinTransportStops1 = FileAttachment("Berlin Transport Stops@1.geojson").json()
Insert cell
bldgs = FileAttachment("Berlin Parks@2.geojson").json()
Insert cell
bldgs2 = FileAttachment("LU-Residential 4 @1.geojson").json()
Insert cell
Current = FileAttachment("Railways.geojson").json()
Insert cell
waterways = FileAttachment("Berlin Waterways@1.geojson").json()
Insert cell
bbox = FileAttachment("Berlin BB 10-13-22.geojson").json()
Insert cell
Insert cell
Spots = d3.csv(Spotslink,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