chart = {
const width = 960,
height = 900;
const svg = d3.create("svg")
.attr("viewBox", [50, 50, width - 250, height - 150]);
var projection = d3
.geoMercator()
.fitSize([width - 140, height - 30], borough_outline);
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 path6 = d3.geoPath().projection(projection);
var path7 = d3.geoPath().projection(projection);
var path8 = d3.geoPath().projection(projection);
var path9 = d3.geoPath().projection(projection);
var path10 = d3.geoPath().projection(projection);
var g = svg.append("g").attr("id", "paths");
var clicks = []
g.selectAll("path1")
.data(boroughs.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path1)
.style('fill', "none")
.style('stroke-opacity','.5')
.style("stroke-width", '.5')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path1") //d3 geopath
.data(neighborhood.features) //Current
.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','.25')
.style("stroke-width", '.25')
.style("stroke", "rgb(0,0,0)")
function demColor(d,i) {
var color = 'none'
if(d.properties.ntaname == 'Flushing' || d.properties.ntaname == 'Sunset Park West' || d.properties.ntaname == 'Sunset Park East' || d.properties.ntaname == 'Chinatown' || d.properties.ntaname == 'Bensonhurst West' || d.properties.ntaname == 'Bensonhurst East'){color = 'cyan'}
if(d.properties.ntaname == 'North Riverdale-Fieldston-Riverdale' || d.properties.ntaname == 'Ocean Parkway South' || d.properties.ntaname == 'Kensington-Ocean Parkway'){color = 'red'}
if(d.properties.ntaname == 'Sheepshead Bay-Gerritsen Beach-Manhattan Beach'){color = 'brown'}
if(d.properties.ntaname == 'Jackson Heights' || d.properties.ntaname == 'Elmhurst'){color = 'magenta'}
if(d.properties.ntaname == 'Washington Heights North' || d.properties.ntaname == 'Wahington Heights South'|| d.properties.ntaname == 'Corona'){color = 'green'}
return color
}
g.selectAll("path10") //d3 geopath
.data(streetlines.features) //Current
.enter() //there are more data than elements, this selects them
.append("path") //appends path to data
.attr('class','outlines')
.attr("d", path10) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", 'none')
.style('stroke-opacity','.25')
.style("stroke-width", '.15')
.style("stroke", "gray")
g.selectAll("path9") //d3 geopath
.data(current_lines.features) //CURRENT
.enter() //there are more data than elements, this selects them
.append("path") //appends path to data
.attr('class','outlines')
.attr("d", path8) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "none")
.style('stroke-opacity','.4')
.style("stroke-width", '.5')
.style("stroke", "rgb(0,0,0)")
var c = svg.selectAll("circle")//current
.data(current_stops.features)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('class','stops')
.attr("cx", function(d) {return path9.centroid(d)[0]})
.attr("cy", function(d) {return path9.centroid(d)[1]})
.attr('r', '1')
.attr('fill', 'gray')//add function to control color by 'type'
.style('fill-opacity','1')
.style('stroke','gray')
.style('stroke-width','1')
.on('mouseover' , stopText)
.on('mouseout', removestopText)
.on('click', curClick)
c.enter().append("circle")//current
.data(restaurant1.features)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('class','spots')
.attr("cx", function(d) {return path9.centroid(d)[0]})
.attr("cy", function(d) {return path9.centroid(d)[1]})
.attr('r', radius)
.attr('fill', cultColor)//add function to control color by 'type'
.style('fill-opacity','1')
.style('stroke','gray')
.style('stroke-width','1')
.on('mouseover' , CultureText)
.on('mouseout', removeCultureText)
.on('click', subClick)
var newSubways = [] //list to hold new subway lines
var clickCoords = [] //list to record the start point of our line
var startPtData = []
var latlong = []
var subwayBudget = 10
var subwayTime = 10
var firstIndex = 0
var secIndex = 0
var trainEnter = []
writesubwayTime()
writesubwayBudget()
function curClick(event,d){
if (clickCoords.length == 1){//this is the second click
secIndex = current_stops.features.indexOf(d)
//empty list for current stop(i) -- make a list with points to create a polyline
for (let i = firstIndex; i < secIndex + 1; i++) {
//assign variable and push location in to the list
trainEnter.push([path9.centroid(d)[0], path9.centroid(d)[1]])
}
//svg code to create polyline
//connect the point in clickCoord to current click
var startPoint = [latlong[0][0], latlong[0][1]]
var endPoint = [d.geometry.coordinates[0], d.geometry.coordinates[1]]
var subLength = turf.distance(startPoint, endPoint, {units: 'miles'})
//console.log('ending at ' + d.properties.name)
//console.log('going from ' + startPtData[0].properties.name)
newSubways.push({x1: clickCoords[0][0], y1: clickCoords[0][1], x2: path9.centroid(d)[0], y2: path9.centroid(d)[1]})
newSubLines()
subwayTime = subwayTime-(subLength*1.5)
subwayBudget = subwayBudget-(subLength*2)
writesubwayTime()
writesubwayBudget()
clickCoords = []
latlong = []
startPtData = []
//console.log(subLength)
//console.log(subwayBudget)
}else{//this is the first click
//add current click point to clickCoords
firstIndex = current_stops.features.indexOf(d)
console.log(firstIndex)
clickCoords.push([path9.centroid(d)[0], path9.centroid(d)[1]])
latlong.push([d.geometry.coordinates[0], d.geometry.coordinates[1]])
startPtData.push(d)
}
}
function subClick(event, d){
//console.log('click')
if (clickCoords.length == 1){//this is the second click
//connect the point in clickCoord to current click
var startPoint = [latlong[0][0], latlong[0][1]]
var endPoint = [d.geometry.coordinates[0], d.geometry.coordinates[1]]
var subLength = turf.distance(startPoint, endPoint, {units: 'miles'})
//console.log('ending at ' + d.properties.name)
//console.log('going from ' + startPtData[0].properties.name)
newSubways.push({x1: clickCoords[0][0], y1: clickCoords[0][1], x2: path9.centroid(d)[0], y2: path9.centroid(d)[1]})
newSubLines()
subwayTime = subwayTime-(subLength*1.5)
subwayBudget = subwayBudget-(subLength*2)
writesubwayTime()
writesubwayBudget()
clickCoords = []
latlong = []
startPtData = []
//console.log(subLength)
//console.log(subwayBudget)
}else{//this is the first click
//add current click point to clickCoords
clickCoords.push([path9.centroid(d)[0], path9.centroid(d)[1]])
latlong.push([d.geometry.coordinates[0], d.geometry.coordinates[1]])
startPtData.push(d)
}
//console.log(newSubways)
}
function newSubLines(){
//console.log('im in the function!')
var ln = svg.selectAll("line") //d3 geopath
.data(newSubways) //get data to define path
.enter() //there are more data than elements, this selects them
.append("line") //appends path to data
.attr('class','newSubwaysClass')
.attr('x1', function(d) {return d.x1})
.attr('y1', function(d) {return d.y1})
.attr('x2', function(d) {return d.x2})
.attr('y2', function(d) {return d.y2})
.style('stroke-opacity','1')
.style("stroke-width", '1')
.style('stroke', 'red')
}
function writesubwayBudget(){
d3.selectAll('text.budget').remove()
svg
.append('text')
.attr('class', 'budget')
.attr('x', '600')
.attr('y', '200')
.attr('font-size', '2em')
.attr('font-family', 'Helvetica')
.text(round(subwayBudget,3))
}
function writesubwayTime(){
d3.selectAll('text.Time').remove()
svg
.append('text')
.attr('class', 'Time')
.attr('x', '600')
.attr('y', '250')
.attr('font-size', '2em')
.attr('font-family', 'Helvetica')
.text(round(subwayTime,3))
}
function cultColor(d,i){
var color = 'black'
if(d.properties.culture=='Chinese'){color = 'rgb(244, 175, 180)'}
if(d.properties.culture=='Italian'){color = 'rgb(72, 58, 88)'}
if(d.properties.culture=='Irish'){color = 'rgb(86, 117, 104)'}
if(d.properties.culture=='Korean'){color = 'rgb(255, 209, 102)'}
if(d.properties.culture=='Mexican'){color = 'rgb(180, 149, 148)'}
if(d.properties.culture=='Jewish'){color = 'rgb(229, 75, 75)'}
if(d.properties.culture=='Russian'){color = 'rgb(148, 197, 204)'}
if(d.properties.culture=='Dominican'){color = 'rgb(52, 37, 47)'}
if(d.properties.culture=='Vietnamese'){color = 'rgb(101, 113, 83)'}
if(d.properties.culture=='Filipino'){color = 'rgb(215, 122, 97)'}
return color
}
function CultureText(event,d){
svg.append('text')
.attr('class','spotsText')
.attr('x','600')
.attr('y','100')
.attr('font-family','Helvetica')
.attr('font-size','.6em')
.attr('text-anchor','start')
.attr('font-weight','bold')
.attr('fill' , 'gray')
.text(d.properties.name)
d3.select(this).attr('r', '4')
}
function removeCultureText(event, d){
d3.select(this).attr('fill',cultColor)
d3.select(this).attr('r', radius)
d3.selectAll('text.spotsText').remove()
}
function stopText(event,d){
svg.append('text')
.attr('class','spotsText')
.attr('x','600')
.attr('y','100')
.attr('font-family','Helvetica')
.attr('font-size','.6em')
.attr('text-anchor','start')
.attr('font-weight','bold')
.attr('fill' , 'gray')
.text(d.properties.name)
d3.select(this).attr('r', '2')
}
function removestopText(event, d){
d3.select(this).attr('fill', 'gray')
d3.select(this).attr('r', '1')
d3.selectAll('text.spotsText').remove()
}
var t = svg.selectAll("text")
.data(Mtime)
.enter()
.append('text')
.attr('x', 116)
.attr('y', function(d,i) {return 115 + 20*i})
.attr('font-family','Helvetica')
.attr('font-size', '.55em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.attr('fill', 'gray')
.text(function(d) {return d})
c.enter().append('circle')
.data(Mtime)
.enter()
.append('circle')
.attr('cx', 110)
.attr('cy', function(d,i) {return 112 + 20*i}) //function is for looping data
.attr('r',3)
.attr('fill','gray')
.on('click', MtimeClick)
function MtimeClick(event,d){
if(d == 'Chinese'){
d3.selectAll('circle.spots').remove()
c.enter().append("circle") //circle
.data(cultureSpots)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('class', 'spots')
.attr("cx", function(d) {return projection([d.Longitude,d.Latitude])[0]})
.attr("cy", function(d) {return projection([d.Longitude,d.Latitude])[1]})
.attr('r', radius)
.attr('fill', chineseColor)
.style('fill-opacity','1')
.style('stroke', chineseStroke)
.style('stroke-width','1')
.on('mouseover' , CultureText)
.on('mouseout', removeCultureText)
function chineseColor(d,i){
var color = 'none'
if(d.Culture=='Chinese'){color = 'rgb(244, 175, 180)'}
return color
}
function chineseStroke(d,i){
var color = 'none'
if(d.Culture=='Chinese'){color = 'gray'}
return color
}
}
if(d == 'Italian'){
d3.selectAll('circle.spots').remove()
c.enter().append("circle") //circle
.data(cultureSpots)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('class', 'spots')
.attr("cx", function(d) {return projection([d.Longitude,d.Latitude])[0]})
.attr("cy", function(d) {return projection([d.Longitude,d.Latitude])[1]})
.attr('r', radius)
.attr('fill', italianColor)
.style('fill-opacity','1')
.style('stroke', italianStroke)
.style('stroke-width','1')
.on('mouseover' , CultureText)
.on('mouseout', removeCultureText)
function italianColor(d,i){
var color = 'none'
if(d.Culture=='Italian'){color = 'rgb(72, 58, 88)'}
return color
}
function italianStroke(d,i){
var color = 'none'
if(d.Culture=='Italian'){color = 'gray'}
return color
}
}
if(d == 'Irish'){
d3.selectAll('circle.spots').remove()
c.enter().append("circle") //circle
.data(cultureSpots)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('class', 'spots')
.attr("cx", function(d) {return projection([d.Longitude,d.Latitude])[0]})
.attr("cy", function(d) {return projection([d.Longitude,d.Latitude])[1]})
.attr('r', radius)
.attr('fill', irishColor)
.style('fill-opacity','1')
.style('stroke', irishStroke)
.style('stroke-width','1')
.on('mouseover' , CultureText)
.on('mouseout', removeCultureText)
function irishColor(d,i){
var color = 'none'
if(d.Culture=='Irish'){color = 'rgb(86, 117, 104)'}
return color
}
function irishStroke(d,i){
var color = 'none'
if(d.Culture=='Irish'){color = 'gray'}
return color
}
}
if(d == 'Korean'){
d3.selectAll('circle.spots').remove()
c.enter().append("circle") //circle
.data(cultureSpots)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('class', 'spots')
.attr("cx", function(d) {return projection([d.Longitude,d.Latitude])[0]})
.attr("cy", function(d) {return projection([d.Longitude,d.Latitude])[1]})
.attr('r', radius)
.attr('fill', koreanColor)
.style('fill-opacity','1')
.style('stroke', koreanStroke)
.style('stroke-width','1')
.on('mouseover' , CultureText)
.on('mouseout', removeCultureText)
function koreanColor(d,i){
var color = 'none'
if(d.Culture=='Korean'){color = 'rgb(255, 209, 102)'}
return color
}
function koreanStroke(d,i){
var color = 'none'
if(d.Culture=='Korean'){color = 'gray'}
return color
}
}
if(d == 'Mexican'){
d3.selectAll('circle.spots').remove()
c.enter().append("circle") //circle
.data(cultureSpots)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('class', 'spots')
.attr("cx", function(d) {return projection([d.Longitude,d.Latitude])[0]})
.attr("cy", function(d) {return projection([d.Longitude,d.Latitude])[1]})
.attr('r', radius)
.attr('fill', mexicanColor)
.style('fill-opacity','1')
.style('stroke', mexicanStroke)
.style('stroke-width','1')
.on('mouseover' , CultureText)
.on('mouseout', removeCultureText)
function mexicanColor(d,i){
var color = 'none'
if(d.Culture=='Mexican'){color = 'rgb(180, 149, 148)'}
return color
}
function mexicanStroke(d,i){
var color = 'none'
if(d.Culture=='Mexican'){color = 'gray'}
return color
}
}
if(d == 'Jewish'){
d3.selectAll('circle.spots').remove()
c.enter().append("circle") //circle
.data(cultureSpots)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('class', 'spots')
.attr("cx", function(d) {return projection([d.Longitude,d.Latitude])[0]})
.attr("cy", function(d) {return projection([d.Longitude,d.Latitude])[1]})
.attr('r', radius)
.attr('fill', jewishColor)
.style('fill-opacity','1')
.style('stroke', jewishStroke)
.style('stroke-width','1')
.on('mouseover' , CultureText)
.on('mouseout', removeCultureText)
function jewishColor(d,i){
var color = 'none'
if(d.Culture=='Jewish'){color = 'rgb(229, 75, 75)'}
return color
}
function jewishStroke(d,i){
var color = 'none'
if(d.Culture=='Jewish'){color = 'gray'}
return color
}
}
if(d == 'Russian'){
d3.selectAll('circle.spots').remove()
c.enter().append("circle") //circle
.data(cultureSpots)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('class', 'spots')
.attr("cx", function(d) {return projection([d.Longitude,d.Latitude])[0]})
.attr("cy", function(d) {return projection([d.Longitude,d.Latitude])[1]})
.attr('r', radius)
.attr('fill', russianColor)
.style('fill-opacity','1')
.style('stroke', russianStroke)
.style('stroke-width','1')
.on('mouseover' , CultureText)
.on('mouseout', removeCultureText)
function russianColor(d,i){
var color = 'none'
if(d.Culture=='Russian'){color = 'rgb(148, 197, 204)'}
return color
}
function russianStroke(d,i){
var color = 'none'
if(d.Culture=='Russian'){color = 'gray'}
return color
}
}
if(d == 'Dominican'){
d3.selectAll('circle.spots').remove()
c.enter().append("circle") //circle
.data(cultureSpots)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('class', 'spots')
.attr("cx", function(d) {return projection([d.Longitude,d.Latitude])[0]})
.attr("cy", function(d) {return projection([d.Longitude,d.Latitude])[1]})
.attr('r', radius)
.attr('fill', dominicanColor)
.style('fill-opacity','1')
.style('stroke', dominicanStroke)
.style('stroke-width','1')
.on('mouseover' , CultureText)
.on('mouseout', removeCultureText)
function dominicanColor(d,i){
var color = 'none'
if(d.Culture=='Dominican'){color = 'rgb(52, 37, 47)'}
return color
}
function dominicanStroke(d,i){
var color = 'none'
if(d.Culture=='Dominican'){color = 'gray'}
return color
}
}
if(d == 'Vietnamese'){
d3.selectAll('circle.spots').remove()
c.enter().append("circle") //circle
.data(cultureSpots)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('class', 'spots')
.attr("cx", function(d) {return projection([d.Longitude,d.Latitude])[0]})
.attr("cy", function(d) {return projection([d.Longitude,d.Latitude])[1]})
.attr('r', radius)
.attr('fill', vietColor)
.style('fill-opacity','1')
.style('stroke', vietStroke)
.style('stroke-width','1')
.on('mouseover' , CultureText)
.on('mouseout', removeCultureText)
function vietColor(d,i){
var color = 'none'
if(d.Culture=='Vietnamese'){color = 'rgb(101, 113, 83)'}
return color
}
function vietStroke(d,i){
var color = 'none'
if(d.Culture=='Vietnamese'){color = 'gray'}
return color
}
}
if(d == 'Filipino'){
d3.selectAll('circle.spots').remove()
c.enter().append("circle") //circle
.data(cultureSpots)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('class', 'spots')
.attr("cx", function(d) {return projection([d.Longitude,d.Latitude])[0]})
.attr("cy", function(d) {return projection([d.Longitude,d.Latitude])[1]})
.attr('r', radius)
.attr('fill', filipinoColor)
.style('fill-opacity','1')
.style('stroke', filipinoStroke)
.style('stroke-width','1')
.on('mouseover' , CultureText)
.on('mouseout', removeCultureText)
function filipinoColor(d,i){
var color = 'none'
if(d.Culture=='Filipino'){color = 'rgb(215, 122, 97)'}
return color
}
function filipinoStroke(d,i){
var color = 'none'
if(d.Culture=='Filipino'){color = 'gray'}
return color
}
}
}
var wrap = svg.selectAll("text.history")
.each(function(d, i) { wrap_text(d3.select(this), 250) });//value controls how wide text gets
return svg.node();
}