我想将多个图表的缩放和平移控制链接在一起,以便在其中一个图表平移和缩放控件启用时它们全部平移和缩放。
我尝试创建一个缩放对象并将其传递给图表,但只有最后一个图表实际上是平移和缩放的。其他人保持静止,即使我在他们的区域放大。
这是图表的快照。每个图表都有一个概览图表,其中包含一个可以移动的视口。我想将所有控件链接在一起,因此每个图表上的视口也是相同的。
那么,如何在多个图表上链接平移和缩放控件?
以下是此代码的jsfiddle:https://jsfiddle.net/babazaroni/a52oukzn/
这是我的代码:
整体图表创建者。此代码生成3个图表。
define([
'd3',
'components/sl',
'MockData',
'components/candlestickSeries',
'Chart'
], function (d3, sl, MockData,candlestickSeries,Chart) {
'use strict';
function generateData()
{
var data = new MockData(0.1, 0.1, 100, 50, function (moment) {
return !(moment.day() === 0 || moment.day() === 6);
})
.generateOHLC(new Date(2014, 1, 1), new Date(2014, 8, 1));
return data;
}
var data = generateData();
d3.select('#chart1')
.datum(data)
.call(Chart());
data = generateData();
d3.select('#chart1')
.datum(data)
.call(Chart());
data = generateData();
d3.select('#chart1')
.datum(data)
.call(Chart());
});
这是图表代码:
define([
'd3',
'components/sl',
'MockData',
'components/candlestickSeries'
], function (d3, sl, MockData) {
'use strict';
function timeSeriesChart() {
function chart(selection)
{
selection.each(function(data) {
var minDate = new Date(d3.min(data, function (d) { return d.date; }).getTime() - 8.64e7);
var maxDate = new Date(d3.max(data, function (d) { return d.date; }).getTime() + 8.64e7);
var yMin = d3.min(data, function (d) { return d.low; });
var yMax = d3.max(data, function (d) { return d.high; });
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// The primary chart
// Set up the drawing area
var margin = {top: 20, right: 20, bottom: 30, left: 35},
width = 600 - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
var plotChart = d3.select(this).classed('chart', true).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 + ')');
var plotArea = plotChart.append('g')
.attr('clip-path', 'url(#plotAreaClip)');
plotArea.append('clipPath')
.attr('id', 'plotAreaClip')
.append('rect')
.attr({ width: width, height: height });
// Scales
var xScale = d3.time.scale(),
yScale = d3.scale.linear();
// Set scale domains
xScale.domain([minDate, maxDate]);
yScale.domain([yMin, yMax]).nice();
// Set scale ranges
xScale.range([0, width]);
yScale.range([height, 0]);
// Axes
var xAxis = d3.svg.axis()
.scale(xScale)
.orient('bottom')
.ticks(10);
var yAxis = d3.svg.axis()
.scale(yScale)
.orient('left');
plotChart.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis);
plotChart.append('g')
.attr('class', 'y axis')
.call(yAxis);
plotChart.append("text")
.attr("x", (width / 2))
.attr("y", 1 - (margin.top / 2))
.attr("text-anchor", "middle")
.style("font-size", "16px")
.style("text-decoration", "underline")
.text("Your title goes here");
// Data series
var series = sl.series.candlestick()
.xScale(xScale)
.yScale(yScale);
var dataSeries = plotArea.append('g')
.attr('class', 'series')
.datum(data)
.call(series);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Navigation chart
var navWidth = width,
navHeight = 100 - margin.top - margin.bottom;
// Set up the drawing area
var navChart = d3.select(this).classed('chart', true).append('svg')
.classed('navigator', true)
.attr('width', navWidth + margin.left + margin.right)
.attr('height', navHeight + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
// Scales
var navXScale = d3.time.scale()
.domain([
new Date(minDate.getTime() - 8.64e7),
new Date(maxDate.getTime() + 8.64e7)
])
.range([0, navWidth]),
navYScale = d3.scale.linear()
.domain([yMin, yMax])
.range([navHeight, 0]);
// Axes
var navXAxis = d3.svg.axis()
.scale(navXScale)
.orient('bottom');
navChart.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + navHeight + ')')
.call(navXAxis);
// Data series
var navData = d3.svg.area()
.x(function (d) { return navXScale(d.date); })
.y0(navHeight)
.y1(function (d) { return navYScale(d.close); });
var navLine = d3.svg.line()
.x(function (d) { return navXScale(d.date); })
.y(function (d) { return navYScale(d.close); });
navChart.append('path')
.attr('class', 'data')
.attr('d', navData(data));
navChart.append('path')
.attr('class', 'line')
.attr('d', navLine(data));
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Viewport
function redrawChart() {
dataSeries.call(series);
plotChart.select('.x.axis').call(xAxis);
}
function updateZoomFromChart() {
var fullDomain = maxDate - minDate,
currentDomain = xScale.domain()[1] - xScale.domain()[0];
var minScale = currentDomain / fullDomain,
maxScale = minScale * 20;
zoom.x(xScale)
.scaleExtent([minScale, maxScale]);
}
var viewport = d3.svg.brush()
.x(navXScale)
.on("brush", function () {
xScale.domain(viewport.empty() ? navXScale.domain() : viewport.extent());
redrawChart();
})
.on("brushend", function () {
updateZoomFromChart();
});
navChart.append("g")
.attr("class", "viewport")
.call(viewport)
.selectAll("rect")
.attr("height", navHeight);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Zooming and panning
function updateViewpointFromChart() {
if ((xScale.domain()[0] <= minDate) && (xScale.domain()[1] >= maxDate)) {
viewport.clear();
}
else {
viewport.extent(xScale.domain());
}
navChart.select('.viewport').call(viewport);
}
var zoom = d3.behavior.zoom()
.x(xScale)
.on('zoom', function() {
if (xScale.domain()[0] < minDate) {
zoom.translate([zoom.translate()[0] - xScale(minDate) + xScale.range()[0], 0]);
} else if (xScale.domain()[1] > maxDate) {
zoom.translate([zoom.translate()[0] - xScale(maxDate) + xScale.range()[1], 0]);
}
redrawChart();
updateViewpointFromChart();
});
var overlay = d3.svg.area()
.x(function (d) { return xScale(d.date); })
.y0(0)
.y1(height);
plotArea.append('path')
.attr('class', 'overlay')
.attr('d', overlay(data))
.call(zoom);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Setup
var daysShown = 30;
xScale.domain([
data[data.length - daysShown - 1].date,
data[data.length - 1].date
]);
redrawChart();
updateViewpointFromChart();
updateZoomFromChart();
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Helper methods
});
}
// alert("here we are again and again");
return chart;
}
return timeSeriesChart;
});
答案 0 :(得分:1)
从此示例中:http://bl.ocks.org/mbostock/6123708
创建缩放:
var zoom = d3.behavior.zoom()
.scaleExtent([1, 10])
.on("zoom", zoomed);
function zoomed() {
container.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
调用容器缩放:
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.right + ")")
.call(zoom); //<<<<<HERE
这就是它在单个画布上的样子,但在你的情况下,它看起来像这样:
创建缩放:
var zoom = d3.behavior.zoom()
.scaleExtent([1, 10])
.on("zoom", zoomed);
转换每个画布的容器
function zoomed() {
container1.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
container2.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
container3.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
在所有容器上调用缩放:
var svg1 = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.right + ")")
.call(zoom); //<<<<<HERE
var svg2 = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.right + ")")
.call(zoom); //<<<<<HERE
var svg3 = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.right + ")")
.call(zoom); //<<<<<HERE
这些方面的某些内容应该有效,但无需任何示例即可对其进行测试。