chart = (dataset) => {
const hXBrush = 40
, wYBrush = 40
, mYBrush = {t: 10, b: 15, l: 40, r: 10}
, mXBrush = {t: 10, b: 20, l: 0, r: 10}
const wSVG = width + margin.left + margin.right + wYBrush + mYBrush.l + mYBrush.r
, hSVG = height + margin.top + margin.bottom + hXBrush + mXBrush.t + mXBrush.b
const svg = d3.select(DOM.svg(wSVG,hSVG))
const scatterplot = svg.append("g")
.attr('transform', `translate(${margin.left + mYBrush.l + mYBrush.r + wYBrush}, ${margin.top})`);
const clip = DOM.uid("clip")
scatterplot.append("defs")
.append("clipPath")
.attr("id", clip.id)
.append("rect")
.attr("width", width)
.attr("height", height - hXBrush);
const xScale = d3.scalePoint()
.domain(Object.values(known_ips_map))
.range([50, width]);
const xAxis = scatterplot.append("g")
.attr("class", "x axis")
.attr("transform", `translate(0, ${height - hXBrush})`)
.call(d3.axisBottom(xScale)
.ticks(Object.values(known_ips_map).length))
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", "rotate(-65)");
const portRange = [0, 65530];
const yScale = d3.scaleLinear()
.range([height - hXBrush, 0])
.domain(portRange);
const yAxis = scatterplot.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(yScale));
const circles = scatterplot.selectAll("circle")
.data(dataset)
.join("circle")
.attr("clip-path", clip)
.attr("cx", d => xScale(ipaddress_map[d["SrcAddr"]]))
.attr("cy", d => yScale(d["Sport"]))
.attr("r", 5)
.style("fill-opacity", 1)
.style("fill", d => {
return "steelblue"
});
const contextX = svg.append("g")
.attr("class", "context")
.attr("transform",
`translate(${wYBrush + margin.left + mXBrush.l + mYBrush.l + mYBrush.r},${height + margin.top + margin.bottom + mXBrush.t})`);
const xXScaleBrush =
d3.scalePoint()
.range([0, width])
.domain(Object.values(known_ips_map))
xXScaleBrush.invert = (function(){
var domain = xXScaleBrush.domain()
var range = xXScaleBrush.range()
var scale = d3.scaleQuantize().domain(range).range(domain)
return function(x){
return scale(x)
}
})()
const yXScaleBrush = d3.scaleLinear()
.range([hXBrush, 0])
.domain(d3.extent(dataset, d => d["Sport"]));
function brushedX({selection}) {
console.log(selection)
let extent = selection.map(xXScaleBrush.invert, xXScaleBrush);
console.log("Extent");
console.log(extent);
xScale.domain(extent);
circles.attr("cx", d => xScale(ipaddress_map[d["SrcAddr"]]))
xAxis.call(d3.axisBottom(xScale));
}
const brushX = d3.brushX().extent([[0, 0],[width, hXBrush]]).on("brush", brushedX);
contextX.append("g")
.attr("class", "x axis")
.attr("transform", `translate(0,${hXBrush})`)
.call(d3.axisBottom(xXScaleBrush));
contextX.selectAll("circle")
.data(dataset)
.join("circle")
.style("fill", "#555")
.attr("r", 2)
.attr("cx", d => xScale(ipaddress_map[d["SrcAddr"]]))
.attr("cy", d => yXScaleBrush(d["Sport"]))
contextX.append("g")
.attr("class", "x brush")
.call(brushX);
const contextY = svg.append("g")
.attr("class", "context")
.attr("transform", `translate(${mYBrush.l},${margin.top})`);
const yYScaleBrush = d3.scaleLinear()
.range([height - margin.top - margin.bottom, 0])
.domain(portRange);
const xYScaleBrush = d3.scalePoint()
.range([0, wYBrush])
.domain(Object.values(known_ips_map))
function brushedY({selection}) {
let extent = selection.map(yYScaleBrush.invert, yYScaleBrush);
yScale.domain([extent[1], extent[0]]);
circles.attr("cy", d => yScale(d["Sport"]))
yAxis.call(d3.axisLeft(yScale));
}
const brushY = d3.brushY().extent([[0, 0],[wYBrush, height - hXBrush]]).on("brush", brushedY);
contextY.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(yYScaleBrush));
contextY.selectAll("circle")
.data(dataset)
.join("circle")
.style("fill", "#555")
.attr("r", 2)
.attr("cy", d => yScale(d["Sport"]))
.attr("cx", d => xYScaleBrush(ipaddress_map[d["SrcAddr"]]))
contextY.append("g")
.attr("class", "y brush")
.call(brushY);
return svg.node()
}