data = {
let arr = [];
for (var i = 0; i < 150; i++) {
arr.push({
x: Math.floor(Math.random() * xmax),
y: Math.floor(Math.random() * ymax),
color: Math.floor(Math.random() * 7)
});
}
return arr;
}
width = 1050
height = 500
r = 15
xmax = 400
ymax = 100
sample_y = height - r - 1
margin = ({top: r*2, right: 10, bottom: r, left: 5});
pop = {
var sampleData = [];
const svg = d3.select("#sample-inference-container")
.append("svg").attr("id", "#sample-inference-svg")
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("viewBox", "0 0 " + width + " " + height)
<!-- .attr("width", width).attr("height", height) -->
const sample = svg.append("g").attr("id", "sample-circles")
const circles = svg.append("g").attr("id", "pop-circles")
const arrowData = [{id: -1, points: [[-10,-10],[10,-10],[0,10]]},
{id: 1, points: [[-10,10],[10,10],[0,-10]]}]
let path = {
x: (width*0.5 + xmax*.5 + r),
y: (margin.top + ymax*0.5),
cy: (height - r - (margin.top + ymax*0.5)) * 0.5
};
function generateSample() {
let arr = [];
for (var i = 0; i < 10; i++) {
arr.push(Math.floor(Math.random() * 7))
}
return arr;
}
function drawNewSample() {
sampleData = generateSample();
sample.selectAll("circle").remove()
sample.selectAll("circle")
.data(sampleData)
.enter()
.append("circle")
.attr("fill", d => color(d))
.attr("stroke", "black")
.attr("r", r)
.attr("cx", function(d, i) {return (i * 41.5 + width/2 - xmax/2 + r)})
.attr("cy", 55)
.transition()
.duration(700)
.delay(function(d, i) {return i * 50})
.attr("cy", sample_y);
paths.select("#sample-path")
.attr("stroke-dasharray", len + " " + len).attr("stroke-dashoffset", len)
.transition().duration(900).attr("stroke-dashoffset", 0)
}
function animateArrow() {
arrows.select("#arrow0")
.transition().duration(200)
.attr("transform", d => "translate(" + (width/2 + 315*d.id) + " ," + (path.cy+margin.top+ymax*0.5 - 10) +") scale(2.5)")
.transition().duration(300)
.attr("transform", d => "translate(" + (width/2 + 315*d.id) + " ," + (path.cy+margin.top+ymax*0.5 - 10) +") scale(1.5)")
}
const paths = svg.append("g").attr("id", "paths")
.attr("stroke", "black")
.attr("fill", "none")
.attr("class", "invertable");
const labels = svg.append("g").attr("id", "labels")
.attr("text-anchor", "middle")
.attr("dy", "1em")
.attr("class", "invertable");
const arrows = svg.append("g")
circles.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("fill", d => color(d.color))
.attr("stroke", "black")
.attr("r", 15)
.attr("cx", d => x(d.x))
.attr("cy", d => y(d.y))
svg.append("rect").attr("id", "population-box")
.attr("x", width/2 - xmax/2 - r)
.attr("y", margin.top - r)
.attr("width", xmax + 2*r)
.attr("height",ymax + 2*r)
.style("stroke", "black")
.style("fill", "white")
.style("fill-opacity", 0.9)
.on("mouseover", function(d){d3.select(this).style("fill-opacity", 0.1)})
.on("mouseout", function(d){d3.select(this).style("fill-opacity", 0.9)})
paths.append("path").attr("id", "inference-path")
.attr("d", "M" + path.x + " " + path.y + " q200 " + path.cy + " 0 " + (height - r - path.y))
.attr("stroke-dasharray", [5, 5])
paths.append("path").attr("id", "sample-path")
.attr("d", "M" + (path.x - xmax - 2*r) + " " + path.y + " q-200," + path.cy + " 0 " + (height - r - path.y))
var len = paths.select("#sample-path").node().getTotalLength();
arrows.selectAll("polygon")
.data(arrowData)
.enter().append("polygon")
.attr("points", d => d.points)
.attr("id", function(d,i){return "arrow" + i})
.attr("class", "invertable")
.style("fill", "black")
.attr("transform", d => "translate(" + (width/2 + 315*d.id) + " ," + (path.cy+margin.top+ymax*0.5 - 10) +") scale(1.5)")
svg.select("#arrow0")
.style("touch-action", "manipulation")
.on("mouseover", animateArrow)
.on("click", drawNewSample)
labels.append("text").attr("id", "population-label")
.text("POPULATION")
.attr("x", width/2)
.attr("y", margin.top + ymax + 2*r + 20)
labels.append("text").attr("id", "sample-label")
.text("SAMPLE")
.attr("x", width/2)
.attr("y", sample_y - r - 10)
drawNewSample();
return svg.node();
}
x = d3.scaleLinear()
.domain([0, xmax])
.range([width/2 - xmax/2, width/2 + xmax/2])
y = d3.scaleLinear()
.domain([0, ymax])
.range([margin.top + ymax, margin.top])
color = d3.scaleOrdinal().
domain(data.map(d => d.color))
.range(d3.schemeSet3);