gpt4 book ai didi

javascript - 响应式 D3 缩放行为

转载 作者:行者123 更新时间:2023-11-29 19:21:16 26 4
gpt4 key购买 nike

我正在使用 D3 制作一个利用可缩放行为的以时间为中心的图表。我正在遵循 Mike Bostock 的“迈向可重用图表”一文中提出的模式,此外,我还试图让上述图表具有响应能力。

可重复使用的图表模式让我可以简单地在 setInterval 中调用我的图表来处理响应。某些值(如宽度)会在每次调用时更新,其他值会封装在闭包中并仅在初始图表创建时设置。每次调用都需要潜在更新的值之一是秤的范围。

此外,根据https://github.com/mbostock/d3/wiki/Zoom-Behavior ,修改由缩放行为自动调整的比例的域或范围需要(重新)指定缩放行为的比例(此外,缩放行为的比例和平移值将被重置)。

但是,以下是每当我修改比例范围(并使用最新的比例和平移值更新缩放)时将比例重新指定为缩放行为所得到的结果:

http://jsfiddle.net/xf3fk8hu/

function test(config) {
var aspectRatio = 10 / 3;
var margin = { top: 0, right: 0, bottom: 30, left: 0 };
var current = new Date();
var xScale = d3.time.scale().domain([d3.time.year.offset(current, -1), current]);
var xAxis = d3.svg.axis().scale(xScale).ticks(5);
var currentScale = 1;
var currentTranslate = [0, 0];
var zoom = d3.behavior.zoom().x(xScale).on('zoom', function() {
currentScale = d3.event.scale;
currentTranslate = d3.event.translate;
d3.select(this.parentNode.parentNode.parentNode).call(result);
});
var result = function(selection) {
selection.each(function(data) {
var outerWidth = $(this).width();
var outerHeight = outerWidth / aspectRatio;
var width = outerWidth - margin.left - margin.right;
var height = outerHeight - margin.top - margin.bottom;
xScale.range([0, width]);
zoom.x(xScale).scale(currentScale).translate(currentTranslate);

var svg = d3.select(this).selectAll('svg').data([data]);
var svgEnter = svg.enter().append('svg');
svg.attr('width', outerWidth).attr('height', outerHeight);
var gEnter = svgEnter.append('g');
var g = svg.select('g').attr('transform', 'translate(' + margin.left + ' ' + margin.top + ')');
gEnter.append('rect').attr('class', 'background').style('fill', '#F4F4F4').call(zoom);
g.select('rect.background').attr('width', width).attr('height', height);

var rectItem = g.selectAll('rect.item').data(function(d) {
return d;
});
rectItem.enter().append('rect').attr('class', 'item').style('fill', '#00F');
rectItem.attr('x', function(d) {
return xScale(d);
}).attr('width', xScale(d3.time.day.offset(xScale.invert(0), 7))).attr('height', height);

gEnter.append('g');
g.select('g').attr('transform', 'translate(0 ' + height + ')').call(xAxis);
});
};
return result;
}

setInterval(function() {
var selection = d3.select('#main').datum(d3.range(5).map(function() {
var current = new Date();
var mean = -d3.time.minute.range(current, d3.time.month.offset(current, 6)).length;
var deviation = d3.time.minute.range(current, d3.time.month.offset(current, 1)).length;
var random = d3.random.normal(mean, deviation);
return function() {
return d3.time.minute.offset(current, random());
};
}()));
var myTest = test();
return function() {
selection.call(myTest);
};
}(), 1000 / 60);
<div id="main"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

我可以通过尝试最低限度地重新指定缩放行为的比例来非常接近。以下工作直到我调整窗口大小,然后缩放焦点不再与鼠标对齐:

http://jsfiddle.net/xf3fk8hu/1/

