首页 > 解决方案 > D3 json() 函数适用于本地文件,但不适用于将本地 var 设置为 json

问题描述

Script.js 在我引用本地 json 文件时有效,但在我将该文件的内容放入变量时无效。

脚本.js:

function getDataset(value,label)
{
    return{
        label:value,
        value:label
    }
}

var json_obj = {
    "1":
    {
        "1":
        {
            "labels": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "", "", "", "", "", "", "", ""],
            "name": "Jacob",
            "values": [86, 58, 58, 46, 48, 44, 0, 0, 0, 0, 0, 0, 340, 340, 340, 340, 340, 340, 340, 340]
        },
        "2":
        {
            "labels": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "", "", "", "", "", "", "", ""],
            "name": "Janis",
            "values": [276, 250, 248, 233, 149, 120, 112, 106, 125, 134, 96, 0, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849]
        },
        "3":
        {
            "labels": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "", "", "", "", "", "", "", ""],
            "name": "Mohammad",
            "values": [111, 55, 74, 55, 42, 51, 60, 63, 60, 61, 48, 0, 680, 680, 680, 680, 680, 680, 680, 680]
        }
    },
    "2":
    {
        "1":
        {
            "labels": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
            "name": "2008",
            "values": [11333.06, 12476.72, 10319.53, 10283.78, 9857.24, 9198.09, 9089.79, 8770.44, 8240.04, 6783.54, 6597.54, 9830.54]
        },
        "2":
        {
            "labels": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
            "name": "2009",
            "values": [7086.21, 8022.06, 2474.26, 14907.01, 9637.66, 11529.76, 11589.86, 11380.71, 8237.84, 10080.07, 8753.17, 8009.95]
        },
        "3":
        {
            "labels": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
            "name": "2010",
            "values": [9722.98, 10299.76, 10078.96, 10125.91, 10692.61, 8723.51, 8842.07, 13039.03, 17556.39, 19951.38, 24566.54, 23093.74]
        }
    }
};

var json_string = JSON.stringify(json_obj);
console.log(json_string);

function pieChart() {
    d3.json("data.json",function (json) {

        let years = [];

        for (let i = 1; i <= Object.keys(json[2]).length; i++) {

            years.push(getDataset(json[2][i].name, (json[2][i]['values'].reduce((a, b) => a + b, 0))));
        }


        var width = 1000;
        var height = 800;

// a circle chart needs a radius
        var radius = Math.min(width, height) / 2.5;

// legend dimensions
        var legendRectSize = 25; // defines the size of the colored squares in legend
        var legendSpacing = 6; // defines spacing between squares

// define color scale
        var color = d3.scale.category20();


        var svg = d3.select('#pie_chart') // select element in the DOM with id 'chart'
            .append('svg').attr('filter','url(#f3)') // append an svg element to the element we've selected
            .attr('width', width) // set the width of the svg element we just added
            .attr('height', height) // set the height of the svg element we just added
            .append('g') // append 'g' element to the svg element
            .attr('transform', 'translate(' + ((width / 2)-180) + ',' + (height / 2) + ')'); // our reference is now to the 'g' element. centerting the 'g' element to the svg element



        var arc = d3.svg.arc()
            .innerRadius(0) // none for pie chart
            .outerRadius(radius); // size of overall chart

        var pie = d3.layout.pie() // start and end angles of the segments
            .value(function(d) { return d.value; }) // how to extract the numerical data from each entry in our dataset
            .sort(null); // by default, data sorts in oescending value. this will mess with our animation so we set it to null



        var path = svg.selectAll('path') // select all path elements inside the svg. specifically the 'g' element. they don't exist yet but they will be created below
            .data(pie(years)) //associate dataset wit he path elements we're about to create. must pass through the pie function. it magically knows how to extract values and bakes it into the pie
            .enter() //creates placeholder nodes for each of the values
            .append('path') // replace placeholders with path elements
            .attr('d', arc) // define d attribute with arc function above
            .attr('fill', function(d) { return color(d.data.label); }).style('stroke','white') // use color scale to define fill of each label in dataset
            .each(function(d) { this._current - d; }); // creates a smooth animation for each track


        var labelArc = d3.svg.arc()
            .outerRadius(radius+151)
            .innerRadius(0);

        var labelArc1 = d3.svg.arc()
            .outerRadius(radius+351)
            .innerRadius(0);

        svg
            .selectAll('mySlices')
            .data(pie(years))
            .enter()
            .append('text').attr('class',function(d){return d.value}).attr('class','textn')
            .text(function(d){ return (Math.floor(d.data.value))})
            .attr("transform", function(d) { return (d.data.value>0? "translate(" + labelArc.centroid(d) + ")" : "translate(" + labelArc1.centroid(d) + ")");  })
            .style("text-anchor", "middle")
            .style("font-size", 15).style('fill',function(d){return (d.data.value>0? "white" : "black")});

// define legend
        var legend = svg.selectAll('.legend') // selecting elements with class 'legend'
            .data(color.domain()) // refers to an array of labels from our dataset
            .enter() // creates placeholder
            .append('g') // replace placeholders with g elements
            .attr('class', 'legend') // each g is given a legend class
            .attr('transform', function(d, i) {
                var height = legendRectSize + legendSpacing; // height of element is the height of the colored square plus the spacing
                var offset =  height * color.domain().length / 2; // vertical offset of the entire legend = height of a single element & half the total number of elements
                var horz = 15 * legendRectSize; // the legend is shifted to the left to make room for the text
                var vert = i * height - offset; // the top of the element is hifted up or down from the center using the offset defiend earlier and the index of the current element 'i'
                return 'translate(' + horz + ',' + vert + ')'; //return translation
            });

// adding colored squares to legend
        legend.append('rect') // append rectangle squares to legend
            .attr('width', legendRectSize) // width of rect size is defined above
            .attr('height', legendRectSize) // height of rect size is defined above
            .style('fill', color) // each fill is passed a color
            .style('stroke', color); // each stroke is passed a color

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

    });
}

当我用 json_obj 或 json_string 替换“data.json”时,出现错误:

Uncaught TypeError: Cannot read property '2' of null

这是在不同的应用程序中使用 javascipt 的垫脚石,所以如果可能的话,我希望 json 直接位于 javascript 文件中。可能吗?如果是这样,我应该如何格式化它?

标签: javascriptjsond3.js

解决方案


推荐阅读