timeline = {
const scale =1;
let svg = d3.create("svg")
.attr("width", scale * 1200)
.attr("height", 4000)
.style("background","black")
const chart = svg.append("g")
const timeScale = d3.scaleLinear()
.domain([1860, 2000])
.range([scale * 500, scale * 4000]);
const xScale = d3.scaleLinear()
.domain([0,4])
.range([scale * 200, scale * 1100]);
const topics = ["computer science","mathematics","physics","chemistry","biology",
"economics","psychology"];
const topicColors = ["#00ffeb","#00b9ff","violet","#ff8400","#83ff00",
"gold","#fa207b"];
chart.append("g")
.attr("transform", "translate(20,0)")
.call(d3.axisRight(timeScale)
.tickFormat(d => d)
.tickSize(10)
)
.style("color","lightgrey")
.style("opacity", 0.4)
.style("font-size",scale * 50)
.style("stroke-width", scale * 5);
const images = await Promise.all(scientists2.map(scientist => scientist.imgUrl));
let defs = svg.append("defs")
let radiusFunc = (rank) => 0.5*(Math.max(160 - 5*Math.sqrt(rank) , 50));
defs.selectAll(".bubbleClip")
.data(scientists2)
.join("clipPath")
.attr("id", d => d.name.replaceAll(" ","-") + "-clip")
.append("circle")
.attr("cx", (d,i)=> scale * d.xShift + xScale(topics.indexOf(d.field)))
.attr("cy", d=> ((timeScale(d.dates.split(" -")[0]))))
.attr("r" , d => scale * radiusFunc(d.rank))
chart.selectAll(".bubbleShadow2")
.data(scientists2)
.join("circle")
.attr("cx", (d,i)=> (scale * d.xShift + xScale(topics.indexOf(d.field))))
.attr("cy", d=> ((timeScale(d.dates.split(" -")[0]))))
.attr("r" , d => scale * radiusFunc(d.rank))
.attr("transform","scale(0.3,1.5)")
.attr("transform-origin",d=>scale * d.xShift + xScale(topics.indexOf(d.field)) + " " +
( -scale * radiusFunc(d.rank) + timeScale(d.dates.split(" -")[0])))
.style("opacity",0.2)
.style("filter",d=> "drop-shadow(0px "+-scale *1.8* radiusFunc(d.rank) +"px " + parseInt(scale * 0.7 * radiusFunc(d.rank)) + "px " + topicColors[topics.indexOf(d.field)] + ")")
chart.selectAll(".bubbleshadow1")
.data(scientists2)
.join("circle")
.attr("cx", (d,i)=> (scale * d.xShift + xScale(topics.indexOf(d.field))))
.attr("cy", d=> ((timeScale(d.dates.split(" -")[0]))))
.attr("r" , d => scale * radiusFunc(d.rank))
.attr("transform","scale(0.7,1)")
.attr("transform-origin",d=>scale * d.xShift + xScale(topics.indexOf(d.field)) + " " +
( -scale * radiusFunc(d.rank) + timeScale(d.dates.split(" -")[0])))
.style("opacity",0.3)
.style("filter",d=> "drop-shadow(0px "+-scale * 1.2 * radiusFunc(d.rank) +"px " + parseInt(scale * 0.7 * radiusFunc(d.rank)) + "px " + topicColors[topics.indexOf(d.field)] + ")")
chart.selectAll(".bubbleBorder")
.data(scientists2)
.join("circle")
.attr("cx", (d,i)=> (scale * d.xShift + xScale(topics.indexOf(d.field))))
.attr("cy", d=> ((timeScale(d.dates.split(" -")[0]))))
.attr("r" , d => scale * radiusFunc(d.rank))
.attr("stroke", d=> topicColors[topics.indexOf(d.field)])
.attr("stroke-width", d=> scale * (0.05 * radiusFunc(d.rank)))
.style("filter",d=> "drop-shadow(0px 0px " + parseInt(scale * 0.7 * radiusFunc(d.rank)) + "px " + topicColors[topics.indexOf(d.field)] + ")")
chart.selectAll(".bubble")
.data(scientists2)
.join("image")
.attr("href", (d,i) => images[i] ? images[i].src : "null")
.attr("width", (d,i) => scale * 2 * radiusFunc(d.rank))
.attr("height", (d,i) =>scale * 2 * radiusFunc(d.rank))
.attr("x", (d,i)=> (scale * (d.xShift - radiusFunc(d.rank)) + xScale(topics.indexOf(d.field))))
.attr("y", d=> (timeScale(d.dates.split(" -")[0]) - scale * radiusFunc(d.rank)))
.attr('clip-path', d => "url(#" + d.name.replaceAll(" ","-") + "-clip" + ")")
chart.selectAll(".nameLabelBG")
.data(scientists2)
.join("text")
.classed("nameLabelBG",true)
.attr("x", (d,i)=> (scale * 2 + scale * (d.xShift) + xScale(topics.indexOf(d.field))))
.attr("y", d => (scale * 18+ timeScale(d.dates.split(" -")[0]) + scale*(radiusFunc(d.rank))))
.text(d => d.name.split(" ").at(-1))
//.text(d => d.dates + ": " + d.name + " " + d.text.replace("PUB_NAME", " "+d.publication))
.attr("fill", "black")
.style("font-family", 'Catamaran, sans-serif')
.style("font-weight", 600)
.style("font-size", scale * 28)
.style("text-anchor","middle");
chart.selectAll(".nameLabel")
.data(scientists2)
.join("text")
.classed("nameLabel",true)
.attr("x", (d,i)=> (scale * d.xShift + xScale(topics.indexOf(d.field))))
.attr("y", d => (scale * 15+ timeScale(d.dates.split(" -")[0]) + scale*radiusFunc(d.rank)))
.text(d => d.name.split(" ").at(-1))
//.text(d => d.dates + ": " + d.name + " " + d.text.replace("PUB_NAME", " "+d.publication))
.attr("fill",d=> topicColors[topics.indexOf(d.field)])
.style("font-family", 'Catamaran, sans-serif')
.style("font-weight", 600)
//.style("font-size", d=> 10 + scale * (0.25 * scale*radiusFunc(d.rank)))
.style("font-size", scale * 28)
.style("text-anchor","middle");
chart.selectAll(".bubbleKey")
.data([[10,1200 - 335,88], [100,1200 - 200,70], [300,1200 - 100,52]])
.join("circle")
.attr("cx", d=> scale * d[1])
.attr("cy", d=> scale * d[2])
.attr("r" , d => scale * radiusFunc(d[0]))
.attr("stroke", "gold")
.attr("stroke-width", d=> scale * (0.025 * radiusFunc(d[0])))
.style("filter",d=> "drop-shadow(0px 0px " + parseInt(scale * 0.7 * radiusFunc(d[0])) + "px " + " gold)")
return svg.node()
}