我正在使用D3製作一個使用可縮放行爲的時間聚焦圖。我遵循邁克·博斯托克的「邁向可重用圖表」文章中規定的模式,此外,還試圖使圖表反應靈敏。響應D3縮放行爲
可重複使用的圖表模式允許我簡單地在setInterval中調用我的圖表來處理響應。某些值(如寬度)會在每次調用時更新,其他值則封裝在閉包中,並僅在初始圖表創建時進行設置。需要潛在更新每個呼叫的值之一是比例範圍。
此外,根據https://github.com/mbostock/d3/wiki/Zoom-Behavior,修改由縮放行爲自動調整的比例的域或範圍時,需要(重新)指定縮放行爲的比例(此外,縮放行爲的比例和轉換值將被重置)。
但是,下面是結果我得到respecifying規模,每當我修改規模的範圍縮放行爲(也與最新的大規模更新縮放和平移值):
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);
\t var gEnter = svgEnter.append('g');
\t 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);
\t \t var rectItem = g.selectAll('rect.item').data(function(d) {
return d;
});
\t \t rectItem.enter().append('rect').attr('class', 'item').style('fill', '#00F');
\t \t \t \t \t 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() {
\t selection.call(myTest);
\t };
}(), 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>
我可以試圖通過規模最小respecify變焦性能非常接近。下面的工作,直到我調整窗口的大小,然後將變焦重點不是用鼠標排隊了:
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;
\t 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);
\t var gEnter = svgEnter.append('g');
\t 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);
\t \t var rectItem = g.selectAll('rect.item').data(function(d) {
return d;
});
\t \t rectItem.enter().append('rect').attr('class', 'item').style('fill', '#00F');
\t \t \t \t \t 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() {
\t selection.call(myTest);
\t };
}(), 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>
如何在響應使用縮放行爲和可重用的方式?