D3错误:<rect>属性width =“NaN”的值无效

时间:2015-08-07 12:36:55

标签: javascript d3.js

我有以下javascript:

/**
 *  Init
 */
var data = scope.dataset;
var outerWidth = scope.outerWidth;
var outerHeight = scope.outerHeight;
var margin = {
    left: 130,
    top: 0,
    right: 0,
    bottom: 30
};
var barPadding = 0.2;

var xColumn = scope.xColumn;
var yColumn = scope.yColumn;

var innerWidth = outerWidth - margin.left - margin.right;
var innerHeight = outerHeight - margin.top - margin.bottom;

var svg = d3.select("#chartArea").append("svg")
    .attr("width", outerWidth)
    .attr("height", outerHeight);


var tip = d3.tip()
    .attr('class', 'd3-tip')
    .offset([0, 0])
    .html(function (d) {
    return d[yColumn] + ": <span style='color:#008000'>" + d[xColumn];
});


var g = svg.append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var xAxisG = g.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + innerHeight + ")");
var yAxisG = g.append("g")
    .attr("class", "y axis");

var xScale = d3.scale.linear().range([0, innerWidth]);
var yScale = d3.scale.ordinal().rangeBands([0, innerHeight], barPadding);

var xAxis = d3.svg.axis().scale(xScale).orient("bottom")
    .ticks(d3.max(data, function (d) {
    return d[xColumn];
})) // Use approximately 5 ticks marks.
.tickFormat(d3.format("s")) // Use intelligent abbreviations, e.g. 5M for 5 Million
.outerTickSize(0); // Turn off the marks at the end of the axis.
var yAxis = d3.svg.axis().scale(yScale).orient("left")
    .outerTickSize(1); // Turn off the marks at the end of the axis.
svg.call(tip);

/**
 * Render function renders the chart with given data
 * @param data
 */
function render(data) {
    xScale.domain([0, d3.max(data, function (d) {
        return d[xColumn];
    })]);
    yScale.domain(data.map(function (d) {
        return d[yColumn];
    }));

    xAxisG.call(xAxis);
    yAxisG.call(yAxis);

    var bars = g.selectAll("rect").data(data);
    bars.enter().append("rect")
        .attr("height", yScale.rangeBand())
        .attr('class', 'vertical_bar')
        .on('mouseover', tip.show)
        .on('mouseout', tip.hide);
    bars.transition()
        .attr("x", 0)
        .attr("y", function (d) {
        return yScale(d[yColumn]);
    })
        .attr("width", function (d) {
        return xScale(d[xColumn]);
    });
    bars.exit().remove();
}

/**
 * Watchers for data change
 */
scope.$watch('xColumn', function (newValue, oldValue) {
    if (newValue) {
        xColumn = newValue;
    }
}, true);


scope.$watch('yColumn', function (newValue, oldValue) {
    if (newValue) {
        yColumn = newValue;
    }
}, true);

scope.$watch('dataset', function (newValue, oldValue) {
    if (newValue) {
        render(newValue);
    }
}, true);

然而,当我运行此操作时,我收到以下错误:

Error: Invalid value for <rect> attribute width="NaN"

我真的看不出问题所在!

示例数据:{label: 'hello world', value: 5}

Xcolumn = null

这是我的完整代码:

    app.controller('CompetenceOverviewController', ['$http', '$scope', '$sessionStorage', 'competenceStatService', '$log', 'Session', 'api', 'jobProfileService', 'divisionService', '$filter', function ($http, $scope, $sessionStorage, competenceStatService, $log, Session, api, jobProfileService, divisionService, $filter) {


    $scope.xColumn = 'value';
    $scope.yColumn = 'label';
    $scope.dataSet = null;


    $http.get(api.getUrl('aggregatedCompetences',[10,'gap'])).success(function(response){
        var dataSet = [];

        response.forEach(function (y) {
            var obj = {label: y.title.name, value: y.average};
            dataSet.push(obj);
        });

        $scope.dataSet = dataSet;

    })

}]);

