chart = {
const width = 960,
height = 900;
const svg = d3.create("svg")
.attr("viewBox", [0, 50, width-100, height-100]);
var projection = d3
.geoMercator()
.fitSize([width - 50, height - 50], bbox1);
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
var clicks = []
svg
.on('click',function(event){
var coords = d3.pointer(event)
console.log(coords[0],coords[1])
clicks.push(coords)
console.log(clicks)
c.enter().append("circle")
.data(clicks)
.enter()
.append("circle")
.attr("cx", function(d) {return d[0]})
.attr("cy", function(d) {return d[1]})
.attr('r',3)
.attr('fill','cyan')
.style('fill-opacity','1')
var distances = []
//loop through clicks array
for(let i = 0; i <clicks.length;i++){
var dist = getDistance(10,10,clicks[i][0],clicks[i][1])
//measure the distance from static point to clicks array point
//add distances to an array
distances.push(dist)
}
//sort distances to find the shortest
var sorted = distances.sort(function(a, b){return a - b});
console.log(sorted)
var c = document.getElementById("distances");
var ctx = c.getContext("2d");
var cx= coords[0];
var cy= coords[1];
ctx.moveTo(cx,function(d) {return d[0]});
ctx.lineTo(cy,function(d) {return d[1]});
ctx.lineWidth = 1
ctx.stroke("stroke", 'black');
/* var c = document.getElementbyId("images")
/*
var c = document.getElementById("distances");
var ctx = c.getContext("2d");
var cx= function(dist)
var cy= function(dist)
ctx.moveTo(cx,function(d) {return d[0]});
ctx.lineTo(cy,function(d) {return d[1]});
ctx.lineWidth = 1
ctx.stroke("stroke", 'black');
svg.append('line')
.attr('class','spotLine')
.attr("cx",function(getDistance) {return d[0]})
.attr("cy", function(getDistance) {return d[1]})
.style('stroke-width','.75')
.style('stroke','black')
.style('stroke-dasharray','2 2')
but the function get distance feels like it could work
*/
})
/*
function draw() {
const dist = getDistance.selectAll('line');
if (!canvas.getContext) {
return;
}
function drawLine(ctx, begin, end, stroke = 'black', width = 1) {
if (stroke) {
ctx.strokeStyle = stroke;
}
*/
function showImage(elemId, imgSrc) {
console.log("Mouse is over text");
console.log("\tElemId:" + elemId + " Image Source:" + imgSrc);
const elem = document.getElementById(elemId);
const popImage = new Image();
popImage.src = imgSrc;
popImage.style.position = "position:fixed; right:0px; bottom:0px; width:50px; height:50px; border:none;"
popImage.style.zIndex = "1";
elem.appendChild(popImage);
}
function hideImage(elemId) {
console.log("Mouse is off text");
console.log("\tElemId:" + elemId);
const elem = document.getElementById(elemId);
while (elem.childElementCount > 0) {
elem.removeChild(elem.lastChild);
}
}
function changeDropdownOption(event,d){
console.log(d)
if(d=='Option 1: 4hr | Scooter | Cultural Date in central Paris'){
d3.selectAll('path.metrolines').remove()
d3.selectAll('path.walkingscooter').remove()
g.selectAll("path2")
.data(rline.features)
.enter()
.append("path")
.attr('class','rline')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1.5')
.style("stroke-width", '1.5')
.style("stroke", "red")
g.selectAll("path2")
.data(walkingScooter1.features)
.enter()
.append("path")
.attr('class','walkingScooter1')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1.5')
.style("stroke-width", '1.5')
.style("stroke", "red")
}
var c = svg.selectAll('circle')
.data(Dropdown)
.enter()
.append('circle')
//.attr('class','spots')
.attr('x','200')
.attr('y',function(d,i){return 200+(i*20)})
.attr('r',8)
.attr('fill','floralwhite')
.style("stroke-width", '1')
.style("stroke", "rgb(0,0,0)")
.text(function(d){return d})
g.selectAll("path2")
.data(lines1.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path2")
.data(lines2.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path2")
.data(lines3.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path2")
.data(lines4.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path2")
.data(lines5.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path2")
.data(lines6.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path2")
.data(lines7.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path2")
.data(bikeRoute.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path2")
.data(funSpotsLines.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1.5')
.style("stroke-width", '1.5')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path2")
.data(outdoorScenicRoutes.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path2")
.data(existingRoutesForBus.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path2")
.data(newRoutesForBus.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path2")
.data(rer.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path2")
.data(suburb1.features)
.enter()
.append("path")
.attr('class','district')
.attr("d", path2)
.style("fill", "aliceblue")
.style('fill-opacity','0.2')
.style('stroke-opacity','0.1')
.style("stroke-width", '.6')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path2")
.data(suburb2.features)
.enter()
.append("path")
.attr('class','district')
.attr("d", path2)
.style("fill", "aliceblue")
.style('fill-opacity','0.3')
.style('stroke-opacity','0.1')
.style("stroke-width", '.6')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path2")
.data(suburb3.features)
.enter()
.append("path")
.attr('class','district')
.attr("d", path2)
.style("fill", "aliceblue")
.style('fill-opacity','0.4')
.style('stroke-opacity','0.1')
.style("stroke-width", '.6')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path2")
.data(suburb4.features)
.enter()
.append("path")
.attr('class','district')
.attr("d", path2)
.style("fill", "lightsteelblue")
.style('fill-opacity','0.5')
.style('stroke-opacity','0.1')
.style("stroke-width", '.6')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path3")
.data(GreenSpaces.features)
.enter()
.append("path")
.attr('class','greenspaces')
.attr("d", path3)
.style("fill", "rgb(186, 219, 203)")
.style("fill-opacity", ".2")
.style('stroke-opacity','.5')
.style("stroke-width", '.2')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path3")
.data(water.features)
.enter()
.append("path")
.attr('class','water')
.attr("d", path3)
.style("fill", "rgb(193, 219, 224)")
.style("fill-opacity", ".4")
.style('stroke-opacity','.4')
.style("stroke-width", '.5')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path3")
.data(Streets.features)
.enter()
.append("path")
.attr('class','streets')
.attr("d", path3)
.style("fill", "rgb(200,200,200)")
.style("fill-opacity", "0")
.style('stroke-opacity','.3')
.style("stroke-width", '.1')
.style("stroke", "rgb(0,0,0)")
var c = svg.selectAll("circle")
.data(stations.features)
.enter()
.append("circle")
.attr("cx", function(d) {return path1.centroid(d)[0]})
.attr("cy", function(d) {return path1.centroid(d)[1]})
.attr('r',staRadius)//make a function
.attr('fill','rgb(120,120,120)')
.style('fill-opacity','1')
.style("stroke-width", '0.5')
.style("stroke", "black")
.on('mouseover',growDot)
.on('mouseout', shrinkDot)
.on('click', subClick) //click on subway station, perform a series of operations
function staRadius(){
//get index of this
//use index value to find the station proximity value - stationProximity[index]
//if the station proximity value ==0 then radius = 5 else radius = 2
//return radius
}
function growDot(){
d3.select(this).attr('r','5')
}
function shrinkDot(){
d3.select(this).attr('r','3')
}
var newSubways = [] //list to hold new subway lines
var clickCoords = [] //list to reocrd the start point of our line
var startPtData = []
var latlong = []
var subwayMaxLength = 600
writesubwayMaxLength() //write down initial subway budget
function subClick(event,d) {
//console.log('click')
if(clickCoords.length==1){
var startPt = [latlong[0][0],latlong[0][1]]
var endPt = [d.geometry.coordinates[0],d.geometry.coordinates[1]]
var subLength = turf.distance(startPt,endPt,{units:"meters"});
console.log(round(subLength,600))
console.log("going from " + startPtData[0].properties.name)
console.log("ending at " + d.properties.name)
//connect the points in clickCoords to the current clicks
newSubways.push({x1:clickCoords[0][0], y1:clickCoords[0][1], x2:path1.centroid(d)[0], y2:path1.centroid(d)[1], length:subLength}) //create object w/ new subways
newSubLines() //function that draws new subwayLines
subwayMaxLength = writesubwayMaxLength-subLength
writesubwayMaxLength()
latlong = [] //list that carries lat/long values so we can measure
clickCoords = [] //list that carries pixel values
startPtData = []
}else{
//add the current clicked point to clickCoords
clickCoords.push([path1.centroid(d)[0],path1.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("lines") //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('x2', function(d) {return d.x2})
.attr('y1', function(d) {return d.y1})
.attr('y2', function(d) {return d.y2})
.style('stroke-opacity','1')
.style("stroke-width", '1.5')
.style("stroke", "plum")
}
function writesubwayMaxLength(){
d3.selectAll('text.budget').remove()
svg
.append('text')
.attr('class','budget')
.attr('x','800')
.attr('y','800')
.attr('fint-sze','2em')
.attr('font-family','Helvetica')
.text(round(subwayMaxLength,600))
}
var t = svg.selectAll("text")
.data(layers)
.enter()
.append('text')
.attr('x',60)
.attr('y',function(d,i) {return 119+20*i})
.attr('fill','dimgray')
.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',40)
.attr('cy',function(d,i) {return 115+20*i})
.attr('r',5)
.attr('fill','floralwhite')
.style("stroke-width", '.3')
.style("stroke", "rgb(0,0,0)")
.on('click',layersClick)
function layersClick(event,d){
console.log(d)
if(d=='Proposed'){
d3.selectAll('path.outlines').remove()
d3.selectAll('text.layersText').remove()
d3.selectAll('path.district').remove()
svg.append('text')
.attr('class','layersText')
.attr('x', '20')
.attr('y','70')
.attr('font-family','Helvetica')
.attr('font-size', '.65em')
.attr('text.anchor','start')
.attr('font-weight', 'bold')
.text('Proposed transportation system')
svg.append('text')
.attr('class','layersText')
.attr('x', '20')
.attr('y','85')
.attr('font-family','Helvetica')
.attr('font-size', '.55em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text('Reduced number of lines for easier understanding while also reaching all tourists points.')
svg.append('text')
.attr('class','layersText')
.attr('x', '20')
.attr('y','95')
.attr('font-family','Helvetica')
.attr('font-size', '.55em')
.attr('text.anchor','start')
.attr('font-weight', 'normal')
.text('Increased metro routes for neighborhoods in outskirts for greater safety.')
g.selectAll("path2")
.data(bikeRoute.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '1.5')
.style("stroke", "darkorange")
.style('stroke-dasharray','2 2')
g.selectAll("path2")
.data(funSpotsLines.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1.5')
.style("stroke-width", '2')
.style("stroke", "darkmagenta")
g.selectAll("path2")
.data(outdoorScenicRoutes.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1.5')
.style("stroke-width", '2')
.style("stroke", "yellowgreen")
g.selectAll("path2")
.data(existingRoutesForBus.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1.5')
.style("stroke-width", '1.5')
.style("stroke", "rgb(139, 158, 166)")
g.selectAll("path2")
.data(newRoutesForBus.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1.5')
.style("stroke-width", '1.5')
.style("stroke", "lightskyblue")
.style('stroke-dasharray','2 2')
g.selectAll("path2")
.data(rer.features)
.enter()
.append("path")
.attr('class','outlines')
.attr("d", path2)
.style("fill", "none")
.style('stroke-opacity','1.5')
.style("stroke-width", '1.5')
.style("stroke", "rgb(0,0,0)")
.style('stroke-dasharray','4 4')
}
}
var wrap = svg.selectAll("text.layersText")
.each(function(d, i) { wrap_text(d3.select(this), 415) });
c.enter().append('circle')
.data(Underratedspots)
.enter()
.append("circle")
.attr("cx", function(d) {return projection([d.longitude, d.latitude])[0]})
.attr("cy", function(d) {return projection([d.longitude, d.latitude])[1]})
.attr('r',5)
.attr('fill','lightpink')
.style('fill-opacity','1')
.style('stroke','black')
.style('stroke-width','.8')
.on('mouseover', spotText)
.on('mouseout', removespotText)
c.enter().append('circle')
.data(spots)
.enter()
.append("circle")
.attr("cx", function(d) {return projection([d.longitude, d.latitude])[0]})
.attr("cy", function(d) {return projection([d.longitude, d.latitude])[1]})
.attr('r',5)
.attr('fill',colorType)
.style('fill-opacity','1')
.style('stroke','black')
.style('stroke-width','.8')
.on('mouseover', spotText)
.on('mouseout', removespotText)
g.selectAll("path4")
.data(mapKey.features)
.enter()
.append("path")
.attr('class','key')
.attr("d", path4)
.style("fill", "white")
.style('stroke-opacity','1')
.style("stroke-width", '.5')
.style("stroke", "rgb(0,0,0)")
g.selectAll("path4")
.data(keyText.features)
.enter()
.append("path")
.attr('class','key')
.attr("d", path4)
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '.25')
.style("stroke", "black")
g.selectAll("path4")
.data(cSpot.features)
.enter()
.append("path")
.attr('class','key')
.attr("d", path4)
.style("fill", "white")
.style('fill-opacity','1')
.style("stroke-width", '1')
.style("stroke", "black")
g.selectAll("path4")
.data(statSpot.features)
.enter()
.append("path")
.attr('class','key')
.attr("d", path4)
.style("fill", "black")
.style('fill-opacity','.5')
.style("stroke-width", '.15')
.style("stroke", "black")
g.selectAll("path4")
.data(distSpot.features)
.enter()
.append("path")
.attr('class','key')
.attr("d", path4)
.style("fill", "lavender")
.style('fill-opacity','.75')
.style("stroke-width", '.25')
.style("stroke", "black")
g.selectAll("path4")
.data(railSpot.features)
.enter()
.append("path")
.attr('class','key')
.attr("d", path4)
.style("fill", "none")
.style('fill-opacity','1')
.style("stroke-width", '1.5')
.style("stroke", "black")
function colorType(d,i){
var color = 'black'
if(d.type=='landmark')(color = 'white')
return color
}
/*
c.enter().append('circle')
.data(uSpots)
.enter()
.append('circle')
//.attr('class','spots')
.attr("cx",uSpots.longitude)
.attr("cy", uSpots.latitude)
//.attr("cx", projection([uSpots.longitude, uSpots.latitude])[0])
//.attr("cy", projection([uSpots.longitude, uSpots.latitude])[1])
//.attr("cx", function(d) {return projection([d.longitude, d.latitude])[0]})
//.attr("cy", function(d) {return projection([d.longitude, d.latitude])[1]})
//.attr("cx", d.longitude)
//.attr("cy", d.latitude)
.attr('r',30)
.attr('fill','green')
.style('fill-opacity','1')
.style('stroke','black')
.style('stroke-width','.8')
*/
svg
.append('circle')
.attr("cx", projection([Dropdown.longitude, Dropdown.latitude])[0])
.attr("cy", projection([Dropdown.longitude, Dropdown.latitude])[1])
.attr('r',30)
.attr('fill','yellow')
.style('fill-opacity','.5')
.style('stroke','black')
.style('stroke-width','.8')
function spotText(event,d){
d3.select(this).attr('fill','white')
svg.append('text')
.attr('class','spots')
.attr('x', '720')
.attr('y','780')
.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', '720')
.attr('y','790')
.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', '720')
.attr('y1', '786')
.attr('x2', projection([d.longitude, d.latitude])[0])
.attr('y2', '786')
.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', '786')
.attr('x2', projection([d.longitude, d.latitude])[0])
.attr('y2', projection([d.longitude, d.latitude])[1])
.style('stroke-width','.7')
.style('stroke','black')
.style('stroke-dasharray','2 2')
svg.append('image')
.attr('xlink:href','https://cdn1.jaccede.com/uploads/places/imgs/fauvettesafp-1446801949_20160622-3033-zzs.jpg')
.attr('class','spotsImage')
.attr('x', '720')
.attr('y','800')
.attr('width', 100)
.attr('height', 50)
.text(d.image)
}
function removespotText(event,d){
d3.select(this).attr('fill',colorType)
d3.selectAll('text.spots').remove()
d3.selectAll('line.spotLine').remove()
d3.selectAll('spotImage').remove()
}
svg .on('click',function(event){
var culturalspots = d3.pointer(event)
console.log(clicks)
c.enter().append("circle") //circle
.data(clicks)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr("cx", function(d) {return d[0]})
.attr("cy", function(d) {return d[1]})
.attr('r',3)
.attr('fill','black')//add function to control color by 'type'
.style('fill-opacity','1')
})
/*
function yearFill(d,i){
var color = 'none'
if(d.year == clickYear){
color = 'white'
}
return color
}
*/
//}
return svg.node();
}