[英]Update X-axis via zoom scale
I am trying to create a dynamic x-Axis time scale by checking my current zoom scale. 我正在尝试通过检查当前的缩放比例来创建动态的x轴时间比例。
It works on first load, but if I subsequently try to zoom in or out of the chart, my x-Axis doesn't response although I have declared the variable as a function and expect it to return the appropriate scale and axis every time a zoom action is called. 它在第一次加载时起作用,但是如果我随后尝试放大或缩小图表,尽管我已将变量声明为函数,并希望每次a都返回适当的比例尺和轴,但我的x轴没有响应。调用缩放动作。
My code below. 我的代码如下。 Thank you in advance.
先感谢您。
d3.csv('data/sample.csv', function (data) {
// sort out the data we'll be using
data.forEach(function (d) {
d.date = new Date(d.dateTime);
d.Ranking = +d.weight;
});
// define the boundaries of the svg canvas
var margin = {top : 30, right : 45, bottom : 30, left : 45},
width = window.innerWidth - margin.left - margin.right,
height = window.innerHeight - margin.top - margin.bottom;
// define the scale for each axis
var interval = 'hours';
var xScale = d3.time.scale()
.domain([d3.min(data, function (d) {
return d.date;
}), d3.max(data, function (d) {
return d.date;
})])
.range([0, width])
.nice();
var xDaysScale = d3.time.scale()
.domain([new Date(2014, 7, 1), new Date(2014, 7, 6)])
.range([0, width])
.nice();
var xWeeksScale = d3.time.scale()
.domain([new Date(2014, 7, 1), new Date(2014, 7, 31)])
.range([0, width])
.nice();
var xMonthsScale = d3.time.scale()
.domain([new Date(2014, 7, 1), new Date(2015, 0, 1)])
.range([0, width])
.nice();
var yScale = d3.scale.linear().domain([0, 5]).range([height, 0]).nice();
// define the axes
var xAxis = d3.svg.axis()
.scale(xScale)
.ticks(d3.time.hours, 1)
.orient('bottom');
var yAxis = d3.svg.axis().scale(yScale).orient('left');
// define the zoom behavior
var zm = d3.behavior.zoom()
.x(xScale)
.scaleExtent([.1, 1024])
.on('zoom', zoom);
// initialize the tooltip, and append it to the body
var tooltip = d3.select('body')
.append('div')
.attr('class', 'tooltip')
.attr('id', 'tooltip')
.style('opacity', 0);
// initialize the chart
var svg = d3.select('.graph')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('svg:g')
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
// append the manipulation areas to the chart
svg.append('rect')
.attr('class', 'zoom xy')
.attr('width', width)
.attr('height', height)
.call(zm)
.on('dblclick.zoom', null) // disable the standard shitty doubleclick zoom function
.on('dblclick', function (d) { // use my own awesome zoom function, that resets the chart
// reset the main scale
zm.scale(1);
zm.translate([0, 0]);
// let's not forget to update the axes
svg.select('.x.axis').call(xAxis);
svg.select('.y.axis').call(yAxis);
// apply the changes
update();
});
// append the axes to the chart
svg.append('svg:g')
.attr('class', 'x axis')
.attr('transform', 'translate(-' + width + ', ' + height + ')')
.attr('transform', 'translate(0, ' + height + ')')
.call(xAxis);
// create the elements based on the data provided
var elem = svg.selectAll()
.data(data)
.enter()
.append('g')
.attr('class', 'element')
.attr('transform', function (d) {
return 'translate(' + xScale(d.date) + ', ' + yScale(d.Ranking) + ')';
});
// we append the full text description as a HTML element, because, a text element is more expensive, and doesn't support line breaks
elem.append('foreignObject')
.attr('width', 200)
.attr('height', 1000)
.append('xhtml:div')
.attr('class', 'fulltext')
.html(function (d) {
return d.content;
})
.style('opacity', 0);
// function::zoom - handles the scaling, translation of the chart elements
function zoom() {
//svg.select('.x.axis').call(xAxis);
//svg.select('.y.axis').call(yAxis);
//update();
console.log(interval);
if (zm.scale() < 1) {
//console.log('zooming OUT');
if (interval == 'hours') {
xAxis = d3.svg.axis().scale(xDaysScale).ticks(d3.time.days, 1).orient("bottom");
zm.x(xDaysScale);
interval = 'days';
}
else if (interval == 'days') {
xAxis = d3.svg.axis().scale(xWeeksScale).ticks(d3.time.weeks, 1).orient("bottom");
zm.x(xWeeksScale);
interval = 'weeks';
}
else if (interval == 'weeks') {
xAxis = d3.svg.axis().scale(xMonthsScale).ticks(d3.time.months, 1).orient("bottom");
zm.x(xMonthsScale);
interval = 'months';
}
}
else if (zm.scale() > 1) {
//console.log('zooming IN');
if (interval == 'months') {
xAxis = d3.svg.axis().scale(xWeeksScale).ticks(d3.time.weeks, 1).orient("bottom");
zm.x(xWeeksScale);
interval = 'weeks';
}
else if (interval == 'weeks') {
xAxis = d3.svg.axis().scale(xDaysScale).ticks(d3.time.days, 1).orient("bottom");
zm.x(xDaysScale);
interval = 'days';
}
else if (interval == 'days') {
xAxis = d3.svg.axis().scale(xScale).ticks(d3.time.hours, 1).orient("bottom");
zm.x(xScale);
interval = 'hours';
}
}
svg.select('.x.axis').call(xAxis);
svg.select('.y.axis').call(yAxis);
update();
}
// function::resize - handles the responsive positioning and sizing of elements depending on the size of the viewport
function resize() {
// re-get the size of the window
width = window.innerWidth - margin.left - margin.right,
height = window.innerHeight - margin.top - margin.bottom;
// re-set the size of the chart's range
xScale.range([0, width]).nice();
yScale.range([height, 0]).nice();
// configure the chart to the new size
d3.select('.graph')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom);
// re-set the size of the manipulation area
svg.select('rect')
.attr('width', width)
.attr('height', height);
// re-size and re-position the axes
svg.select('.x.axis')
.attr('transform', 'translate(0, ' + height + ')')
.call(xAxis);
// update the elements according to the resized elements
update();
}
// function::update - handles all redrawing of the chart and checking of dynamic elements
function update() {
// re-position individual elements
svg.selectAll('.element')
.attr('transform', function (d) {
if (interval == 'hours') {
return 'translate(' + xScale(d.date) + ', ' + yScale(d.Ranking) + ')';
}
if (interval == 'days') {
return 'translate(' + xDaysScale(d.date) + ', ' + yScale(d.Ranking) + ')';
}
if (interval == 'weeks') {
return 'translate(' + xWeeksScale(d.date) + ', ' + yScale(d.Ranking) + ')';
}
if (interval == 'months') {
return 'translate(' + xMonthsScale(d.date) + ', ' + yScale(d.Ranking) + ')';
}
//return 'translate(' + xScale(d.date) + ', ' + yScale(d.Ranking) + ')';
});
d3.selectAll('.fulltext')
.style('opacity', function (d) {
// hide or show the full text descriptions based on zoom level
if (zm.scale() >= 1) {
return 1;
} else {
return 0;
}
});
}
// add the event handler for resizing
d3.select(window).on('resize', resize);
// refresh once to make sure all the processing gets through
update();
});
Declaring 宣告
xScale = returnScale()
will just call returnScale once, which doesn't sound like what you want. 只会调用returnScale一次,这听起来不像您想要的。 In your zoom() or update() you need to call returnScale() again, and then do
在您的zoom()或update()中,您需要再次调用returnScale(),然后执行
zm.x(xScale)
function zoom() {
console.log('interval: ' + interval);
console.log('zoom: ' + zm.scale());
if (zm.scale() < 1) {
if (interval == 'hours') {
//xAxis = xDaysAxis;
xDaysScale = d3.time.scale().domain([new Date(2014, 7, 1), new Date(2014, 7, 6)]).range([0, width]).nice();
xAxis = d3.svg.axis().scale(xDaysScale).ticks(d3.time.days, 1).orient("bottom");
zm.x(xDaysScale);
interval = 'days';
}
else if (interval == 'days') {
//xAxis = xWeeksAxis;
xWeeksScale = d3.time.scale().domain([new Date(2014, 7, 1), new Date(2014, 7, 31)]).range([0, width]).nice();
xAxis = d3.svg.axis().scale(xWeeksScale).ticks(d3.time.weeks, 1).orient("bottom");
zm.x(xWeeksScale);
interval = 'weeks';
}
else if (interval == 'weeks') {
//xAxis = xMonthsAxis;
xMonthsScale = d3.time.scale().domain([new Date(2014, 7, 1), new Date(2015, 0, 1)]).range([0, width]).nice();
xAxis = d3.svg.axis().scale(xMonthsScale).ticks(d3.time.months, 1).orient("bottom");
zm.x(xMonthsScale);
interval = 'months';
}
else {
//zm.x(xMonthsScale);
//interval = 'months';
}
}
else if (zm.scale() > 1) {
if (interval == 'months') {
//xAxis = xWeeksAxis;
xWeeksScale = d3.time.scale().domain([new Date(2014, 7, 1), new Date(2014, 7, 31)]).range([0, width]).nice();
xAxis = d3.svg.axis().scale(xWeeksScale).ticks(d3.time.weeks, 1).orient("bottom");
zm.x(xWeeksScale);
interval = 'weeks';
}
else if (interval == 'weeks') {
//xAxis = xDaysAxis;
xDaysScale = d3.time.scale().domain([new Date(2014, 7, 1), new Date(2014, 7, 6)]).range([0, width]).nice();
xAxis = d3.svg.axis().scale(xDaysScale).ticks(d3.time.days, 1).orient("bottom");
zm.x(xDaysScale);
interval = 'days';
}
else if (interval == 'days') {
//xAxis = xHoursAxis;
xHoursScale = d3.time.scale()
.domain([
//d3.min(data, function (d) { return d.date; }),
//d3.max(data, function (d) { return d.date; })
mindate, maxdate
])
.range([0, width])
.nice();
xAxis = d3.svg.axis().scale(xHoursScale).ticks(d3.time.hours, 1).orient("bottom");
zm.x(xHoursScale);
interval = 'hours';
}
else {
//zm.x(xHoursScale);
//interval = 'hours';
}
}
svg.select('.x.axis')
//.attr('transform', 'translate(0, ' + height + ')')
.call(xAxis);
svg.select('.y.axis').call(yAxis);
update();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.