Transgender Day of Remembrance (TDoR) 2022
390 reported trans and gender-diverse deaths between October 1, 2021 and September 30, 2022
Hover/Click for details (TW abuse, death, murder, rape, suicide, torture, transphobia, violence, weapons)






Data from tdor.translivesmatter.info, a project combining TGEU murder monitoring records with original news sources and reports. Details in accompanying blog post.


//SVG setup const widthpx = 600 const heightpx = 217 const margin = {top: 10, right: 30, bottom: 25, left: 30}, width = widthpx - margin.left - margin.right, height = heightpx - margin.top - margin.bottom;

// Custome time format var formatMillisecond = d3.timeFormat(".%L"), formatSecond = d3.timeFormat(":%S"), formatMinute = d3.timeFormat("%I:%M"), formatHour = d3.timeFormat("%I %p"), formatDay = d3.timeFormat("%a %d"), formatWeek = d3.timeFormat("%b %d"), formatMonth = d3.timeFormat("%b"), formatYear = d3.timeFormat("%Y"); function multiFormat(date) { return (d3.timeSecond(date) < date ? formatMillisecond : d3.timeMinute(date) < date ? formatSecond : d3.timeHour(date) < date ? formatMinute : d3.timeDay(date) < date ? formatHour : d3.timeMonth(date) < date ? (d3.timeWeek(date) < date ? formatDay : formatWeek) : d3.timeYear(date) < date ? formatMonth : formatYear)(date); } function loader(config) { return function() { var radius = Math.min(config.width, config.height) / 2; var tau = 2 * Math.PI; var arc = d3.arc() .innerRadius(radius*0.5) .outerRadius(radius*0.9) .startAngle(0); var svg = d3.select(config.container).append("svg") .attr("id", config.id) .attr("width", config.width) .attr("height", config.height) .append("g") .attr("transform", "translate(" + config.width / 2 + "," + config.height / 2 + ")") var background = svg.append("path") .datum({endAngle: 0.33*tau}) .style("fill", "#4D4D4D") .attr("d", arc) .call(spin, 1500) function spin(selection, duration) { selection.transition() .ease(d3.easeLinear) .duration(duration) .attrTween("transform", function() { return d3.interpolateString("rotate(0)", "rotate(360)"); }); setTimeout(function() { spin(selection, duration); }, duration); } function transitionFunction(path) { path.transition() .duration(7500) .attrTween("stroke-dasharray", tweenDash) .each("end", function() { d3.select(this).call(transition); }); } }; } var myLoader = loader({width: widthpx, height: heightpx, container: "#container", id: "loader"}); myLoader(); // Parse function for date var parseTime = d3.timeParse("%m/%d/%Y"); var formatTime = d3.timeFormat("%m/%d/%Y"); //set up svg // const svg = d3.select("body") // .append("svg") var svg = d3.select("div#container").append("svg") .attr("preserveAspectRatio", "xMinYMin meet") .attr("viewBox", "0 0 " + widthpx + " " + heightpx) // 600 200") //.attr("width", width + margin.left + margin.right) //.attr("height", height + margin.top + margin.bottom) .classed("svg-content", true) .append("g") .attr("transform",`translate(${margin.left}, ${margin.top})`); //tooltip const tooltip = d3.select("body") .append("div") .attr("class", "tooltip") .style("opacity", 0); const t = d3.transition().duration(1000); // dataFile = "data/2019/tdor2019_cln.csv" // dataFile = "data/2020/tdor2020_cln.csv" // const dataFile = "https://www.gaytascience.com/wp-content/uploads/2020/11/tdor2020_cln.csv" dataFile = "https://www.gaytascience.com/wp-content/uploads/2022/11/tdor2022_cln.csv" // Define x axis (doesnt change) var x2 = d3.scaleTime() // .domain([new Date(2019,8,27), new Date(2020,9,5)]) .domain([new Date(2021,8,26), new Date(2022,9,1)]) .rangeRound([0, width]); var target = document.getElementById("div#container"); //Update function function update(continent){ // Get the data d3.csv(dataFile, function(error, allData) { if (error) throw error; allData.forEach(function(d) { //d.cause = d.cause //d.continent = d.continent d.date = parseTime(d.date); }); loader = d3.select("svg#loader") loader.remove() // Filtered Data if (continent == 'All') { var data = allData; } else { var data = allData.filter(function(d) { return d.continent == continent}); } console.log(data) // Determine the first and last dates in the data set var dayExtent = d3.extent(allData, function (d) { return d.date; }); console.log(dayExtent); // Create one bin per week, use offset for full weeks var weekBins = d3.timeWeeks(dayExtent[0],dayExtent[1]); //histogram binning const histogram = d3.histogram() .value(function(d) { return d.date; }) .domain(x2.domain()) .thresholds(x2.ticks(weekBins.length)); //binning data const bins = histogram(data) console.log(bins) //g container for each bin let binContainer = svg.selectAll(".gBin") .data(bins); binContainer.exit().remove() let binContainerEnter = binContainer.enter() .append("g") .attr("class", "gBin") .attr("transform", d => `translate(${x2(d.x0)}, ${height})`)

