javascript - 在模态弹出窗口中加载 d3 图表时,d3.v3.min.js :1 Error: <svg> attribute height: Expected length, "NaN"

标签 javascript angularjs d3.js svg

我一直在尝试在较小图表的模态弹出窗口 onClick 中加载更大尺寸的图表。我通过调整图表的 viewbox 大小使图表具有响应性。但我现在面临的问题是第一个图表正在变得响应并加载到主页上。但是当我单击该图表在 viewbox 中加载更大的图表时,我收到错误 d3.v3.min.js:1 Error: attribute height: Expected length, "NaN"。

奇怪的是,我对两个图表使用相同的指令和相同的 Controller ,对于第一个图表, View 框宽度给出了一个值,但对于其他图表,它给出了 NaN 。

如有任何帮助,请提前致谢。

var app = angular.module('chartApp', []);

app.controller('TimeReportCtrl', ['$scope', function($scope){

    $scope.reportData={"other_time":0,"ais_time":0,"agendas_time":0,"preps_time":1,"meeting_time":7};

    console.log($scope.reportData.other_time);

    if(($scope.reportData.other_time== 0) && ($scope.reportData.ais_time==0) && ($scope.reportData.agendas_time==0) && ($scope.reportData.preps_time==0) && ($scope.reportData.meeting_time==0))
    {

        $scope.noData = false;
    }
    else
    {
       
        $scope.noData = true;
    }

    $scope.timeReportData=[];

    for(var i in $scope.reportData){

        $scope.timeReportData.push({labelData:i,count:$scope.reportData[i]});
    }

    $scope.timeReport=[];


    for(var i=0;i<$scope.timeReportData.length;i++)
    {   $scope.data=(($scope.timeReportData[i]).labelData);


        switch ($scope.data){

            case "meeting_time":
                $scope.timeReport.push({label:"Meeting Time",count:$scope.timeReportData[i].count});
                break;

            case "ais_time":
                $scope.timeReport.push({label:"ActionItem",count:$scope.timeReportData[i].count});
                break;

            case "agendas_time" :
                $scope.timeReport.push({label:"Agendas Preparation",count:$scope.timeReportData[i].count});
                break;
            case "preps_time":
                $scope.timeReport.push({label:"Meeting Preparation",count:$scope.timeReportData[i].count});
                break;

            case "other_time":
                $scope.timeReport.push({label:"Other",count:$scope.timeReportData[i].count});
                break;

        }

    }
   



}]);





