为了具有响应性的D3多折线图,我添加了一个调整大小的功能,尽管该功能被调用,但它似乎不起作用:
var data = [{
Date: "2016-10-10",
ValueOne: 1,
ValueTwo: 0
}, {
Date: "2016-10-17",
ValueOne: 23,
ValueTwo: 2
}, {
Date: "2016-10-24",
ValueOne: 32,
ValueTwo: 17
}, {
Date: "2016-10-31",
ValueOne: 57,
ValueTwo: 40
}, {
Date: "2016-11-07",
ValueOne: 74,
ValueTwo: 56
}];
var margin = {top: 10, right: 50, bottom: 100, left: 50},
// Set default width and height
widther = (window.innerWidth),
width = widther - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// Determine current size, which determines vars
function set_vars() {
var width = window.innerWidth - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
}
function drawGraphic() {
var svg = d3.select('#charts')
.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 + ")");
//Parses date for correct time format
var formatTime = d3.timeFormat("%Y-%m-%d");
data.forEach(function(d) {
d.Date = new Date(d.Date)
});
var valueOneData = data.map(function(d) {
return {
date: d.Date,
value: d.ValueOne
}
});
var valueTwoData = data.map(function(d) {
return {
date: d.Date,
value: d.ValueTwo
}
});
var xScale = d3.scaleTime()
.range([0, width])
.domain(d3.extent(data, function(d) {
return d.Date
}));
var yScale = d3.scaleLinear()
.range([height, 0])
.domain([0, d3.max(data, function(d) {
return d.ValueOne
}) * 1.05]);
var lineGenerator = d3.line()
.x(function(d) {
return xScale(d.date)
})
.y(function(d) {
return yScale(d.value)
});
var gX = svg.append("g")
.attr("transform", `translate(0,${height})`)
.call(d3.axisBottom(xScale).tickFormat(function(d) {
return formatTime(d)
}).tickValues(data.map(function(d) {
return d.Date
})))
.selectAll("text")
.style("text-anchor", "end")
.attr("transform", "rotate(-65)")
.attr("y", 4)
.attr("x", -10)
.attr("dy", ".35em");
var gY = svg.append("g")
.call(d3.axisLeft(yScale));
var valueOneLine = svg.append("path")
.datum(valueOneData)
.attr("d", lineGenerator)
.style("fill", "none")
.style("stroke", "#124");
var valueTwoLine = svg.append("path")
.datum(valueTwoData)
.attr("d", lineGenerator)
.style("fill", "none")
.style("stroke", "#c7003b");
//RESPONSIVENESS ATTEMPT NO1
d3.select(window).on("resize", resized);
}
//Resize function
function resized() {
d3.select("svg").remove();
set_vars();
drawGraphic();
console.log("FUNCTION IS BEING CALLED")
}
set_vars();
drawGraphic();
//RESPONSIVENESS ATTEMPT NO2
window.addEventListener("resize", function(){ d3.select("svg").remove(); set_vars(); drawGraphic(); });
<script src="https://d3js.org/d3.v4.min.js"></script>
<div id="charts"></div>
在代码段中,我尝试了两种方法来做到这一点。他们都没有使图表从头开始重新创建。此jsfiddle中也存在相同的问题。
答案 0 :(得分:1)
问题在于每次调整窗口大小时都会解析数据。
第一次解析数据中的日期时,调用parseDate(d.date)
的其他所有调用都会失败,因为它已经被解析为有效日期。你懂吗?
因此,移动解析代码,使其仅执行一次:
// parse data just once
data.forEach(function(d) {
d.date = parseDate(d.date);
d.value = +d.value;
});
中部链接:https://jsfiddle.net/a5rqt0L1/
建议:我觉得这不是制作响应式图表的正确方法,例如,删除SVG并重新添加到主体,并且所有配置都要进行多次。这是我的处理方式:
drawBars
(绘制实际的条形图)移动到将使用的单独函数d3自己的输入,退出和更新选择逻辑。.call(xAxis)...
重新渲染轴,然后调用drawBars
函数即可。 希望这会有所帮助。