我使用d3显示几个等效折线图,我使用单个chart()
功能构建,接受所有图表数据。
chart()
函数根据需要调用此draw()
函数,该函数遍历页面上的所有占位符图表元素。
我希望在调整视口大小时重绘所有图表。因此,为此,我使用d3.select("svg").remove();
删除现有图表,然后再次调用draw()
函数。
不幸的是,当重新绘制图表时,并非所有元素都是正确的 - 我的路径不会出现(尽管它出现在标记中),而其他一些圆形对象也没有显示)。我不知道为什么会这样。
请参阅我创建的codepen。另外,这是相关代码:
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
var data = [], promos = [], stocks = [], start = [], end = [];
data['chart-7114'] = [{"date":"2017-08-14","value":"5.0000"},{"date":"2017-08-16","value":"5.0000"},{"date":"2017-08-17","value":"5.0000"},{"date":"2017-08-24","value":"5.0000"},{"date":"2017-08-31","value":"5.0000"},{"date":"2017-09-13","value":"5.0000"},{"date":"2017-09-14","value":"5.0000"},{"date":"2017-09-25","value":"6.4500"},{"date":"2017-09-26","value":"6.4500"},{"date":"2017-09-27","value":"6.4500"},{"date":"2017-09-28","value":"6.4500"}];
promos['chart-7114'] = [{"start_date":"2017-08-14","end_date":"2017-08-16"},{"start_date":"2017-08-24","end_date":"2017-08-24"},{"start_date":"2017-09-13","end_date":"2017-09-14"}];
stocks['chart-7114'] = [{"start_date":"2017-08-16","end_date":"2017-08-16"},{"start_date":"2017-09-14","end_date":"2017-09-14"},{"start_date":"2017-09-26","end_date":"2017-09-26"}];
start['chart-7114'] = "2017-08-14";
end['chart-7114'] = "2017-09-28";
$(document).ready(function() {
function chart(selector, data, promos, stocks, start, end) {
var margin = {top: 20, right: 20, bottom: 30, left: 60},
width = $(selector).width() - margin.left - margin.right,
height = $(selector).height() - margin.top - margin.bottom;
var svg = d3.select(selector).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var parseDate = d3.timeParse("%Y-%m-%d"),
formatDate = d3.timeFormat("%Y"),
formatDate2 = d3.timeFormat("%d/%m/%Y");
var x = d3.scaleTime()
.domain([parseDate(start), parseDate(end)])
.range([0, width]);
var y = d3.scaleLinear()
.range([height, 0]);
var xAxis = d3.axisBottom(x);
var yAxis = d3.axisLeft(y);
var area = d3.line()
.curve(d3.curveLinear)
.y(function(d) { return y(d.value); });
var areaPath = g.append("path")
.attr('class', 'line')
.attr("clip-path", "url(#clip)");
var yGroup = g.append("g");
var xGroup = g.append("g")
.attr("transform", "translate(0," + height + ")");
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "Date: " + formatDate2(d.date) + "<br>Price: £" + d.value;
});
g.call(tip);
var promoHighlights = g.selectAll('.promo')
.data(promos)
.enter().append("rect")
.attr('class', 'promo' )
.style("pointer-events","all")
.attr("height", height);
var stockHighlights = g.selectAll('.nostock')
.data(stocks)
.enter().append("rect")
.attr('class', 'nostock' )
.style("pointer-events","all")
.attr("height", height);
var zoom = d3.zoom()
.scaleExtent([1 / 4, 8])
.translateExtent([[-width, -Infinity], [2 * width, Infinity]])
.on("zoom", zoomed);
var zoomRect = g.append("rect")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("fill", "none")
.attr("pointer-events", "all")
.call(zoom);
var toolTips = g.selectAll("circle")
.data(data).enter()
.append("circle")
.attr("r", 4)
.style("pointer-events","all")
.on('mouseover', function(d, e) {
tip.show(d);
d3.select(this).attr('r', 8);
})
.on('mouseout', function(d, e) {
tip.hide(d);
d3.select(this).attr('r', 4);
});
g.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
data.forEach(function(d) {
d.date = parseDate(d.date);
d.value = +d.value;
});
var xExtent = d3.extent(data, function(d) { return d.date; });
zoom.translateExtent([[x(xExtent[0]), -Infinity], [x(xExtent[1]), Infinity]]);
y.domain([0, d3.max(data, function(d) { return d.value; })+1]);
yGroup.call(yAxis).select(".domain").remove();
areaPath.datum(data);
zoomRect.call(zoom.transform, d3.zoomIdentity);
toolTips.attr("cy", function(d) { return y(d.value); });
function zoomed() {
var xz = d3.event.transform.rescaleX(x);
xGroup.call(xAxis.scale(xz));
areaPath.attr("d", area.x(function(d) { return xz(d.date); }));
toolTips.attr("cx", function(d) { return xz(d.date); });
promoHighlights.attr("x", function(d) { return xz(parseDate(d.start_date)); })
.attr("width", function(d) {
if(d.end_date != d.start_date) {
//console.log(parseDate(d.end_date));
return xz(parseDate(d.end_date))-xz(parseDate(d.start_date));
}
else {
return xz(d3.timeDay.offset(parseDate(d.end_date)))-xz(parseDate(d.start_date));
}
});
stockHighlights.attr("x", function(d) {
return xz(parseDate(d.start_date));
})
.attr("width", function(d) {
if(d.end_date != d.start_date) {
//console.log(parseDate(d.end_date));
return xz(parseDate(d.end_date))-xz(parseDate(d.start_date));
}
else {
return xz(d3.timeDay.offset(parseDate(d.end_date)))-xz(parseDate(d.start_date));
}
});
}
}
function draw() {
$('.chart').each(function() {
chart_id = $(this).attr('id');
chart('#'+$(this).attr('id'), data[chart_id], promos[chart_id], stocks[chart_id], start[chart_id], end[chart_id]);
});
}
if($('.chart').length > 0) {
draw();
$(window).resize(debounce(function(){
d3.select("svg").remove();
draw();
},100));
}
});
答案 0 :(得分:0)
您必须查看此示例。 code on jsbin
function render() {
updateDimensions(window.innerWidth);
x.range([0, width]);
y.range([height, 0]);
svg
.attr('width', '100%')
.attr('height', height + margin.top + margin.bottom);
fh = svg.style("height").replace("px", "");
fw = svg.style("width").replace("px", "");
chartWrapper
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
xAxis.scale(x);
yAxis.scale(y);
if(window.innerWidth < wbreakPoint) {
xAxis.ticks(d3.timeHour.every(12))
}
else {
xAxis.ticks(d3.timeHour.every(5))
};
if(window.innerinnerHeight < hbreakPoint) {
yAxis.ticks(Math.max(height/50, 2))
}
else {
yAxis.ticks(Math.max(height/50, 2));
};
svg.select('.x.axis')
.attr('transform', 'translate(0,' + height + ')')
.transition()
.duration(200)
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", "rotate(-50)" );
svg.select('.y.axis')
.transition()
.duration(200)
.call(yAxis);
chartWrapper.select("text")
.attr("x", (fw / 2))
.attr("y", 0 - (margin.top / 2))
.attr("text-anchor", "middle");
path
.transition()
.duration(1000)
.attr('d', d => lineGen(d.Data))
.attr("stroke-width", 3)
.attr("fill", "none")
.attr("stroke", (d, i) => colors(i));
groups.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
groups
.transition()
.duration(1000);}
function updateDimensions(winWidth) {
margin.top = 40;
margin.right = winWidth < wbreakPoint ? 50 : 80;
margin.left = winWidth < wbreakPoint ? 30 : 50;
margin.bottom = 100;
width = winWidth - margin.left - margin.right;
height = .1 * width;}
return {render : render}
})(window,d3);
window.addEventListener('resize', Chart.render);
只需删除一些字符串以便更好地理解
var inter = setInterval(function() {
updateData(jsont1);
或者查看this link with responsive scatterplot
希望有所帮助
答案 1 :(得分:0)
我最终确定了这个问题 - 就是这个循环:
data.forEach(function(d) {
d.date = parseDate(d.date);
d.value = +d.value;
});
基本上,这是更新数组中的日期值。因为它是chart()
函数的一部分,所以它试图两次处理日期,然后有效地将它们的值更改为null
- 并打破数据。