app.directive('timeReport', function($parse, $window){
    return{
        restrict:'EA',

        scope: {data: '=data'},
        link: function(scope, element, attrs) {



            scope.$watch('data', function (data) {

                if (data) {
                    var data = scope.data;
                    var margin = {top: 20, right: 20, bottom: 30, left: 40};
                    var width = 400;
                    var height = 400;
                    var radius = Math.min(width, height) / 2;
                    var donutWidth = 50;
                    var legendRectSize = 16;
                    var legendSpacing = 6;

                    var color = d3.scale.category20();
                    var el=element[0];
                    var svg = d3.select(el)
                        .append('svg')
                        .attr('width', width+(margin.right+margin.left))
                        .attr('height', height+(margin.top+margin.bottom))
                        .call(responsivefy)
                        .append('g')
                        .attr('transform', 'translate(' + (width / 2) +
                            ',' + (height / 2) + ')')
                        ;

                    var arc = d3.svg.arc()
                        .innerRadius(radius - donutWidth)
                        .outerRadius(radius);

                    var pie = d3.layout.pie()
                        .value(function (d) {
                            return d.count;
                        })
                        .sort(null);

                    var tooltip = d3.select(el)
                        .append('div')
                        .attr('class', 'tooltip');

                    tooltip.append('div')
                        .attr('class', 'label');

                    tooltip.append('div')
                        .attr('class', 'count');

                    tooltip.append('div')
                        .attr('class', 'percent');


                    data.forEach(function (d) {
                        d.count = +d.count;
                        d.enabled = true;                                         // NEW
                    });

                    var path = svg.selectAll('path')
                        .data(pie(data))
                        .enter()
                        .append('path')
                        .attr('d', arc)
                        .attr('fill', function (d, i) {
                            return color(d.data.label);
                        })                                                        // UPDATED (removed semicolon)
                        .each(function (d) {
                            this._current = d;
                        });                // NEW

                    path.on('mouseover', function (d) {
                        var total = d3.sum(data.map(function (d) {
                            return (d.enabled) ? d.count : 0;                       // UPDATED
                        }));
                        var percent = Math.round(1000 * d.data.count / total) / 10;
                        tooltip.select('.label').html(d.data.label);
                        tooltip.select('.count').html(d.data.count);
                        tooltip.select('.percent').html(percent + '%');
                        tooltip.style('display', 'block');
                    });

                    path.on('mouseout', function () {
                        tooltip.style('display', 'none');
                    });

                  

                    var legend = svg.selectAll('.legend')
                        .data(color.domain())
                        .enter()
                        .append('g')
                        .attr('class', 'legend')
                        .attr('transform', function (d, i) {
                            var height = legendRectSize + legendSpacing;
                            var offset = height * color.domain().length / 2;
                            var horz = -2 * legendRectSize;
                            var vert = i * height - offset;
                            return 'translate(' + horz + ',' + vert + ')';
                        });

                    legend.append('rect')
                        .attr('width', legendRectSize)
                        .attr('height', legendRectSize)
                        .style('fill', color)
                        .style('stroke', color)
                        .on('click', function (label) {
                            var rect = d3.select(this);
                            var enabled = true;
                            var totalEnabled = d3.sum(data.map(function (d) {
                                return (d.enabled) ? 1 : 0;
                            }));

                            if (rect.attr('class') === 'disabled') {
                                rect.attr('class', '');
                            } else {
                                if (totalEnabled < 2) return;
                                rect.attr('class', 'disabled');
                                enabled = false;
                            }

                            pie.value(function (d) {
                                if (d.label === label) d.enabled = enabled;
                                return (d.enabled) ? d.count : 0;
                            });

                            path = path.data(pie(data));

                            path.transition()
                                .duration(750)
                                .attrTween('d', function (d) {
                                    var interpolate = d3.interpolate(this._current, d);
                                    this._current = interpolate(0);
                                    return function (t) {
                                        return arc(interpolate(t));
                                    };
                                });
                        });

                    legend.append('text')
                        .attr('x', legendRectSize + legendSpacing)
                        .attr('y', legendRectSize - legendSpacing)
                        .text(function (d) {
                            return d;
                        });



                }

                function responsivefy(svg) {
                    console.log("inside responsivefy");
                    // get container + svg aspect ratio
                    var container = d3.select(svg.node().parentNode),
                        width = parseInt(svg.style("width")),
                        height = parseInt(svg.style("height")),
                        aspect = width / height;
                        console.log("width of container");
                    console.log(width);

                    console.log(container.style("width"));

                    svg.attr("viewBox", "0 0 " + width + " " + height)
                        .attr("perserveAspectRatio", "xMinYMid")
                        .call(resize);



                    d3.select(window).on("resize." + container.attr("id"), resize);

                    // get width of container and resize svg to fit it
                    function resize() {

                        var targetWidth = parseInt(container.style("width"));
                        console.log(targetWidth);
                        svg.attr("width", targetWidth);
                        svg.attr("height", Math.round(targetWidth / aspect));
                    }
                };
            })
        }
    };
});
.tooltip {
    background: #eee;
    box-shadow: 0 0 5px #999999;
    color: #333;
    display: none;
    font-size: 12px;
    left: 130px;
    padding: 10px;
    position: absolute;
    text-align: center;
    top: 95px;
    width: 80px;
    z-index: 10;
}
.legend {
    font-size: 7px;
}
rect {
    cursor: pointer;
    stroke-width: 2;
}
rect.disabled {
    fill: transparent !important;
}
<html>
<head>
    <link rel="stylesheet" href="report.css" type="text/css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" type="text/css">

</head>
<body>


<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.4/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-moment/0.10.3/angular-moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
<script src="script.js"></script>


<div ng-app="chartApp">


    <div class="col-lg-6 col-sm-12" data-toggle="modal" data-target="#myModal" style="
        width: 700px;
    ">


        <div  class="panel panel-default" ng-controller="TimeReportCtrl" ng-show="noData"  style="
        width: 50%;
        height: 50%;
    " >
            <div class="panel-heading">Monthly User Report</div>




            <div   class="panel-body"  >


                <div time-report data="timeReport"></div>

            </div>
        </div>
    </div>

    
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
                    <h4 class="modal-title" id="myModalLabel">Reports</h4>
                </div>

                <div class="modal-footer">
                    <div  class="panel panel-default" ng-controller="TimeReportCtrl" ng-show="noData"  >
                        <div class="panel-heading">Monthly User Report</div>




                        <div   class="panel-body"  >


                            <div time-report data="timeReport"></div>

                        </div>
                    </div>
                </div>
                <!-- /.modal-content -->
            </div>
            <!-- /.modal-dialog -->
        </div>

    </div>
</div>
</body>
</html>

最佳答案

试试这个方法。

d3.select(window).on("resize", resize);

// get width of container and resize svg to fit it
function resize() {
    var containerWidth = parseInt(container.style("width"));
    var targetWidth = containerWidth ? containerWidth : parseInt(svg.style("width"));
    console.log(targetWidth);
    svg.attr("width", targetWidth);
    svg.attr("height", Math.round(targetWidth / aspect));
}

