import * as d3 from 'https://unpkg.com/d3?module'
//getting lots of code and insight from: https://www.d3-graph-gallery.com/index.html
// Size
var width = 650;
var height = 400;
var widthBar = 450;
var heightBar = 250;
var margin = {top: 20, right: 30, bottom: 100, left: 130};
let activeValue = "";
var turnOffFilter = false;
var currentMapYear = '2000';
//defining variables for color legend
var colorrange = ["#7c0202", "#b64d24", "#b86213", "#e18820", "#de9b10", "#f3c523", "#7c5201", "#fac45a", "#fd860b", "#ffdc6c", "#ff4901", "#a43407"] //we can change these colors later :)
var colorrangeSoft = ["#edc4c4", "#c3a599", "#dfc4ab", "#efc493", "#e7d6b5", "#f7e5a6", "#cfc8bb", "#fce8c0", "#ffbb76", "#fff1c3", "#fa976f", "#a16851"]
var categories = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11']
var colorrangeSoft = ["#edc4c4", "#c3a599", "#dfc4ab", "#efc493", "#e7d6b5", "#f7e5a6", "#cfc8bb", "#fce8c0", "#ffbb76", "#fff1c3", "#fa976f", "#a16851"]
//defining variables for choose your state visualization
var statesDict = {"Alabama": "AL",
"Alaska": "AK",
"Arizona": "AZ",
"Arkansas": "AR",
"California": "CA",
"Colorado": "CO",
"Connecticut": "CT",
"Delaware": "DE",
"Florida": "FL",
"Georgia": "GA",
"Hawaii": "HI",
"Idaho": "ID",
"Illinois": "IL",
"Indiana": "IN",
"Iowa": "IA",
"Kansas": "KS",
"Kentucky": "KY",
"Louisiana": "LA",
"Maine": "ME",
"Maryland": "MD",
"Massachusetts": "MA",
"Michigan": "MI",
"Minnesota": "MN",
"Mississippi": "MS",
"Missouri": "MO",
"Montana": "MT",
"Nebraska": "NE",
"Nevada": "NV",
"New Hampshire": "NH",
"New Jersey": "NJ",
"New Mexico": "NM",
"New York": "NY",
"North Carolina": "NC",
"North Dakota": "ND",
"Ohio": "OH",
"Oklahoma": "OK",
"Oregon": "OR",
"Pennsylvania": "PA",
"Rhode Island": "RI",
"South Carolina": "SC",
"South Dakota": "SD",
"Tennessee": "TN",
"Texas": "TX",
"Utah": "UT",
"Vermont": "VT",
"Virgina": "VA",
"Washington": "WA",
"West Virginia": "WV",
"Wisconsin": "WI",
"Wyoming": "WY"
}
var states = ["Alabama","Alaska","Arizona","Arkansas","California","Colorado","Connecticut","Delaware","Florida","Georgia","Hawaii","Idaho","Illinois","Indiana","Iowa","Kansas","Kentucky","Louisiana","Maine","Maryland","Massachusetts","Michigan","Minnesota","Mississippi","Missouri","Montana","Nebraska","Nevada","New Hampshire","New Jersey","New Mexico","New York","North Carolina","North Dakota","Ohio","Oklahoma","Oregon","Pennsylvania","Rhode Island","South Carolina","South Dakota","Tennessee","Texas","Utah","Vermont","Virginia","Washington","West Virginia","Wisconsin","Wyoming"]
var stateacr = ["AL","AK","AZ","AR","CA","CO","CT","DE","FL","GA","HI","ID","IL","IN","IA","KS","KY","LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ","NM","NY","NC","ND","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VT","VA","WA","WV","WI","WY"]
var stateProjs = {"Alabama": [-82, 30, 1000],
"Alaska": [-147, 60, 400],
"Arizona": [-107, 30, 1000],
"Arkansas": [-87, 31, 1000],
"California": [-113, 34, 1000],
"Colorado": [-100, 35, 1000],
"Connecticut": [-70, 40, 2000],
"Delaware": [-74, 38, 3000],
"Florida": [-80,26,1300],
"Georgia": [-79,30,1000],
"Hawaii": [-155,19,2000],
"Idaho": [-111, 43, 1000],
"Illinois": [-84, 38, 1300],
"Indiana": [-84, 38, 1300],
"Iowa": [-91, 40, 1300],
"Kansas": [-96, 37, 1300],
"Kentucky": [-82, 35, 1300],
"Louisiana": [-89, 30, 1300],
"Maine": [-66, 44, 1300],
"Maryland": [-74, 37, 1500],
"Massachusetts": [-69, 41, 1900],
"Michigan": [-83, 43, 1300],
"Minnesota": [-92, 45, 1300],
"Mississippi": [-86, 30, 1300],
"Missouri": [-90, 37, 1400],
"Montana": [-107, 46, 1300],
"Nebraska": [-98,40,1300],
"Nevada": [-115, 35, 1000],
"New Hampshire": [-69, 43, 1700],
"New Jersey": [-72, 38, 1900],
"New Mexico": [-103, 30, 1000],
"New York": [-73, 41, 1400],
"North Carolina": [-77, 33, 1300],
"North Dakota": [-99, 46, 1300],
"Ohio": [-81,39,1700],
"Oklahoma": [-95,34,1400],
"Oregon": [-119, 43, 1300],
"Pennsylvania": [-76, 40, 1600],
"Rhode Island": [-70, 41, 3500],
"South Carolina": [-79, 32, 1600],
"South Dakota": [-99, 43, 1400],
"Tennessee": [-82, 34, 1700],
"Texas": [-93, 29, 1000],
"Utah": [-110, 37, 1400],
"Vermont": [-71, 43, 1800],
"Virginia": [-78, 36, 1500],
"Washington": [-118,46,1300],
"West Virginia": [-79, 37, 1500],
"Wisconsin": [-88, 43,1400],
"Wyoming": [-106, 42, 1300]}
//adjusting the size of the circle for both the bubble map and the key to use
var minRadiusRange = 1;
var maxRadiusRange = 260000;
// Map projection for US
var projection = d3.geoMercator()
.center([-96, 37]) // GPS of location to zoom on
.scale(588) // This is like the zoom
.translate([ width/2, height/2 ])
// create a tooltip
var Tooltip = d3.select("#my_dataviz")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0)
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px")
//svg for US map
var svg = d3.select("#my_dataviz")
.append("svg")
.attr("width", width)
.attr("height", height)
//main color legend
var color = d3.scaleOrdinal()
.domain(categories)
.range(colorrange)
//alternate color legend for bar chart
var colorSoft = d3.scaleOrdinal()
.domain(categories)
.range(colorrangeSoft)
// Add a scale for bubble size
var size = d3.scaleLinear()
.domain([minRadiusRange,maxRadiusRange]) // What's in the data
.range([ 2, 25]) // Size in pixel
//import wildfire data.
//could also view fires that burned more than 5,000 acress, 10,000 acres, 25,000 acres, 50,000 acres, or 75,000 acres
//to change dataset view data files in assets
d3.csv("assets/firesfinaldata.csv").then((table)=>{
d3.json("assets/geojson/USA.geojson").then(function(data){
//we don't show Alaska or Hawaii on the map so exclude these from US map
let land_states = table.filter((d) => {return d.STATE != "AK"})
land_states = land_states.filter((d) => {return d.STATE != "HI"})
// Draw the map
svg.append("g")
.selectAll("path")
.data(data.features)
.enter()
.append("path")
.attr("fill", "#b8b8b8")
.attr("d", d3.geoPath()
.projection(projection)
)
.style("stroke", "black")
.style("opacity", .3)
// Add circles:
svg
.selectAll("myCircles")
.data(land_states)
.enter()
//.filter(function(d) { return (d.FIRE_YEAR== "2002") })
.append("circle")
.attr("class" , d => "year"+d.FIRE_YEAR+" dataCircles val"+ d.VALUE+""+d.FIRE_YEAR )
.attr("cx", function(d){ return projection([d.LONGITUDE, d.LATITUDE])[0] })
.attr("cy", function(d){ return projection([d.LONGITUDE, d.LATITUDE])[1] })
.attr("r", function(d){ return size(d.FIRE_SIZE) })
.style("fill", function(d){ return color(d.VALUE) })
.attr("stroke", function(d){ return color(d.VALUE) })
.attr("stroke-width", 3)
.attr("fill-opacity", .4)
.on("mouseover", function(event, d) {
Tooltip.style("opacity", 1);
Tooltip.style("display", "block");
})
.on("mousemove", function(event, d) {
Tooltip
.html("Fire year: " + d.FIRE_YEAR + "
Acres burned: " + d.FIRE_SIZE + "
Cause of fire: "+ d.NWCG_GENERAL_CAUSE+"
State: " + d.STATE + "
County: " + d.FIPS_NAME)
.style("left", (event.x)+30 + "px")
.style("top", (event.y)-30 + "px")
})
.on("mouseleave", function(event, d) {
Tooltip.style("opacity", 0);
Tooltip.style("display", "none");
})
//this is nothing important, just a very hacky way to add spacing between the map and bar chart
d3.select("#my_dataviz")
.append("svg")
.attr("width", width)
.attr("height", 60)
//now we make the bar chart
var svgBar = d3.select("#my_dataviz")
.append("svg")
.attr("width", widthBar + margin.left + margin.right)
.attr("height", heightBar + margin.top + margin.bottom)
.attr("class","overflow-viz")
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// Add X axis of the bar chart
var x = d3.scaleLinear()
.range([ 0, widthBar]);
//add x axis to the bar chart svg
var xAxis = svgBar.append("g")
.attr("transform", "translate(0," + heightBar + ")")
// Y axis
var y = d3.scaleBand()
.range([ 0, heightBar ])
.padding(.1);
//add y axis to the bar chart svg
const yAxis = svgBar.append("g");
//add labels for the bar chart
svgBar.append("text")
.attr("x", (widthBar / 2)-35) // 35 is arbitrary. Just need it to make title look centered
.attr("y", 0 - (margin.top*2.5))
.attr("text-anchor", "middle")
.style("font-size", "16px")
.style("font-weight", "bold")
.text("Human-made fires by cause"); //Title of bar chart
svgBar.append("text")
.attr("x", (widthBar / 2)-35)
.attr("y", 0 - (margin.top*1.3))
.attr("text-anchor", "middle")
.style("font-size", "14px")
.style("color", "grey")
.style("opacity", ".6")
.text("Click on bar to focus. Click again to undo."); // instructions for how to interact with bar chart
svgBar.append("text")
.attr("x", (widthBar / 2))
.attr("y", heightBar + (margin.top *3.4))
.attr("text-anchor", "middle")
.style("font-size", "12px")
.style("font-weight", "bold")
.text("Cumulative Number of acres burned by fires"); //label for the x axis of the bar chart
//function to update the bar chart data based on the selected year
function updateBarChart(selectedYear){
//only get the subset of data for the year shown
let yearData = land_states.filter( function(d){return d.FIRE_YEAR==selectedYear});
// Y axis
y.domain(yearData.map(function(d) { return d.NWCG_GENERAL_CAUSE; } ) )
yAxis.transition().duration(1000).call(d3.axisLeft(y) )
//grouping data by cause and calculating cumulative acres burned for each cause
var result = [];
yearData.reduce(function(res, value) {
if (!res[value.NWCG_GENERAL_CAUSE]) {
res[value.NWCG_GENERAL_CAUSE] = { NWCG_GENERAL_CAUSE: value.NWCG_GENERAL_CAUSE, VALUE: value.VALUE, qty: 0 };
result.push(res[value.NWCG_GENERAL_CAUSE])
}
res[value.NWCG_GENERAL_CAUSE].qty += parseInt(value.FIRE_SIZE);
return res;
}, {});
// Add X axis
x.domain([0, d3.max(result, function(d) { return parseInt(d.qty) }) ]);
xAxis
.transition()
.duration(1000)
.call(d3.axisBottom(x))
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", function(d) {
return "rotate(-65)"
});
// map data to existing bars
var bars = svgBar.selectAll("rect")
.data(result)
//generate the bar chart
bars
.join("rect")
.transition()
.duration(1000)
.attr("x", x(0) )
.attr("x", x(0) )
.attr("class",function(d){ return "val"+d.VALUE+"bar bars" })
.attr("y", d => y(d.NWCG_GENERAL_CAUSE) )
.attr("width", d => x(parseInt(d.qty)))
.attr("height", y.bandwidth() )
.style("fill", function(d){ return color(d.VALUE) })
// When the bar chart is clicked, call updateBar function
d3.selectAll("rect").on("mousedown",function(event, d) {toggleActive(); this.classList.add("active"); selectedCategory = d.NWCG_GENERAL_CAUSE; console.log(activeValue);console.log(d.VALUE);if (activeValue == "val"+d.VALUE){turnOffFilter = true;};activeValue = "";});
d3.selectAll("rect").on("mouseup",updateBar);
}
//initializing the bar chart by calling the function we made above with the year we want to show first
updateBarChart(2000);
var selectedCategory = "";
function toggleActive(){
// console.log("ACTIVATREE");
let allBars = document.getElementsByClassName("bars");
for (let i = 0; i <= allBars.length-1 ;i++){
allBars[i].classList.remove('active');
}
}
//updating bar chart when the slider is moved to a different year
function updateSlider(){
// For each check box:
d3.selectAll(".slider").each(function(d){
let cb = d3.select(this);
let newYear = cb.property("value")
let grp = "year"+newYear;
currentMapYear = newYear;
updateBarChart(currentMapYear);
svg.selectAll(".dataCircles").transition().duration(1000).style("opacity", 0).attr("r",0);
// show the group that the slider indicates
svg.selectAll("."+grp).transition().duration(1000).style("opacity", 1).attr("r", function(d){ return size(d.FIRE_SIZE) })
// Otherwise I hide it
})
}
function updateBar(e, f){
//first check if we are focusing the bars or unfocusing them
if( turnOffFilter == true){
//this is what happens to unfocus the bars
d3.selectAll("rect").each(function(d){
let cb = d3.select(this);
let ctgry = d.VALUE;
let grp = "val" + ctgry;
svg.selectAll("."+grp+""+currentMapYear).transition().duration(1000).style("opacity", 1).attr("fill-opacity", .8)
svgBar.selectAll("."+grp+"bar").transition().duration(1000).style("fill", function(d){ return color(d.VALUE) });
svg.selectAll("."+grp+""+currentMapYear).transition().duration(1000).style("opacity", 1).style("stroke", function(d){ return color(d.VALUE) }).attr("fill-opacity", .4);
svgBar.selectAll("."+grp+"bar").transition().duration(1000).style("stroke", "none" ).style("fill", function(d){ return color(d.VALUE) });
})
turnOffFilter = false;
}
else{
// For each check box:
d3.selectAll("rect").each(function(d){
let cb = d3.select(this);
let ctgry = d.VALUE;
let grp = "val" + ctgry;
if(this.classList.contains("active")!=true && activeValue != grp){
svg.selectAll("."+grp+""+currentMapYear).transition().duration(1000).style("opacity", .3).style("stroke", function(d){ return color(d.VALUE) }).attr("fill-opacity", .4);
svgBar.selectAll("."+grp+"bar").transition().duration(1000).style("stroke", "none" ).style("fill", function(d){ return colorSoft(d.VALUE) });
}
else{
activeValue = grp;
svg.selectAll("."+grp+""+currentMapYear).transition().duration(1000).style("opacity", 1).style("stroke", "black" ).attr("fill-opacity", .8)
svgBar.selectAll("."+grp+"bar").transition().duration(1000).style("fill", function(d){ return color(d.VALUE) });
}
})
}
console.log(turnOffFilter)
}
function test (e){
console.log("this is a test");
}
// When the slider changes, I run a function
d3.selectAll(".slider").on("change",updateSlider);
d3.selectAll(".checkbox").on("change",updateBar);
// And I initialize it at the beginning
updateSlider();
//now I'm making the scale circle legend
var valuesToShow = [minRadiusRange, maxRadiusRange/2, maxRadiusRange]
var xCircle = 50
var xLabel = 100
var yCircle = 380
svg
.selectAll("legend")
.data(valuesToShow)
.enter()
.append("circle")
.attr("cx", xCircle)
.attr("cy", function(d){ return yCircle - size(d) } )
.attr("r", function(d){ return size(d) })
.style("fill", "none")
.attr("stroke", "black")
svg
.selectAll("legend")
.data(valuesToShow)
.enter()
.append("line")
.attr('x1', function(d){ return xCircle + size(d) } )
.attr('x2', xLabel)
.attr('y1', function(d){ return yCircle - size(d)*1.5 } )
.attr('y2', function(d){ return yCircle - size(d)*1.5 } )
.attr('stroke', 'black')
.style('stroke-dasharray', ('2,2'))
// Add legend: labels
svg
.selectAll("legend")
.data(valuesToShow)
.enter()
.append("text")
.attr('x', xLabel)
.attr('y', function(d){ return yCircle - size(d)*1.5 } )
.text( function(d){ if(d == maxRadiusRange){return d.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")+" acres"}else{return d.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} } )
.style("font-size", 12)
.attr('alignment-baseline', 'middle')
//Choose your state visualizaiton code//
var Statesvg = d3.select("#state")
.append("svg")
.attr("width", 400)
.attr("height", 300)
//making dropdown box
d3.select("#stateSelect")
.selectAll('myStates')
.data(states)
.enter()
.append('option')
.text(function (d) { return d; }) // text showed in the menu
.attr("value", function (d) { return d; }) // corresponding value returned by the button
//setting default value for dropdown box
let element = document.getElementById("stateSelect");
element.value = "Texas";
// Map and projection for each individual state
var projection2 = d3.geoMercator()
.center([stateProjs["Texas"][0], stateProjs["Texas"][1]]) // GPS of location to zoom on
.scale(stateProjs["Texas"][2]) // This is like the zoom
.translate([ width/2, height/2 ])
state.features = data.features.filter( function(d){return d.properties.NAME=="Texas"} )
//drawing state based off of choice from dropdown box
Statesvg.selectAll("path")
.data(state.features)
.join("path")
.transition()
.duration(1000)
.attr("fill", "#b8b8b8")
.attr("d", d3.geoPath()
.projection(projection2)
)
.style("stroke", "black")
.style("opacity", .3)
//creating detail-on-demand functionality by modifying the html (inspired by Alex's tutorial in class)
let selectElem = document.querySelector("#hover_Text");
selectElem.innerHTML = "Year of Fire:
Cause of Fire:
Number of acres burned:
Location of Fire:";
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
function setHover(d) {
if (!d) {
selectElem.innerHTML = "Year of Fire:
Cause of Fire:
Number of acres burned:
Location of Fire:";
return;
}
selectElem.innerHTML = `Year of Fire: ${d.year}
Cause of Fire: ${d.cause}
Number of acres burned: ${numberWithCommas(d.acres)}
Location of Fire: ${d.county}, ${d.state}`;
}
// Add circles:
Statesvg.selectAll("myCircles")
.data(table)
.join("circle")
.attr("class" , d => "state"+ d.STATE)
.attr("cx", function(d){ return projection2([d.LONGITUDE, d.LATITUDE])[0] })
.attr("cy", function(d){ return projection2([d.LONGITUDE, d.LATITUDE])[1] })
.attr("r", 0)
.style("fill", function(d){ return color(d.VALUE) })
.attr("stroke", function(d){ return color(d.VALUE) })
.attr("stroke-width", 3)
.attr("fill-opacity", .4)
.on("mouseover", function (_, d) {
setHover({
acres: d.FIRE_SIZE,
state: d.STATE,
year: d.FIRE_YEAR,
county: d.FIPS_NAME,
cause: d.NWCG_GENERAL_CAUSE
});
})
.on("mouseout", function (_) {
setHover();
});
var currentSelection = "Texas"
// A function that update the chart
function updateState(selectedGroup) {
// Create new data with the selection
state.features = data.features.filter(function(d){return d.properties.NAME==selectedGroup})
//state specific projection
var proj = d3.geoMercator()
.center([stateProjs[selectedGroup][0], stateProjs[selectedGroup][1]]) // GPS of location to zoom on
.scale(stateProjs[selectedGroup][2]) // This is like the zoom
.translate([ width/2, height/2 ])
//redraw a new state
Statesvg.selectAll("path")
.data(state.features)
.join("path")
.transition()
.duration(1000)
.attr("fill", "#b8b8b8")
.attr("d", d3.geoPath()
.projection(proj)
)
.style("stroke", "black")
.style("opacity", .3)
var e = document.getElementById("stateSelect");
var strUser = e.value;
let grp = statesDict[selectedGroup]
//hide all of the circles
Statesvg.selectAll("myCircles")
.attr("class" , d => "state"+ d.STATE)
.attr("r", 0)
.style("fill", function(d){ return color(d.VALUE) })
.attr("stroke", function(d){ return color(d.VALUE) })
.attr("stroke-width", 3)
.attr("fill-opacity", .4)
//only show the circles that are relevant to the selected state
Statesvg.selectAll(".state"+grp)
.attr("cx", function(d){ return proj([d.LONGITUDE, d.LATITUDE])[0] })
.attr("cy", function(d){ return proj([d.LONGITUDE, d.LATITUDE])[1] })
.transition()
.duration(1000)
.style("opacity", 1).attr("r", function(d){ return size(d.FIRE_SIZE) })
}
//defualt to texas in the begining
updateState("Texas")
// When the button is changed, run the updateChart function
d3.select("#stateSelect").on("change", function(event,d) {
// recover the option that has been chosen
//set all circles to hide
Statesvg.selectAll(".state"+statesDict[currentSelection]).transition().duration(1000).style("opacity", 0).attr("r", 0)
const selectedOption = d3.select(this).property("value")
// run the updateChart function with this selected option
currentSelection = selectedOption
updateState(selectedOption)
})
//this could definitely have been done better...but for now here is the legend for the state vis
let legendSvg = d3.select("#legend").attr("class","overflow-viz")
legendSvg.append("circle").attr("cx",20).attr("cy",20).attr("r", 8).style("fill", "#7c0202")
legendSvg.append("text").attr("x", 30).attr("y", 20).text("Missing data/not specified/undetermined").style("font-size", "15px").attr("alignment-baseline","middle")
legendSvg.append("circle").attr("cx",20).attr("cy",50).attr("r", 8).style("fill", "#b64d24")
legendSvg.append("text").attr("x", 30).attr("y", 50).text("Debris and open burning").style("font-size", "15px").attr("alignment-baseline","middle")
legendSvg.append("circle").attr("cx",20).attr("cy",80).attr("r", 8).style("fill", "#b86213")
legendSvg.append("text").attr("x", 30).attr("y", 80).text("Arson/incendiarism").style("font-size", "15px").attr("alignment-baseline","middle")
legendSvg.append("circle").attr("cx",20).attr("cy",110).attr("r", 8).style("fill", "#b86213")
legendSvg.append("text").attr("x", 30).attr("y", 110).text("Equipment and vehicle use").style("font-size", "15px").attr("alignment-baseline","middle")
legendSvg.append("circle").attr("cx",20).attr("cy",140).attr("r", 8).style("fill", "#de9b10")
legendSvg.append("text").attr("x", 30).attr("y", 140).text("Recreation and ceremony").style("font-size", "15px").attr("alignment-baseline","middle")
legendSvg.append("circle").attr("cx",20).attr("cy",170).attr("r", 8).style("fill", "#f3c523")
legendSvg.append("text").attr("x", 30).attr("y", 170).text("Misuse of fire by a minor").style("font-size", "15px").attr("alignment-baseline","middle")
legendSvg.append("circle").attr("cx",20).attr("cy",200).attr("r", 8).style("fill", "#7c5201")
legendSvg.append("text").attr("x", 30).attr("y", 200).text("Smoking").style("font-size", "15px").attr("alignment-baseline","middle")
legendSvg.append("circle").attr("cx",20).attr("cy",290).attr("r", 8).style("fill", "#ffdc6c")
legendSvg.append("text").attr("x", 30).attr("y", 290).text("Fireworks").style("font-size", "15px").attr("alignment-baseline","middle")
legendSvg.append("circle").attr("cx",20).attr("cy",230).attr("r", 8).style("fill", "#ff4901")
legendSvg.append("text").attr("x", 30).attr("y", 230).text("Other causes").style("font-size", "15px").attr("alignment-baseline","middle")
legendSvg.append("circle").attr("cx",20).attr("cy",260).attr("r", 8).style("fill", "#a43407")
legendSvg.append("text").attr("x", 30).attr("y", 260).text("Firearms and explosives use").style("font-size", "15px").attr("alignment-baseline","middle")
legendSvg.append("circle").attr("cx",20).attr("cy",320).attr("r", 8).style("fill", "#fac45a")
legendSvg.append("text").attr("x", 30).attr("y", 320).text("Railroad operations and maintenance").style("font-size", "15px").attr("alignment-baseline","middle")
legendSvg.append("circle").attr("cx",20).attr("cy",350).attr("r", 8).style("fill", "#fd860b")
legendSvg.append("text").attr("x", 30).attr("y", 350).text("Power generation/transmission/distribution").style("font-size", "15px").attr("alignment-baseline","middle")
})
});
var yearShown = document.getElementById("yearShown");
myRange.oninput = function() {
yearShown.innerHTML = this.value;
}