function updateCharts(d, mapData) { let latestDate = mapData.tracking[mapData.tracking.length-1].date; updateSquareChart(d.tracking[d.tracking.length-1]) updateNewCurveChart('#covid-canada-date-chart', d, chartInput, latestDate) //updateDateChart('#covid-canada-date-chart', d, chartSettings.date.cumulative, mapData) } let chartInput = ['raw', 'average', ['cases']]; /// Map Create function createMap(parent, mapData) { let container = d3.select(parent); let mapSVG = container.append('svg').attr('class', 'map-svg') .attr('width', '100%') .attr('viewBox', '0 0 750 400') mapSVG.append('rect') .attr('width', '100%') .attr('height', '100%') .attr('fill', '#ffffff') .on('click', function(){ updateCharts(mapData, mapData) }) let mapLayer = mapSVG.append('g') .attr('class', 'map-layer') let circleLayer = mapSVG.append('g') .attr('class', 'circle-layer') let textLayer = mapSVG.append('g') .attr('class', 'text-layer') let wordLayer = mapSVG.append('g') .attr('class', 'word-layer') //let width = Number(mapSVG.style('width').split('px')[0]); //let height = Number(mapSVG.style('height').split('px')[0]); let width = 750; let height = 400; //let projection = d3.geoMercator().fitExtent([[0, -height/2],[width, height*1.05]], mapData); let projection = d3.geoConicConformal().rotate([103, 0]).fitExtent([[0, -height/3],[width, height*1.05]], mapData); let geoGenerator = d3.geoPath().projection(projection); let minProvinceCases = 1; let maxProvinceCases = 0; mapData.features.forEach(province => { maxProvinceCases = Math.max(province.tracking[province.tracking.length-1].total, maxProvinceCases); }) //console.log(maxProvinceCases) let colorScale = d3.scaleLinear() .domain([minProvinceCases, maxProvinceCases/8, maxProvinceCases]) .range(["#F9DC9F", "#F6CA70", "#F4BB3F"]) let m = mapLayer.selectAll('path') .data(mapData.features) m.enter() .append("path") .attr('class', 'province') .attr("d", geoGenerator) .attr("fill", d => d.tracking[d.tracking.length-1].total > 0 ? colorScale(d.tracking[d.tracking.length-1].total) : '#e3e3e3') .attr('fill-opacity', 1) .attr('stroke-linejoin', 'round') .attr("stroke", '#ffffff') .on('click', (d, i, node) => { updateCharts(d, mapData) }) function adjustedY(d) { let dy = 0; if (d.properties.PRENAME === 'Prince Edward Island') { dy = -6; } else if (d.properties.PRENAME === 'Nova Scotia') { dy = 4; } else if (d.properties.PRENAME === 'Yukon') { dy = 23; } else if (d.properties.PRENAME === 'Northwest Territories') { dy = 63; } else if (d.properties.PRENAME === 'Nunavut') { dy = 102; } else if (d.properties.PRENAME === 'Ontario') { dy = -8; } else if (d.properties.PRENAME === 'Newfoundland and Labrador') { dy = -10; } else if (d.properties.PRENAME === 'Saskatchewan') { dy = -10; } return dy } function adjustedX(d) { let dx = 0; if (d.properties.PRENAME === 'Northwest Territories') { dx = 23; } else if (d.properties.PRENAME === 'Nunavut') { dx = -45; } else if (d.properties.PRENAME === 'Newfoundland and Labrador') { dx = -10; } return dx } let c = circleLayer.selectAll('circle') .data(mapData.features) c.enter().append('circle') .attr('class', 'map-circle') .attr('cx', d => geoGenerator.centroid(d)[0] + adjustedX(d)) .attr('cy', d => geoGenerator.centroid(d)[1] + adjustedY(d)) .attr('r', d => d.tracking[d.tracking.length-1].total > 1000 ? 28 : 20) .attr('stroke', '#ccc') .attr('stroke-width', 0) .style('cursor', 'pointer') .on('mouseover', function(d) { this.style.strokeWidth = 0.5; }) .on('mouseout', function(d) { this.style.strokeWidth = 0; }) .on('click', (d, i, node) => { updateCharts(d, mapData) }) let t = textLayer.selectAll('text .number') .data(mapData.features) t.enter().append('text') .attr('class', 'map-text') .attr('x', d => geoGenerator.centroid(d)[0] + adjustedX(d)) .attr('y', d => geoGenerator.centroid(d)[1] + adjustedY(d) + 7) .attr('text-anchor', 'middle') .attr('font-family', `'CTVSans-Bold','CTV Sans',Arial`) .attr('font-size', d => ['New Brunswick', 'Nova Scotia', 'Prince Edward Island'].includes(d.properties.PRENAME) ? 16 : 20) .style('pointer-events', 'none') .text(d => d.tracking[d.tracking.length-1].total.toLocaleString()) wordLayer.append('text') .attr('class', 'map-text') .attr('x', 230).attr('y', 360) .attr('text-anchor', 'end').attr('font-family', `'CTVSans-Regular','CTV Sans',Arial`) .attr('font-size', 36) .style('pointer-events', 'none') .text('Total Cases:') wordLayer.append('text') .attr('x', 230 + 10).attr('y', 360) .attr('text-anchor', 'start') .attr('font-family', `'CTVSans-Bold','CTV Sans',Arial`) .attr('font-size', 36) .attr('fill', '#F4BB3F') .style('pointer-events', 'none') .text(mapData.tracking[mapData.tracking.length-1].total.toLocaleString()) let repNum = mapData.repatriated wordLayer.append('text') .attr('x', 30).attr('y', 380) .attr('text-anchor', 'start').attr('font-family', `'CTVSans-Regular','CTV Sans',Arial`) .attr('font-size', 14) .style('pointer-events', 'none') .attr('fill', '#b3b3b3') .text(`Includes ${repNum.toLocaleString()} repatriated Canadians not on map`) }