var app = angular.module('chartApp', []);

app.controller('TimeReportCtrl', ['$scope', function($scope){

    $scope.reportData={"other_time":0,"ais_time":0,"agendas_time":0,"preps_time":1,"meeting_time":7};

    console.log($scope.reportData.other_time);

    if(($scope.reportData.other_time== 0) && ($scope.reportData.ais_time==0) && ($scope.reportData.agendas_time==0) && ($scope.reportData.preps_time==0) && ($scope.reportData.meeting_time==0))
    {

        $scope.noData = false;
    }
    else
    {
       
        $scope.noData = true;
    }

    $scope.timeReportData=[];

    for(var i in $scope.reportData){

        $scope.timeReportData.push({labelData:i,count:$scope.reportData[i]});
    }

    $scope.timeReport=[];


    for(var i=0;i<$scope.timeReportData.length;i++)
    {   $scope.data=(($scope.timeReportData[i]).labelData);


        switch ($scope.data){

            case "meeting_time":
                $scope.timeReport.push({label:"Meeting Time",count:$scope.timeReportData[i].count});
                break;

            case "ais_time":
                $scope.timeReport.push({label:"ActionItem",count:$scope.timeReportData[i].count});
                break;

            case "agendas_time" :
                $scope.timeReport.push({label:"Agendas Preparation",count:$scope.timeReportData[i].count});
                break;
            case "preps_time":
                $scope.timeReport.push({label:"Meeting Preparation",count:$scope.timeReportData[i].count});
                break;

            case "other_time":
                $scope.timeReport.push({label:"Other",count:$scope.timeReportData[i].count});
                break;

        }

    }
   



}]);





app.directive('timeReport', function($parse, $window){
    return{
        restrict:'EA',

        scope: {data: '=data'},
        link: function(scope, element, attrs) {



            scope.$watch('data', function (data) {

                if (data) {
                    var data = scope.data;
                    var margin = {top: 20, right: 20, bottom: 30, left: 40};
                    var width = 400;
                    var height = 400;
                    var radius = Math.min(width, height) / 2;
                    var donutWidth = 50;
                    var legendRectSize = 16;
                    var legendSpacing = 6;

                    var color = d3.scale.category20();
                    var el=element[0];
                    var svg = d3.select(el)
                        .append('svg')
                        .attr('width', width+(margin.right+margin.left))
                        .attr('height', height+(margin.top+margin.bottom))
                        .call(responsivefy)
                        .append('g')
                        .attr('transform', 'translate(' + (width / 2) +
                            ',' + (height / 2) + ')')
                        ;

                    var arc = d3.svg.arc()
                        .innerRadius(radius - donutWidth)
                        .outerRadius(radius);

                    var pie = d3.layout.pie()
                        .value(function (d) {
                            return d.count;
                        })
                        .sort(null);

                    var tooltip = d3.select(el)
                        .append('div')
                        .attr('class', 'tooltip');

                    tooltip.append('div')
                        .attr('class', 'label');

                    tooltip.append('div')
                        .attr('class', 'count');

                    tooltip.append('div')
                        .attr('class', 'percent');


                    data.forEach(function (d) {
                        d.count = +d.count;
                        d.enabled = true;                                         // NEW
                    });

                    var path = svg.selectAll('path')
                        .data(pie(data))
                        .enter()
                        .append('path')
                        .attr('d', arc)
                        .attr('fill', function (d, i) {
                            return color(d.data.label);
                        })                                                        // UPDATED (removed semicolon)
                        .each(function (d) {
                            this._current = d;
                        });                // NEW

                    path.on('mouseover', function (d) {
                        var total = d3.sum(data.map(function (d) {
                            return (d.enabled) ? d.count : 0;                       // UPDATED
                        }));
                        var percent = Math.round(1000 * d.data.count / total) / 10;
                        tooltip.select('.label').html(d.data.label);
                        tooltip.select('.count').html(d.data.count);
                        tooltip.select('.percent').html(percent + '%');
                        tooltip.style('display', 'block');
                    });

                    path.on('mouseout', function () {
                        tooltip.style('display', 'none');
                    });

                  

                    var legend = svg.selectAll('.legend')
                        .data(color.domain())
                        .enter()
                        .append('g')
                        .attr('class', 'legend')
                        .attr('transform', function (d, i) {
                            var height = legendRectSize + legendSpacing;
                            var offset = height * color.domain().length / 2;
                            var horz = -2 * legendRectSize;
                            var vert = i * height - offset;
                            return 'translate(' + horz + ',' + vert + ')';
                        });

                    legend.append('rect')
                        .attr('width', legendRectSize)
                        .attr('height', legendRectSize)
                        .style('fill', color)
                        .style('stroke', color)
                        .on('click', function (label) {
                            var rect = d3.select(this);
                            var enabled = true;
                            var totalEnabled = d3.sum(data.map(function (d) {
                                return (d.enabled) ? 1 : 0;
                            }));

                            if (rect.attr('class') === 'disabled') {
                                rect.attr('class', '');
                            } else {
                                if (totalEnabled < 2) return;
                                rect.attr('class', 'disabled');
                                enabled = false;
                            }

                            pie.value(function (d) {
                                if (d.label === label) d.enabled = enabled;
                                return (d.enabled) ? d.count : 0;
                            });

                            path = path.data(pie(data));

                            path.transition()
                                .duration(750)
                                .attrTween('d', function (d) {
                                    var interpolate = d3.interpolate(this._current, d);
                                    this._current = interpolate(0);
                                    return function (t) {
                                        return arc(interpolate(t));
                                    };
                                });
                        });

                    legend.append('text')
                        .attr('x', legendRectSize + legendSpacing)
                        .attr('y', legendRectSize - legendSpacing)
                        .text(function (d) {
                            return d;
                        });



                }

                function responsivefy(svg) {
                    console.log("inside responsivefy");
                    // get container + svg aspect ratio
                    var container = d3.select(svg.node().parentNode),
                        width = parseInt(svg.style("width")),
                        height = parseInt(svg.style("height")),
                        aspect = width / height;
                        console.log("width of container");
                    console.log(width);

                    console.log(container.style("width"));

                    svg.attr("viewBox", "0 0 " + width + " " + height)
                        .attr("perserveAspectRatio", "xMinYMid")
                        .call(resize);



                    d3.select(window).on("resize", resize);

                    // get width of container and resize svg to fit it
                    function resize() {
                        var containerWidth = parseInt(container.style("width"));
                        var targetWidth = containerWidth?containerWidth:parseInt(svg.style("width"));
                        console.log(targetWidth);
                        svg.attr("width", targetWidth);
                        svg.attr("height", Math.round(targetWidth / aspect));
                    }
                };
            })
        }
    };
});
.tooltip {
    background: #eee;
    box-shadow: 0 0 5px #999999;
    color: #333;
    display: none;
    font-size: 12px;
    left: 130px;
    padding: 10px;
    position: absolute;
    text-align: center;
    top: 95px;
    width: 80px;
    z-index: 10;
}
.legend {
    font-size: 7px;
}
rect {
    cursor: pointer;
    stroke-width: 2;
}
rect.disabled {
    fill: transparent !important;
}
<html>
<head>
    <link rel="stylesheet" href="report.css" type="text/css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" type="text/css">

