当我尝试使用D3调整事件大小时,它表明我在图表中附加的元素“ g”在调整大小期间正在重复打印。如何使用this
关键字?或类似的东西?
This is the code on js fiddle。
问题:如何在d3中使用this
关键字解决此问题?
function redraw(){
let chartContainer = document.getElementById("bar_Chart");
let containerWidth = chartContainer.clientWidth;
let containerHeight = chartContainer.clientHeight;
let inputData = [
{name: "JAN", value: 10},
{name: "FEB", value: 8},
{name: "MAR", value: 15},
{name: "APR", value: 16},
{name: "MAY", value: 23},
{name: "JUN", value: 30},
{name: "JUL", value: 12},
{name: "AUG", value: 41},
{name: "SEP", value: 52},
{name: "OCT", value: 23},
{name: "NOV", value: 32},
{name: "DEC", value: 42}
];
let margin = {top: 20, right: 30, bottom: 30, left: 40};
let width = containerWidth - margin.left - margin.right;
let height = containerHeight - margin.top - margin.bottom;
let x = d3.scaleBand()
.rangeRound([0, width])
.padding(0.1);
let y = d3.scaleLinear()
.range([height, 0]);
let tooltip = d3.select("body").append("div").attr("class", "toolTip");
let chart = d3.select(".chart-svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
x.domain(inputData.map(function(d) { return d.name; }));
y.domain([0, d3.max(inputData, function (d) { return d.value; })]);
let xAxis = d3.axisBottom(x);
let yAxis = d3.axisLeft(y);
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
chart.append("g")
.attr("class", "y axis")
.call(yAxis)
chart.selectAll(".bar")
.data(inputData)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.name); })
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.attr("width", x.bandwidth())
.on("mouseover", function (d) {
tooltip.transition()
.duration(200)
.style("opacity", 0.85)
.style("left", d3.event.pageX - 50 + "px")
.style("top", d3.event.pageY - 70 + "px");
tooltip
.style("display", "inline-block")
.html((d.name) + "£" + (d.value));
d3.select(this).transition()
.duration(300)
.style("fill", "red");
})
.on("mouseout", function () {
tooltip.transition()
.duration(200)
.style("opacity", 0);
tooltip
.style("display", "none");
d3.select(this).transition()
.duration(300)
.style("fill", "steelblue")
.style("transition", "scale(1.8)");
});
}
redraw();
window.addEventListener("resize", redraw);
答案 0 :(得分:0)
首次绘制图形时,需要调用enter
将数据绑定到DOM元素,并调用append
创建DOM元素。调整窗口大小时,您不再希望调用enter
或append
,因为数据已经绑定到DOM元素并且DOM元素已经存在。您真正想要做的就是使用attr
调整事物的大小并重新设置轴。
您可以拥有两个函数draw
和redraw
,它们与draw
相同,只是它不调用enter
或append
。我在这里显示它们:
let inputData = [
{name: "JAN", value: 10},
{name: "FEB", value: 8},
{name: "MAR", value: 15},
{name: "APR", value: 16},
{name: "MAY", value: 23},
{name: "JUN", value: 30},
{name: "JUL", value: 12},
{name: "AUG", value: 41},
{name: "SEP", value: 52},
{name: "OCT", value: 23},
{name: "NOV", value: 32},
{name: "DEC", value: 42}
];
let margin = {top: 20, right: 30, bottom: 30, left: 40};
function draw() {
let chartContainer = document.getElementById("bar_Chart");
let containerWidth = chartContainer.clientWidth;
let containerHeight = chartContainer.clientHeight;
let width = containerWidth - margin.left - margin.right;
let height = containerHeight - margin.top - margin.bottom;
let x = d3.scaleBand()
.rangeRound([0, width])
.padding(0.1);
let y = d3.scaleLinear()
.range([height, 0]);
let tooltip = d3.select("body").append("div").attr("class", "toolTip");
let chart = d3.select(".chart-svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
x.domain(inputData.map(function(d) { return d.name; }));
y.domain([0, d3.max(inputData, function (d) { return d.value; })]);
let xAxis = d3.axisBottom(x);
let yAxis = d3.axisLeft(y);
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
chart.append("g")
.attr("class", "y axis")
.call(yAxis)
chart.selectAll(".bar")
.data(inputData)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.name); })
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.attr("width", x.bandwidth())
.on("mouseover", function (d) {
tooltip.transition()
.duration(200)
.style("opacity", 0.85)
.style("left", d3.event.pageX - 50 + "px")
.style("top", d3.event.pageY - 70 + "px");
tooltip
.style("display", "inline-block")
.html((d.name) + "£" + (d.value));
d3.select(this).transition()
.duration(300)
.style("fill", "red");
})
.on("mouseout", function () {
tooltip.transition()
.duration(200)
.style("opacity", 0);
tooltip
.style("display", "none");
d3.select(this).transition()
.duration(300)
.style("fill", "steelblue")
.style("transition", "scale(1.8)");
});
}
function redraw() {
let chartContainer = document.getElementById("bar_Chart");
let containerWidth = chartContainer.clientWidth;
let containerHeight = chartContainer.clientHeight;
let width = containerWidth - margin.left - margin.right;
let height = containerHeight - margin.top - margin.bottom;
let x = d3.scaleBand()
.rangeRound([0, width])
.padding(0.1);
let y = d3.scaleLinear()
.range([height, 0]);
let tooltip = d3.select("body").append("div").attr("class", "toolTip");
let chart = d3.select(".chart-svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
x.domain(inputData.map(function(d) { return d.name; }));
y.domain([0, d3.max(inputData, function (d) { return d.value; })]);
let xAxis = d3.axisBottom(x);
let yAxis = d3.axisLeft(y);
chart.select(".x.axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
chart.select(".y.axis")
.call(yAxis)
chart.selectAll(".bar")
.data(inputData)
.attr("class", "bar")
.attr("x", function(d) { return x(d.name); })
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.attr("width", x.bandwidth())
}
document.addEventListener('DOMContentLoaded', draw);
window.addEventListener("resize", redraw);
仍然存在问题。 X方向与窗口的宽度很好地缩放,但Y方向却不。我相信您不应该在let containerHeight = chartContainer.clientHeight;
函数中使用redraw
,因为它不能正确计算容器元素的高度(无论窗口是增大还是缩小,它都会增加)。我会把这个留给你修复。我改而玩了window.innerHeight
,这似乎效果更好,但是它计算的是窗口的高度,而不是容器div的高度。