我正在尝试通过检查当前的缩放比例来创建动态x轴时间刻度。
它适用于第一次加载,但如果我随后尝试放大或缩小图表,我的x轴没有响应,虽然我已将变量声明为函数并期望它返回适当的比例和轴每次调用缩放操作时。
我的代码如下。提前谢谢。
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();
});
答案 0 :(得分:0)
声明
xScale = returnScale()
只会调用一次returnScale,这听起来并不像你想要的那样。在缩放()或更新()中,您需要再次调用returnScale(),然后执行
zm.x(xScale)
答案 1 :(得分:0)
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();
}