//need to populate the bin containers with data the first time binContainerEnter.selectAll("image") .data(d => d.map((p, i) => { return {idx: i, name: p.name, date: formatTime(p.date), age: p.age, cause: p.cause, location: p.location, thumbnail: p.thumbnail, remarks: p.remarks, link: p.link, radius: 5 //radius: (x2(d.x1)-x2(d.x0))/2 } })) .enter() .append("image") .attr("xlink:href","https://www.gaytascience.com/wp-content/uploads/2017/11/candle0-e1511115732266.png") .attr("x", 0) //g element already at correct x pos .attr("y", function(d) { return - d.idx * 2 * d.radius - d.radius - 8; }) .on("mouseover", tooltipOn) .on("mouseout", tooltipOff) .on("click", function(d){ var url = d.link; window.open( url, '_blank' // <- This is what makes it open in a new window. ); }) .transition() .duration(500) .attr("width", 10) .attr("height", 10) // .attr("r", function(d) { // return (d.length==0) ? 0 : d.radius; }) binContainerEnter.merge(binContainer) .attr("transform", d => `translate(${x2(d.x0)}, ${height})`)

//enter/update/exit for circles, inside each container let dots = binContainer.selectAll("image") .data(d => d.map((p, i) => { return {idx: i, name: p.name, date: formatTime(p.date), age: p.age, cause: p.cause, location: p.location, thumbnail: p.thumbnail, remarks: p.remarks, link: p.link, //radius: (x2(d.x1)-x2(d.x0))/2 radius: 5 } }))

//EXIT old elements not present in data dots.exit() //.attr("class", "exit") .transition(t) //.attr("r", 0) .attr("width", 0) .attr("height", 0) .remove();

//UPDATE old elements present in new data. //dots.attr("class", "update");

//ENTER new elements present in new data. dots.enter() .append("image") .attr("xlink:href","https://www.gaytascience.com/wp-content/uploads/2017/11/candle0-e1511115732266.png") .attr("x", 0) //g element already at correct x pos .attr("y", function(d) { return - d.idx * 2 * d.radius - d.radius - 8; }) .merge(dots) .on("mouseover", tooltipOn) .on("mouseout", tooltipOff) .on("click", function(d){ var url = d.link; window.open( url, '_blank' // <- This is what makes it open in a new window. ); }) .transition() .duration(500) .attr("width", 10) .attr("height", 10) // .attr("r", function(d) { // return (d.length==0) ? 0 : d.radius; }) });//d3.csv };//update function tooltipOn(d) { //x position of parent g element let gParent = d3.select(this.parentElement) let translateValue = gParent.attr("transform") let gX = translateValue.split(",")[0].split("(")[1] let gY = height + (+d3.select(this).attr("y")+100) //let gY = 150 d3.select(this).attr("xlink:href", "https://www.gaytascience.com/wp-content/uploads/2017/11/candle2-e1511115697505.png") .classed("selected", true) tooltip.transition() .duration(200) .style("opacity", .9); // Create string to display thumbnail photo (if exists) var thumbpath = "https://www.gaytascience.com/wp-content/uploads/2022/11/" // var thumbpath = "/data/2020/" if (d.thumbnail != "") { var picstring = "" + "
"; // } else { var picstring = ""; } // Define tooltip information tooltip.html(picstring + "" + d.name + "" + "
" + "Age " + d.age + "
" + d.location + "
" + d.remarks) .style("left", gX + "px") .style("top", gY + "px"); }//tooltipOn

function tooltipOff(d) { d3.select(this).attr("xlink:href", "https://www.gaytascience.com/wp-content/uploads/2017/11/candle0-e1511115732266.png") .classed("selected", false); tooltip.transition() .duration(500) .style("opacity", 0); }//tooltipOff

// Add x axis var x2Axis = d3.axisBottom(x2) .tickFormat(multiFormat);

svg.append("g") .attr("class", "axis--x") .attr("transform", "translate(0," + height + ")") .call(x2Axis);

//draw everything update('All');