【发布时间】:2023-03-08 23:14:02
【问题描述】:
我想将多个图表的缩放和平移控件链接在一起,以便在启用图表平移和缩放控件之一时,它们都可以一起平移和缩放。
我尝试创建单个缩放对象并将其传递给图表,但只有最后一个图表实际平移和缩放。即使我放大他们的区域,其他人仍然保持静止。
这是图表的快照。每个图表都有一个概览图表,其中包含一个也可以移动的视口。我想将所有控件链接在一起,以便每个图表上的视口也相同。
那么,如何在多个图表上链接平移和缩放控件?
这是此代码的 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;
});
【问题讨论】:
-
您的代码运行不正常。做一个小提琴,让我们看看。但我要做的是调用缩放函数,在这个函数中(你在 svg 上调整大小/翻译),我会同时调用每个容器
-
好的,我会做一个小提琴。
-
我之前没有做过小提琴,所以我不知道如何制作一个使用 require 和 code 分布在多个文件中的小提琴。会继续努力。
-
@thisOneGuy 我为此代码创建了一个小提琴。主图表在开头,配置代码在底部。我不得不在中间添加一些库代码,因为我无法从外部资源中获取一些库来工作。你能给我一些关于如何访问所有控件以便同时更新它们的更多线索吗?
标签: d3.js