</head>
<body>


<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.4/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-moment/0.10.3/angular-moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
<script src="script.js"></script>


<div ng-app="chartApp">


    <div class="col-lg-6 col-sm-12" data-toggle="modal" data-target="#myModal" style="
        width: 700px;
    ">


        <div  class="panel panel-default" ng-controller="TimeReportCtrl" ng-show="noData"  style="
        width: 50%;
        height: 50%;
    " >
            <div class="panel-heading">Monthly User Report</div>




            <div   class="panel-body"  >


                <div time-report data="timeReport"></div>

            </div>
        </div>
    </div>

    
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
                    <h4 class="modal-title" id="myModalLabel">Reports</h4>
                </div>

                <div class="modal-footer">
                    <div  class="panel panel-default" ng-controller="TimeReportCtrl" ng-show="noData"  >
                        <div class="panel-heading">Monthly User Report</div>




                        <div   class="panel-body"  >


                            <div time-report data="timeReport"></div>

                        </div>
                    </div>
                </div>
                <!-- /.modal-content -->
            </div>
            <!-- /.modal-dialog -->
        </div>

    </div>
</div>
</body>
</html>

关于javascript - 在模态弹出窗口中加载 d3 图表时,d3.v3.min.js :1 Error: <svg> attribute height: Expected length, "NaN",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37452472/

相关文章:

java - 多个提交按钮,javascript

javascript - 拖动 div 正在创建更多 div

javascript - 无法使用带有 php 的 jquery ajax 将数据添加到数据库中

javascript - 然后 Angularjs 在 for 循环中根据 Promise 运行。如何访问当前项目的索引?

javascript - Angular JS $http.get 返回数组,尝试将每个数组放入 $scope 中

javascript - 如何使用 d3.js 缩放图表内的元素

javascript - d3.js filter() 不显示预期结果

javascript - Ruby 中的索引

angularjs - 在 AngularJS 中使用 ngdocs 和 Controller 属性

javascript - 沃罗诺伊 map : Unable to find data that I just associated with an object