// GLOBAL VARIABLES // // Set dimensions const width = 360 let dimensions = { width: width, height: width, margin: { top: 20, right: 20, bottom: 100, left: 100, }, } dimensions.boundedWidth = dimensions.width - dimensions.margin.left - dimensions.margin.right dimensions.boundedHeight = dimensions.height - dimensions.margin.top - dimensions.margin.bottom // Create scales const xScale = d3.scaleLinear() .range([0, dimensions.boundedWidth]) const yScale = d3.scaleLinear() .range([dimensions.boundedHeight, 0]) const xAxisGenerator = d3.axisBottom() .scale(xScale) const yAxisGenerator = d3.axisLeft() .scale(yScale) const xAccessor = d => parseFloat(d.xfrom) + 0.5 * Math.random() //hack to spread points a wee bit const yAccessor = d => parseFloat(d.yfrom) + 0.5 * Math.random() //hack to spread points a wee bit that overlap exactly const imgTitle = d => d.name const imgAuthor = d => d.author const srcURL = d => d.url const imgURL = d => d.imgURL const domainAccessor = d => d.primary_domain const secondaryDomainAccessor = d => d.secondary_domain const tooltip = d3.select("#tooltip") const imgTitleTT = d3.select("#name-title") const imgAuthorTT = d3.select("#author-title") const srcURLTT = d3.select("#link-title") const domainAccessorTT = d3.select("#primary-domain-title") const secondDomainAccessorTT = d3.select("#secondary-domain-title") const imgPreview = d3.select("#preview-img") // CMT rationale variables const structuralAccessor = d => d.structural_details const ontologicalAccessor = d => d.ontological_details const orientationalAccessor = d => d.orientational_details const imagisticAccessor = d => d.imagistic_details const textGraphicMetaphorAcc = d => d.text_support_graphical_metaphors const textGraphicMetaphorDetailsAcc = d => d.text_support_graphical_metaphor_details const structTT = d3.select("#structural-details") const ontoTT = d3.select("#ontological-details") const orientTT = d3.select("#orientational-details") const imagTT = d3.select("#imagistic-details") const textMetTT = d3.select("#text-support-graphical-metaphors") const textMetTypeTT = d3.select("#text-support-graphical-metaphors-details") function domainTick(whichDomain) { if (whichDomain == "Biomedicine") { //const yTick = [10, 20, 30, 40, 50, 60, 70, 80, 90] const yTickStr = [ 'molecules', 'viruses', 'cells', 'bacteria', 'tissues', 'organs', 'organ systems', 'organism', 'population', ] //const xTick = [10, 20, 30, 40, 50, 60, 70, 80, 90] const xTickStr = [ "nanosec", "sec", "min", "hour", "day", "week", "month", "year" ] return [xTickStr, yTickStr] } else if (whichDomain == "Climate") { //const yTick = [10, 20, 30] const yTickStr = [ "local", "regional", "global" ] //const xTick = [10, 20, 30, 40, 50] const xTickStr = [ "<1 year", "decade", "century", "thousand", "" //HANNA check this ] return [xTickStr, yTickStr] } else if (whichDomain == "Space") { //const yTick = [10, 20, 30, 40, 50, 60] const yTickStr = [ "objects in space", "planet", "star", "black holes", "galaxy", "universe", ] //const xTick = [10, 20, 30, 40] const xTickStr = [ "<1 yr", "decade", "million", "billion" ] return [xTickStr, yTickStr] } else if (whichDomain == "Anthropology") { //const yTick = [10, 20, 30, 40, 50] const yTickStr = [ "local", "regional", "continental", "intercontinental", "global" ] //const xTick = [10, 20, 30, 40, 50, 60, 70, 80] const xTickStr = [ "<1 yr", "decade", "century", "quincent.", "thousand", "centamill.", "million", "billion" ] return [xTickStr, yTickStr] } } function onMouseEnter(e, datum) { const barLengths = [ {"metaphorType" : "Str", "count" : parseInt(datum.cnt_structural)}, {"metaphorType" : "Ont", "count" : parseInt(datum.cnt_ontological)}, {"metaphorType" : "Ori", "count" : parseInt(datum.cnt_orientational)}, {"metaphorType" : "Img", "count" : parseInt(datum.cnt_imagistic)}, ] updateBarPlot(barLengths) //CMT rationale structTT.text(structuralAccessor(datum)) ontoTT.text(ontologicalAccessor(datum)) orientTT.text(orientationalAccessor(datum)) imagTT.text(imagisticAccessor(datum)) textMetTT.text(textGraphicMetaphorAcc(datum)) textMetTypeTT.text(textGraphicMetaphorDetailsAcc(datum)) // Other image metadata to populate based on mouseHover: imgTitleTT.text(imgTitle(datum)) imgAuthorTT.text(imgAuthor(datum)) srcURLTT.text(srcURL(datum)) domainAccessorTT.text(domainAccessor(datum)) secondDomainAccessorTT.text(secondaryDomainAccessor(datum)) imgPreview.attr("src", "./images/placeholder.png") imgPreview.attr("src", imgURL(datum)) this.parentNode.appendChild(this); //move hovered item to top d3.select(this) .transition().ease(d3.easeLinear) .duration(400) .attr("fill", "black") // BRIGHT TURQ #5afaed .attr("opacity", 1) .attr("r", 10) } function onMouseLeave() { tooltip.style("opacity", 0) d3.select(this) .transition().ease(d3.easeLinear) .duration(400) .attr("fill", "gray") .attr("opacity", 0.5) .attr("r", 5) //imgPreview.attr("src", "./images/placeholder.png") } function setTickMarks(dataset) { let whichDomain = domainAccessor(dataset[0]) console.log(dataset[0]) let ticks = domainTick(whichDomain) console.log(ticks) xAxisGenerator .ticks(ticks[0].length) .tickFormat(d => ticks[0][d-1]) //bring to 0 since lowest value in dataset is 1 yAxisGenerator .ticks(ticks[1].length) .tickFormat(d => ticks[1][d-1]) } function styleAxes(dataset, scatterBounds) { //redraw x axis xScale.domain([d3.extent(dataset, xAccessor)[0]-0.5, d3.extent(dataset, xAccessor)[1]+0.5]) scatterBounds.selectAll(".myXaxis").transition() .duration(750) .call(xAxisGenerator) .selectAll("text") .style("text-anchor", "end") .attr("dx", "-.8em") .attr("dy", ".15em") .attr("transform", "rotate(-30)") //redraw y axis yScale.domain([d3.extent(dataset, xAccessor)[0]-0.5, d3.extent(dataset, yAccessor)[1]+0.5]) scatterBounds.selectAll(".myYaxis").transition() .duration(750) .call(yAxisGenerator) } async function drawScatterPlot(dataset) { // Initial draw canvas const scatterWrapper = d3.select("#scatterplot") .append("svg") .attr("width", dimensions.width) .attr("height", dimensions.height) const scatterBounds = scatterWrapper.append("g") .attr("id", "scatter-bounds") .style("transform", `translate(${ dimensions.margin.left }px, ${ dimensions.margin.top }px)`) // Access data //const dataset= await d3.csv(dataCSV) //console.table(dataset[0]) setTickMarks(dataset) const xAxis = scatterBounds.append("g") .call(xAxisGenerator) .style("transform", `translateY(${dimensions.boundedHeight}px)`) .attr("class", "myXaxis") // scatterBounds.selectAll(".myXaxis") // .selectAll("text") // .style("text-anchor", "end") // .attr("dx", "-.8em") // .attr("dy", ".15em") // .attr("transform", "rotate(-30)") const yAxis = scatterBounds.append("g") .call(yAxisGenerator) .attr("class", "myYaxis") styleAxes(dataset, scatterBounds) scatterBounds.append("text") .attr("class", "y label") .attr("text-anchor", "end") .attr("y", -dimensions.margin.left + 15) .attr("x", -dimensions.margin.top) .attr("fill", "black") //.style("font-size", "1.2em") .attr("transform", "rotate(-90)") .text("SPATIAL COVERAGE") scatterBounds.append("text") .attr("class", "x label") .attr("text-anchor", "end") .attr("x", dimensions.boundedWidth) .attr("y", dimensions.boundedHeight + 55) .text("TEMPORAL COVERAGE"); // const sqs = scatterBounds.selectAll("rect").data(rangeRectangles) // sqs // .join("rect") // .attr("x", d => xScale(x1RectAccessor(d))) // .attr("y", d => yScale(y2RectAccessor(d))) // .attr("width", d => xScale(x2RectAccessor(d))-xScale(x1RectAccessor(d))) // .attr("height", d => yScale(y1RectAccessor(d))-yScale(y2RectAccessor(d))) // .attr("rx", 15) // .attr("fill-opacity", 0.3) //create update selection to bind new data const dots = scatterBounds.selectAll("circle").data(dataset) dots .join("circle") //.attr('class', 'circle-base') .transition().duration(750) .attr("cx", d => xScale(xAccessor(d))) .attr("cy", d => yScale(yAccessor(d))) .attr("fill", "gray") //teal color rgb(1, 148, 136) .attr("opacity", 0.5) .attr("r", 5) // INTERACTIONS scatterBounds.selectAll("circle").on("mouseenter", function(e, d){ console.log(e.target) }) scatterBounds.selectAll("circle") .on("mouseenter", onMouseEnter) .on("mouseleave", onMouseLeave) } async function updateScatterPlot(dataset) { //const dataset= await d3.csv(dataCSV) console.log("this is my new data") console.table(dataset[1]) const scatterBounds = d3.select("#scatter-bounds") // redraw X and Y axes setTickMarks(dataset) styleAxes(dataset, scatterBounds) // redraw dots in new position const dots = scatterBounds.selectAll("circle").data(dataset) dots .join("circle") .transition().duration(1000) .attr("cx", d => xScale(xAccessor(d))) .attr("cy", d => yScale(yAccessor(d))) }