我是d3.js的新手并试图在一页中绘制多个图表,这些图表在-x-轴上都有时间维度。 我希望在缩放页面中的任何图形时对所有图形应用相同的缩放。如何实现这一目标?您可以在此处找到一个可用的示例:Multiple Charts example,我需要在缩放事件功能中进行哪些更改?
var zoom = d3.behavior.zoom()
.scaleExtent([1, 20])
.x(x)
.on('zoom', function zoomHandler() {
axes.select('.x-axis')
.call(xAxis);
circles.attr("transform", function (d) {
return "translate(" + x(d.date) + "," + y(d.measurement) + ")";
});
svg.selectAll('path.line')
.attr('d', function (d) {
return line(d.values);
});
});
答案 0 :(得分:2)
我找到了发布的jsfiddle的解决方案。我在图表函数外部定义了缩放行为,并将svg,circle,line和axes对象保存在相应的列表全局对象中,以便可以在图形创建范围之外访问。最后,我创建了一个setzoom函数,该函数在创建所有图形之后调用,并在svglist数组中进行迭代,并在svglist,circlelist和linelist中保存的每个对象中应用相同的转换。最终的JavaScript代码是:
var timeFormat = d3.time.format('%Y-%m-%d %H:%M:%S');
var customTimeFormat = d3.time.format.multi([
[".%L", function (d) { return d.getMilliseconds(); }],
[":%S", function (d) { return d.getSeconds(); }],
["%H:%M", function (d) { return d.getMinutes(); }],
["%H:%M", function (d) { return d.getHours(); }],
["%d / %m", function (d) { return d.getDay() && d.getDate() != 1; }],
["%d", function (d) { return d.getDate() != 1; }],
["%m - %Y", function (d) { return d.getMonth(); }],
["%Y", function () { return true; }]
]);
var color = d3.scale.category10();
var width = 900,
height = 250,
margin = {
top: 5,
right: 50,
bottom: 20,
left: 80
};
var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S").parse;
var x = d3.time.scale().range([margin.left, width - margin.right]);
var xAxis = d3.svg.axis()
.scale(x)
.tickFormat(customTimeFormat)
.innerTickSize(0)
.outerTickSize(0)
.orient("bottom");
var zoom = d3.behavior.zoom();
var circleslist=[];
var svglist=[];
var axeslist=[];
var ylist=[];
var linelist=[];
function setzoom()
{
zoom.scaleExtent([1, 20])
.x(x)
.on('zoom', function zoomHandler() {
//alert(svglist.length);
for(var i=0;i<3;i++)
{
axeslist[i].select('.x-axis')
.call(xAxis);
circleslist[i].attr("transform", function (d) {
return "translate(" + x(d.date) + "," + ylist[i](d.measurement) + ")";
});
svglist[i].selectAll('path.line')
.attr('d', function (d) {
return linelist[i](d.values);
});
}
});
}
var chartValuesList1 = [{ Date: "2018-01-29 11:47:09", Measurement: 225 },
{ Date: "2018-01-29 12:47:09", Measurement: 225 },{ Date: "2018-01-29 13:47:13", Measurement: 224 },{ Date: "2018-01-29 14:47:13", Measurement: 225 },{ Date: "2018-01-29 15:47:10", Measurement: 223 },
{ Date: "2018-01-29 16:47:11", Measurement: 223 }];
var Array1 = [{ name: "Plot1", units: "", chartValuesList:chartValuesList1 }];
var chartValuesList2 = [{ Date: "2018-01-29 11:47:09", Measurement: 225 },
{ Date: "2018-01-29 12:47:09", Measurement: 225 },{ Date: "2018-01-29 13:47:13", Measurement: 224 },{ Date: "2018-01-29 14:47:13", Measurement: 200 },{ Date: "2018-01-29 15:47:10", Measurement: 233 },
{ Date: "2018-01-29 16:47:11", Measurement: 240 }];
var Array2 = [{ name: "Plot2", units: "", chartValuesList:chartValuesList2 }];
var chartValuesList3 = [{ Date: "2018-01-29 11:47:09", Measurement: 225 },
{ Date: "2018-01-29 12:47:09", Measurement: 550 },{ Date: "2018-01-29 13:47:13", Measurement: 600 },{ Date: "2018-01-29 14:47:13", Measurement: 400 },{ Date: "2018-01-29 15:47:10", Measurement: 300 },
{ Date: "2018-01-29 16:47:11", Measurement: 600 }];
var Array3 = [{ name: "Plot3", units: "", chartValuesList:chartValuesList3 }];
chart("chart1", Array1, "Values");
chart("chart2", Array2, "Values");
chart("chart3", Array3, "Values");
setzoom();
function chart(chartID, chartData, heading) {
var y = d3.scale.linear().range([height - margin.bottom, margin.top]);
ylist.push(y);
var yAxis = d3.svg.axis()
.scale(y)
.tickFormat(function (d) { return d; })
.innerTickSize(-(width - margin.left - margin.right))
.outerTickSize(0)
.orient("left");
var data = chartData;
var line = d3.svg.line()
.interpolate("linear")
.x(function (d) { return x(d.date); })
.y(function (d) { return y(d.measurement); });
linelist.push(line);
var container = d3.select("#" + chartID);
var svg = container.append("svg")
.attr('width', width)
.attr('height', height);
svglist.push(svg);
var defs = svg.append('defs');
defs.append('clipPath')
.attr('id', 'plot-area-clip-path')
.append('rect')
.attr({
x: margin.left,
y: margin.top,
width: width - margin.right - margin.left,
height: height - margin.top - margin.bottom
});
var backRect = svg.append('rect')
.style('stroke', 'none')
.style('fill', '#FFF')
.style('fill-opacity', 0)
.attr({
x: margin.left,
y: margin.top,
width: width - margin.right - margin.left,
height: height - margin.top - margin.bottom,
'pointer-events': 'all'
});
axes = svg.append('g')
.attr('pointer-events', 'none')
.style('font-size', '11px');
axeslist.push(axes);
var chart = svg.append('g')
.attr('class', 'plot-area')
.attr('pointer-events', 'none')
.attr('clip-path', 'url(#plot-area-clip-path)');
var dates = [];
var measurements = [];
var dateStrings = [];
var units;
var chartLines = data.map(function (chartLine) {
units = chartLine.units;
return {
name: chartLine.name,
units: chartLine.units,
values: chartLine.chartValuesList.map(function (value) {
dateStrings.push(value.Date);
var date = parseDate(value.Date);
var measurement = value.Measurement;
dates.push(date);
measurements.push(measurement);
return {
date: date,
measurement: measurement
};
})
}
});
x.domain(d3.extent(dates));
if (chartID == "charge-chart" || chartID == "genBattVdc-chart") {
var max = d3.max(measurements);
y.domain([0, max + (0.1 * max)]);
}
// else if (chartID == "powerFact_g-chart") {
// y.domain([-1.2, 1.2]);
// }
//energy-chart
else if (chartID == "energy-chart") {
y.domain(d3.extent(measurements));
}
else {
//y.domain(d3.extent(measurements));
y.domain([d3.min(measurements) - 0.01 * d3.min(measurements), 1.01 * d3.max(measurements)]);
}
var xAxisEl = axes.append('g')
.attr('class', 'x-axis')
.attr('transform', 'translate(' + 0 + ',' + (height - margin.bottom) + ')')
.call(xAxis);
var yAxisEl = axes.append('g')
.attr('class', 'y-axis')
.attr('transform', 'translate(' + margin.left + ',' + 0 + ')')
.call(yAxis);
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 20)
.attr("x", -height / 2)
.attr("dy", "1em")
.style("text-anchor", "middle")
.text((units == "") ? "" : "( " + units + " )");
backRect.call(zoom);
yAxisEl.selectAll('line')
.style('stroke', '#BBB')
.style('stroke-width', '1px')
.style('shape-rendering', 'crispEdges');
var chartLine = chart.selectAll(".chartLine")
.data(chartLines)
.enter().append("g")
.attr("class", "chartLine");
var paths = chart.selectAll(".chartLine").append("g")
.attr("class", "plot")
.attr("id",
function (d, i) {
return 'tag' + d.name.replace(/\s+/g, '');
})
.append("path")
.attr("class", "line")
.attr("d", function (d) {
return line(d.values);
})
.style("stroke", function (d, i) {
return color(i);
});
/* Title and Legends */
var chartInfo = container.append('svg')
.attr("class", "title")
.attr("x", width + 65)
.attr("y", 50)
.attr("height", height)
.attr("width", 200);
var title = chartInfo.append('svg')
.attr("class", "title")
.attr('width', 200)
.attr('height', 40)
.attr("x", 10)
.attr("y", 0)
.append('g')
.append("text")
.attr("x", 0)
.attr("y", 30)
.attr("height", 30)
.attr("width", 200)
.attr("text-anchor", "start")
.style("font-size", "16px")
.style("font-weight", "bold")
.style("fill", "rgb(128,128,128)")
.text(heading);
var legends = chartInfo.append('svg')
.attr("class", "legend")
.attr('width', 200)
.attr('height', height - 40)
.attr("x", 10)
.attr("y", 60);
legends.selectAll('g').data(chartLines)
.enter()
.append('g')
.each(function (d, i) {
var g = d3.select(this);
g.append("rect")
.attr("x", 10)
.attr("y", i * 25)
.attr("width", 10)
.attr("height", 10)
.style("fill", color(i));
g.append("text")
.attr("x", 30)
.attr("y", i * 25 + 10)
.attr("height", 30)
.attr("width", 100)
.style("fill", color(i))
.on("click", function () {
(!d.active) ? $(this).attr("opacity", 0.3) : $(this).attr("opacity", 1);
var active = d.active ? false : true,
newOpacity = active ? 0 : 1;
d3.select('#tag' + d.name.replace(/\s+/g, ''))
.transition().duration(100)
.style('opacity', newOpacity);
d.active = active;
})
.text(d.name);
});
/* Dots */
var circles = chart.selectAll(".chartLine").select('.plot').append('g')
.attr("class", "dots")
.selectAll('circle')
.data(function (d) { return d.values; })
.enter().append('circle')
// .attr('cy', function(d){
// return y(d.measurement);
// })
// .attr('cx', function(d){
// return x(d.date);
// })
.attr("transform", function (d) {
return "translate(" + x(d.date) + "," + y(d.measurement) + ")";
})
.attr('r', 1)
.attr('fill', 'black')
.attr('pointer-events', 'all')
.attr('stroke', 'black')
.attr('stroke-width', 1)
.on("mouseover", mouseover)
.on("mousemove", function (d) {
var aa = new Date(d.date);
var h = aa.getHours();
var m = aa.getMinutes();
var s = aa.getSeconds();
var t = h + ":" + m + ":" + s;
console.log(aa, t)
divToolTip.text(this.parentNode.__data__.units + ": " + d.measurement + ", " + "Time: " + t)
.style("left", (d3.event.pageX + 15) + "px")
.style("top", (d3.event.pageY - 10) + "px");
})
.on("mouseout", mouseout);
circleslist.push(circles);
/* Tooltip */
var divToolTip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 1e-6);
function mouseover() {
divToolTip.transition()
.duration(100)
.style("opacity", 1);
}
function mouseout() {
divToolTip.transition()
.duration(100)
.style("opacity", 1e-6);
}
}