function test(config) {
var aspectRatio = 10 / 3;
var margin = { top: 0, right: 0, bottom: 30, left: 0 };
var current = new Date();
var xScale = d3.time.scale().domain([d3.time.year.offset(current, -1), current]);
var isZoomControllingScale = false;
var xAxis = d3.svg.axis().scale(xScale).ticks(5);
var currentScale = 1;
var currentTranslate = [0, 0];
var zoom = d3.behavior.zoom().on('zoom', function() {
currentScale = d3.event.scale;
currentTranslate = d3.event.translate;
d3.select(this.parentNode.parentNode.parentNode).call(result);
});
var result = function(selection) {
selection.each(function(data) {
var outerWidth = $(this).width();
var outerHeight = outerWidth / aspectRatio;
var width = outerWidth - margin.left - margin.right;
var height = outerHeight - margin.top - margin.bottom;
xScale.range([0, width]);
if(!isZoomControllingScale) {
isZoomControllingScale = true;
zoom.x(xScale).scale(currentScale).translate(currentTranslate);
}

var svg = d3.select(this).selectAll('svg').data([data]);
var svgEnter = svg.enter().append('svg');
svg.attr('width', outerWidth).attr('height', outerHeight);
var gEnter = svgEnter.append('g');
var g = svg.select('g').attr('transform', 'translate(' + margin.left + ' ' + margin.top + ')');
gEnter.append('rect').attr('class', 'background').style('fill', '#F4F4F4').call(zoom);
g.select('rect.background').attr('width', width).attr('height', height);

var rectItem = g.selectAll('rect.item').data(function(d) {
return d;
});
rectItem.enter().append('rect').attr('class', 'item').style('fill', '#00F');
rectItem.attr('x', function(d) {
return xScale(d);
}).attr('width', xScale(d3.time.day.offset(xScale.invert(0), 7))).attr('height', height);

gEnter.append('g');
g.select('g').attr('transform', 'translate(0 ' + height + ')').call(xAxis);
});
};
return result;
}

setInterval(function() {
var selection = d3.select('#main').datum(d3.range(5).map(function() {
var current = new Date();
var mean = -d3.time.minute.range(current, d3.time.month.offset(current, 6)).length;
var deviation = d3.time.minute.range(current, d3.time.month.offset(current, 1)).length;
var random = d3.random.normal(mean, deviation);
return function() {
return d3.time.minute.offset(current, random());
};
}()));
var myTest = test();
return function() {
selection.call(myTest);
};
}(), 1000 / 60);
<div id="main"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

如何以响应式和可重用的方式使用缩放行为?

最佳答案

我解决了调整大小后缩放焦点不与鼠标对齐的问题,方法是仅在检测到宽度变化后才重新指定缩放行为的比例。但是,新宽度仍然存在问题,导致在调整大小时出现错误的转换。我在 d3 Preserve scale/translate after resetting range 找到了答案,这让我找到了一个解决方案:

http://jsfiddle.net/xf3fk8hu/5/

function test(config) {
var aspectRatio = 10 / 3;
var margin = { top: 0, right: 0, bottom: 30, left: 0 };
var current = new Date();
var xScale = d3.time.scale();
var xAxis = d3.svg.axis().scale(xScale).ticks(5);
var zoom = d3.behavior.zoom().x(xScale).on('zoom', function() {
currentScale = d3.event.scale;
currentTranslate = d3.event.translate;
d3.select(this.parentNode.parentNode.parentNode).call(result);
});
var currentScale = zoom.scale();
var currentTranslate = zoom.translate();
var oldWidth;
var result = function(selection) {
selection.each(function(data) {
var outerWidth = $(this).width();
var outerHeight = outerWidth / aspectRatio;
var width = outerWidth - margin.left - margin.right;
var height = outerHeight - margin.top - margin.bottom;
if(oldWidth !== width) {
if(oldWidth === undefined) oldWidth = width;
currentTranslate[0] *= width / oldWidth;
xScale.domain([d3.time.year.offset(current, -1), current]).range([0, width]);
zoom.x(xScale).scale(currentScale).translate(currentTranslate);
}
oldWidth = width;

var svg = d3.select(this).selectAll('svg').data([data]);
var svgEnter = svg.enter().append('svg');
svg.attr('width', outerWidth).attr('height', outerHeight);
var gEnter = svgEnter.append('g');
var g = svg.select('g').attr('transform', 'translate(' + margin.left + ' ' + margin.top + ')');
gEnter.append('rect').attr('class', 'background').style('fill', '#F4F4F4').call(zoom);
g.select('rect.background').attr('width', width).attr('height', height);

var rectItem = g.selectAll('rect.item').data(function(d) {
return d;
});
rectItem.enter().append('rect').attr('class', 'item').style('fill', '#00F');
rectItem.attr('x', function(d) {
return xScale(d);
}).attr('width', xScale(d3.time.day.offset(xScale.invert(0), 7))).attr('height', height);

gEnter.append('g');
g.select('g').attr('transform', 'translate(0 ' + height + ')').call(xAxis);
});
};
return result;
}

setInterval(function() {
var selection = d3.select('#main').datum(d3.range(5).map(function() {
var current = new Date();
var mean = -d3.time.minute.range(current, d3.time.month.offset(current, 6)).length;
var deviation = d3.time.minute.range(current, d3.time.month.offset(current, 1)).length;
var random = d3.random.normal(mean, deviation);
return function() {
return d3.time.minute.offset(current, random());
};
}()));
var myTest = test();
return function() {
selection.call(myTest);
};
}(), 1000 / 60);
<div id="main"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

关于javascript - 响应式 D3 缩放行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32959056/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com