异步将新数据加载到d3图表

时间:2015-05-11 15:38:34

标签: javascript angularjs d3.js

我正在使用d3.js构建一种时间轴工具,可以在设定的时间段内向前和向后缩放和分页。我的轴完美转换,但我似乎无法重新加载我的数据。想法是缩放级别定义移动窗口,例如用户在几天的时间内向后和向前移动的1小时。每次他们这样做时,都会打电话来获取该小时的数据。

对于大代码块的抱歉,处理新数据获取的方法是最底层的。如果它有任何不同,该工具是angular.js的指令。

// routes.php
$route['(:any)'] = "PublicController/index/$1";

// PublicController.php
public function index()
{
    var_dump(func_get_args());
}

更新#1

我已经能够在line console.log(data.items.length)

之后使用Articles.get回调中的以下代码来显示要显示的新数据和旧数据。
 scope.zoomLevels = [
                {
                    value: 1,
                    unit: 'minutes',
                    tickFormat: $window.d3.time.format('%S')
                },
                {
                    value: 30,
                    unit: 'minutes',
                    tickFormat: $window.d3.time.format('%H:%M')
                },
                {
                    value: 1,
                    unit: 'hours',
                    tickFormat: $window.d3.time.format('%H:%M')
                },
                {
                    value: 3,
                    unit: 'hours',
                    tickFormat: $window.d3.time.format('%H:%M')
                },
                {
                    value: 6,
                    unit: 'hours',
                    tickFormat: $window.d3.time.format('%H:%M')
                },
                {
                    value: 12,
                    unit: 'hours',
                    tickFormat: $window.d3.time.format('%H:%M')
                },
                {
                    value: 1,
                    unit: 'days',
                    tickFormat: $window.d3.time.format('%H:%M')
                }
            ];

            var margin = {top: 0, right: 0, bottom: 0, left: 0},
                width = $window.innerWidth,
                height = $window.innerHeight - margin.top - margin.bottom,
                xAxisHeight = $window.innerHeight - margin.top - ($window.innerHeight/2);

            var start = $window.moment(Datasets.current.dates[0], 'DD/MM/YYYY'),
                end = $window.moment(Datasets.current.dates[Datasets.current.dates.length - 1], 'DD/MM/YYYY'),
                duration = $window.moment.duration(end.diff(start));

            scope.zoomLevel = 3;
            scope.page = 0;
            scope.maxPage = duration.asMinutes()/scope.zoomLevels[scope.zoomLevel].value;

            //$scope.tweets = Tweets.getTweets(start.format('x'), end.format('x'));

            var rows = Math.floor(height/ 60);

            console.log(rows + ' Rows');

            var x = $window.d3.time.scale()
                .domain([start.toDate(), start.clone().add(scope.zoomLevels[scope.zoomLevel].value, scope.zoomLevels[scope.zoomLevel].unit).toDate()])
                .range([0, width]);

            var y =  $window.d3.scale.linear()
                .domain([(rows/2) * -1,(rows/2)])
                .range([height, 0]);

            var xAxis = $window.d3.svg.axis()
                .scale(x);

            var yAxis =  $window.d3.svg.axis()
                .scale(y)
                .tickSize(5)
                .orient('right');

            var svg = $window.d3.select('#timeline').append('svg')
                .attr('width', width + margin.left + margin.right)
                .attr('height', height)
                .append('g')
                .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

            svg.append('g')
                .attr('class', 'x axis')
                .attr('transform', 'translate(0,' + xAxisHeight + ')')
                .call(xAxis)
                .selectAll('text')
                .attr('y', 15)
                .attr('x', 0)
                .attr('dy', '.35em');

            svg.append('g')
                .attr('class', 'y axis')
                .call(yAxis);

            Articles.get({startDate: start.format(), endDate: start.clone().add(scope.zoomLevels[scope.zoomLevel].value, scope.zoomLevels[scope.zoomLevel].unit).format(), limit: 20}, function(data){

                var bar = svg.selectAll('.news')
                    .data(data.items)
                    .enter()
                    .append('g')
                    .attr('class', 'news')
                    .on('mouseover', function(d) {
                        console.log(d);
                    })
                    .on('mouseout', function(d) {

                    });

                bar.append('rect')
                    .attr('width', 250)
                    .attr('height', 60)
                    .attr('x', function(d){return x($window.moment(d.date, 'YYYY-MM-DDTHH:mm:ss.000Z').format('x'));})
                    .attr('y', function(d){return y(2);})

                bar.append('foreignObject')
                    .attr('width', 250)
                    .attr('height', 60)
                    .attr('x', function(d){return x($window.moment(d.date, 'YYYY-MM-DDTHH:mm:ss.000Z').format('x'));})
                    .attr('y', function(d){return y(2);})
                    .append('xhtml:p')
                    .attr("class","statement")
                    .text(function(d) { return d.title; });

            });

            scope.movePage = function(direction){
                if(!(direction === 1 && scope.page === scope.maxPage) || !(direction === -1 && scope.page === 0)){

                    console.log('Paging allowed');

                    if(direction === 1){

                        start = start.add(scope.zoomLevels[scope.zoomLevel].value, scope.zoomLevels[scope.zoomLevel].unit);

                        x.domain([start.toDate(), start.clone().add(scope.zoomLevels[scope.zoomLevel].value, scope.zoomLevels[scope.zoomLevel].unit).toDate()]);

                        Articles.get({startDate: start.format(), endDate: start.clone().add(scope.zoomLevels[scope.zoomLevel].value, scope.zoomLevels[scope.zoomLevel].unit).format(), limit: 20}, function(data) {

                            console.log(data.items.length);

                            svg.selectAll('.news').data(data.items).transition().duration(1500).ease('sin-in-out');

                            svg.selectAll('g.axis.x').transition().duration(1500).ease('sin-in-out').call(xAxis);
                        });

                        scope.page++;
                    }

                    if(direction === -1){

                        start = start.subtract(scope.zoomLevels[scope.zoomLevel].value, scope.zoomLevels[scope.zoomLevel].unit);

                        x.domain([start.toDate(), start.clone().add(scope.zoomLevels[scope.zoomLevel].value, scope.zoomLevels[scope.zoomLevel].unit).toDate()]);

                        svg.selectAll('g.axis.x').transition().duration(1500).ease('sin-in-out').call(xAxis);

                        scope.page--;

                    }
                }
            };

            scope.toggleZoom = function(direction){
                if(!(direction === 1 && scope.zoomLevel === 6) || !(direction === -1 && scope.zoomLevel === 0)){

                    duration = $window.moment.duration(end.diff(start));

                    scope.zoomLevel = scope.zoomLevel + direction;

                    console.log(scope.zoomLevels[scope.zoomLevel].unit);

                    switch (scope.zoomLevels[scope.zoomLevel].unit){
                        case 'minutes':

                            scope.maxPage = duration.asMinutes()/scope.zoomLevels[scope.zoomLevel].value;

                            console.log(duration.asMinutes() + ' Minutes');
                            console.log((duration.asMinutes()/scope.zoomLevels[scope.zoomLevel].value) + ' Pages');
                            break;
                        case 'hours':

                            scope.maxPage = duration.asHours()/scope.zoomLevels[scope.zoomLevel].value;

                            console.log(duration.asHours() + ' Hours');
                            console.log((duration.asHours()/scope.zoomLevels[scope.zoomLevel].value) + ' Pages');
                            break;
                        case 'days':

                            scope.maxPage = duration.asDays()/scope.zoomLevels[scope.zoomLevel].value;

                            console.log(duration.asDays() + ' Days');
                            console.log((duration.asDays()/scope.zoomLevels[scope.zoomLevel].value) + ' Pages');
                            break;
                    }

                    x.domain([start.toDate(), start.clone().add(scope.zoomLevels[scope.zoomLevel].value, scope.zoomLevels[scope.zoomLevel].unit).toDate()]);

                    svg.selectAll('g.axis').transition().duration(1500).ease('sin-in-out').call(xAxis);

                }
            };

然而,动画并没有真正起作用。最终,如果用户点击下一页,我希望代表每个新闻项目的svg元素以与轴相同的速度向左移动。目前,当用户点击前进和后退按钮时,它们会立即显示/消失。

1 个答案:

答案 0 :(得分:0)

if(!(direction === 1 && scope.page === scope.maxPage) || !(direction === -1 && scope.page === 0)){

if(direction === 1){ ... }
if(direction === -1){ .. }

这不容易解析,你确定在给定这些条件的情况下,任何一个内部代码块都可以执行吗?