Я пытаюсь реализовать масштабирование и панорамирование на d3 с помощью javascript. Кажется, что линии и круги нарисованы за пределами области, которую я хотел бы, чтобы они просто появились. У меня проблемы с визуализацией, что может быть не так. Вот все js.
(()=> {
// set the dimensions and margins of the graph
var margin = {top: 30, right: 30, bottom: 70, left: 60},
width = 400 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom
tipDelvs = d3.tip()
.attr('class', 'd3-tip')
.offset([-5, 0])
.html(function(d) { return "DAY: " + d.DIA + "<br/>PO: " + d.PO_ID})
tipOpen = d3.tip()
.attr('class', 'd3-tip')
.offset([-5, 0])
.html(function(d) { return "DAY: " + d.DIA + "<br/>PO: " + d.PO_ID})
var files = ["url1", 'url2'];
var promises = [];
files.forEach(function(url) {
promises.push(d3.json(url))
});
Promise.all(promises).then(function(data) {
tipAvgDelvs = d3.tip()
.attr('class', 'd3-tip')
.offset([-5, 0])
.html(function(d) { return "AVG DELVS: " + Math.floor(data[1].DailyDelvs)})
d3.select("#dailyDeliveryVolume_spinner").remove();
var maxY = d3.max(data[0].STD2, function(d) { return +d.PO_ID })
var dias = []
for(i = 1; i<=data[0].STD2[0].LAST_DAY; i++){
dias.push(i)
}
var maxX = d3.max(dias, d => {return d})
var finalSTD = [] // has data
var tempOpen = []
var a = [], b = [], prev;
var finalOpen = [] // has data
var x = d3.scaleLinear()
.domain([1, maxX])
.range([ 0, width ])
//.padding(0.05);
var xAxis = d3.axisBottom(x)
//.tickValues(x.domain().filter(function(d,i){ return !(i%2)}));
var y = d3.scaleLinear()
.domain([0, maxY])
.range([ height, 0]);
var yAxis = d3.axisLeft(y)
// Set the zoom and Pan features: how much you can zoom, on which part, and what to do when there is a zoom
var zoom = d3.zoom()
.scaleExtent([1, 3]) // This control how much you can unzoom (x0.5) and zoom (x20)
.extent([[x(1), y(maxY)], [x(maxX), y(0)]])
.translateExtent([[x(1), 0], [x(maxX), y(0)]])
.on("zoom", updateChart);
// append the svg object to the body of the page
var svg = d3.select("#dailyDeliveryVolume")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")")
.call(tipDelvs)
.call(tipOpen)
.call(zoom)
// now the user can zoom and it will trigger the function called updateChart
var gX = svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
var gY = svg.append("g")
.call(yAxis)
// Add a clipPath: everything out of this area won't be drawn.
var clip = svg.append("defs").append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("width", width )
.attr("height", height )
.attr("x", 0)
.attr("y", 0);
// This add an invisible rect on top of the chart area. This rect can recover pointer events: necessary to understand when the user zoom
svg.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all")
//.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
// Create the scatter variable: where both the circles and the brush take place
var scatter = svg.append('g')
.attr("clip-path", "url(#clip)")
var lineDelvs = d3.line()
.x(function(d) { return x(d.DIA); })
.y(function(d) { return y(+d.PO_ID); })
// Bars
scatter.attr("class", "scatter").append("path")
//.datum(data[0].STD2)
.datum(finalSTD)
.attr('class', 'line')
.attr("fill", "none")
.attr("stroke", "lightgreen")
.attr("stroke-width", 1.5)
.attr("d", lineDelvs)
scatter.selectAll(".circle")
//.data(data[0].STD2)
.data(finalSTD)
.enter()
.append("svg:circle")
.attr("class", "circle")
.attr("fill", "lightgreen")
.attr("cx", function (d, i) {return x(d.DIA);})
.attr("cy", function (d, i) {return y(d.PO_ID);})
.attr("r", 5)
.on('mouseover', tipDelvs.show)
.on('mouseout', tipDelvs.hide)
var lineOpen = d3.line()
.x(function(d) { return x(d.DIA); })
.y(function(d) { return y(+d.PO_ID); })
scatter.append("path")
//.datum(data[0].OPEN2)
.datum(finalOpen)
.attr('class', 'line')
.attr("fill", "none")
.attr("stroke", "white")
.attr("stroke-width", 1.5)
.attr("d", lineOpen)
scatter.selectAll(".circule")
//.data(data[0].OPEN2)
.data(finalOpen)
.enter()
.append("svg:circle")
.attr("class", "circle")
.attr("fill", "lightgrey")
.attr("cx", function (d, i) {return x(d.DIA);})
.attr("cy", function (d, i) {return y(d.PO_ID);})
.attr("r", 5)
.on('mouseover', tipOpen.show)
.on('mouseout', tipOpen.hide)
var deltaTemp = []
//for (i=0; i<data[0].STD2.length; i++){
// deltaTemp.push(data[0].STD2[i].PO_ID - data[0].OPEN2[i].PO_ID)
for (i=0; i<finalSTD.length; i++){
deltaTemp.push(finalSTD[i].PO_ID - finalOpen[i].PO_ID)
}
const average = arr => arr.reduce( ( p, c ) => p + c, 0 ) / arr.length;
var delta = average(deltaTemp)
tipAvgDelta = d3.tip()
.attr('class', 'd3-tip')
.offset([-5, 0])
.html(function(d) { return "AVG DELTA: " + Math.floor(delta)})
svg = d3.select("#dailyDeliveryVolume").select('g').call(tipAvgDelta).call(tipAvgDelvs)
scatter.append('line')
.attr('class', 'line')
.style('stroke', 'lightcoral')
.attr('x1', x(0))
.attr('y1', y(data[1].DailyDelvs))
.attr('x2', x(data[0].STD2[0].LAST_DAY))
.attr('y2', y(data[1].DailyDelvs))
scatter.append('circle')
.attr("class", "circle")
.attr("fill", "coral")
.attr('cx', x(data[0].STD2[0].LAST_DAY))
.attr('cy', y(data[1].DailyDelvs))
.attr("r", 5)
.on("mouseover", tipAvgDelvs.show)
.on("mouseleave", tipAvgDelvs.hide)
scatter.append('line')
.attr('class', 'line')
.style('stroke', 'yellow')
.attr('x1', x(0))
.attr('y1', y(delta))
.attr('x2', x(data[0].STD2[0].LAST_DAY))
.attr('y2', y(delta))
scatter.append('circle')
.attr("class", "circle")
.attr("fill", "lightyellow")
.attr('cx', x(data[0].STD2[0].LAST_DAY))
.attr('cy', y(delta))
.attr("r", 5)
.on("mouseover", tipAvgDelta.show)
.on("mousemove", tipAvgDelta.show)
.on("mouseleave", tipAvgDelta.hide)
// A function that updates the chart when the user zoom and thus new boundaries are available
function updateChart() {
svg.selectAll(".scatter")
.attr("transform", d3.event.transform);
d3.selectAll('.line').style("stroke-width", 2/d3.event.transform.k);
gX.call(xAxis.scale(d3.event.transform.rescaleX(x)));
gY.call(yAxis.scale(d3.event.transform.rescaleY(y)));
}
svg.append("text")
.text("Delivered")
.attr("fill", "lightgreen")
.attr("x", 240)
.attr("y", 30)
svg.append("text")
.text("New")
.attr("fill", "white")
.attr("x", 240)
.attr("y", 45)
})
})()
Я скопировал детали и детали из разных реализаций, чтобы получить окончательный результат
Однако логика c для масштабирования и панорамирования работает не так, как я ожидал.
Все элементы go вне Прямоугольник, который, как я полагал, был тем местом, куда я их добавлял. Я попытался изменить пару вещей, таких как добавление прямых строк и окружностей в клип или добавление событий указателя в разброс, но это просто попытки без реального знания.
Когда я проверяю страницу, пределом является svg. Я звоню в zoom на svg: g, но не уверен, что это как-то связано с этим. Тем не менее, я попытался вызвать zoom на 'rect', но у меня были те же результаты.
Любая помощь будет высоко ценится. Спасибо