HTML

       <vertical-bar-chart  x-column="xColumn" y-column="yColumn" dataset="dataSet" outer-width="500" outer-height="500"></vertical-bar-chart>

指令

app.directive("verticalBarChart", ['LRM', '$sce', '$http', 'deviceDetector', function (LRM, $sce, $http, deviceDetector) {
return {
    restrict: "E",
    templateUrl: 'tpl/directives/lb-charts/vertical_bar_chart.html',
    scope: {
        outerWidth: '=',
        outerHeight: '=',
        xColumn: '=',
        yColumn: '=',
        dataset: '='
    },
    link: function (scope, element, attr) {
        /**
         *  Init
         */
        var data = scope.dataset;
        var outerWidth = scope.outerWidth;
        var outerHeight = scope.outerHeight;
        var margin = {left: 130, top: 0, right: 0, bottom: 30};
        var barPadding = 0.2;

        var xColumn = scope.xColumn;
        var yColumn = scope.yColumn;

        var innerWidth = outerWidth - margin.left - margin.right;
        var innerHeight = outerHeight - margin.top - margin.bottom;

        var svg = d3.select("#chartArea").append("svg")
            .attr("width", outerWidth)
            .attr("height", outerHeight);


        var tip = d3.tip()
            .attr('class', 'd3-tip')
            .offset([0, 0])
            .html(function (d) {
                return d[yColumn] + ": <span style='color:#008000'>" + d[xColumn];
            });


        var g = svg.append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
        var xAxisG = g.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + innerHeight + ")");
        var yAxisG = g.append("g")
            .attr("class", "y axis");

        var xScale = d3.scale.linear().range([0, innerWidth]);
        var yScale = d3.scale.ordinal().rangeBands([0, innerHeight], barPadding);

        var xAxis = d3.svg.axis().scale(xScale).orient("bottom")
            .ticks(d3.max(data, function (d) {
                return d[xColumn];
            }))                   // Use approximately 5 ticks marks.
            .tickFormat(d3.format("s")) // Use intelligent abbreviations, e.g. 5M for 5 Million
            .outerTickSize(0);          // Turn off the marks at the end of the axis.
        var yAxis = d3.svg.axis().scale(yScale).orient("left")
            .outerTickSize(1);          // Turn off the marks at the end of the axis.
        svg.call(tip);

        /**
         * Render function renders the chart with given data
         * @param data
         */
        function render(data) {
            xScale.domain([0, d3.max(data, function (d) {
                return d[xColumn];
            })]);
            yScale.domain(data.map(function (d) {
                return d[yColumn];
            }));

            xAxisG.call(xAxis);
            yAxisG.call(yAxis);

            var bars = g.selectAll("rect").data(data);
            bars.enter().append("rect")
                .attr("height", yScale.rangeBand())
                .attr('class', 'vertical_bar')
                .on('mouseover', tip.show)
                .on('mouseout', tip.hide);
            bars
                .transition()
                .attr("x", 0)
                .attr("y", function (d) {
                    return yScale(d[yColumn]);
                })
                .attr("width", function (d) {
                    return xScale(d[xColumn]);
                });
            bars.exit().remove();
        }

        /**
         * Watchers for data change
         */
        scope.$watch('xColumn', function (newValue, oldValue) {
            if (newValue) {
                xColumn = newValue;
            }
        }, true);


        scope.$watch('yColumn', function (newValue, oldValue) {
            if (newValue) {
                yColumn = newValue;
            }
        }, true);

        scope.$watch('dataset', function (newValue, oldValue) {
            if (newValue) {
                if (xColumn == null) {
                    xColumn = scope.xColumn;
                }
                if (yColumn == null) {
                    yColumn = scope.yColumn;
                }
                render(newValue);
            }
        }, true);


    }
};
}]);

0 个答案:

没有答案