D3.js使用对象数据渲染条形图的问题

时间:2018-11-10 14:32:07

标签: javascript d3.js

我有以下脚本用于在D3.js中渲染简单的条形图。我已经能够将图表渲染到一定程度。

我有下面的这些数据,我很难插入到图表中,没有可以调用的特定键,而且我真的很困惑如何将所有这些插入图表中。

Object { "food-environmental-science": 0, "art-media-research": 0, .....}

我有一个单独的HTML文件(只有一个片段):

var barchart1 = barchart("#otherchart");

function clickScatter(d){
   var unitOfAssessment = d.UoAString;
   click = d.environment.topicWeights
   renderTopicWeights(click)
}

function renderTopicWeights(clickedPoint){
    barchart1.loadAndRenderDataset(clickedPoint)
}

当我调用loadAndRenderDataset函数时,控制台会给我一个data.map不是函数错误。

 function barchart(targetDOMelement) { 

//=================== PUBLIC FUNCTIONS =========================
//
barchartObject.appendedMouseOverFunction = function (callbackFunction) {
    console.log("appendedMouseOverFunction called", callbackFunction)
    appendedMouseOverFunction = callbackFunction;
    render();
    return barchartObject;
}   

barchartObject.appendedMouseOutFunction = function (callbackFunction) {
    appendedMouseOutFunction = callbackFunction;
    render();
    return barchartObject;
}   

barchartObject.loadAndRenderDataset = function (data) {
    dataset=data.map(d=>d); //create local copy of references so that we can sort etc.
    render();
    return barchartObject;
}   

barchartObject.overrideDataFieldFunction = function (dataFieldFunction) {
    dataField = dataFieldFunction;
    return barchartObject;
}

barchartObject.overrideKeyFunction = function (keyFunction) {
    //The key function is used to obtain keys for GUP rendering and
    //to provide the categories for the y-axis
    //These valuse should be unique
    GUPkeyField = yAxisCategoryFunction = keyFunction;
    return barchartObject;
}

barchartObject.overrideMouseOverFunction = function (callbackFunction) {
    mouseOverFunction = callbackFunction;
    render();
    return barchartObject;
}

barchartObject.overrideMouseOutFunction = function (callbackFunction) {
    mouseOutFunction = callbackFunction;
    render(); //Needed to update DOM
    return barchartObject;
}

barchartObject.overrideTooltipFunction = function (toolTipFunction) {
    tooltip = toolTipFunction;
    return barchartObject;
}

barchartObject.overrideMouseClickFunction = function (fn) {
    mouseClick2Function = fn;
    render(); //Needed to update DOM if they exist
    return barchartObject;
}   


barchartObject.render = function (callbackFunction) {
    render(); //Needed to update DOM
    return barchartObject;
}   


barchartObject.setTransform = function (t) {
    //Set the transform on the svg
    svg.attr("transform", t)
    return barchartObject;
}   

barchartObject.yAxisIndent = function (indent) {
    yAxisIndent=indent;
    return barchartObject;
}



//=================== PRIVATE VARIABLES ====================================
//Width and height of svg canvas
var svgWidth = 900; 
var svgHeight = 450;
var dataset = [];
var xScale = d3.scaleLinear();
var yScale = d3.scaleBand(); //This is an ordinal (categorical) scale
var yAxisIndent = 400; //Space for labels
var maxValueOfDataset; //For manual setting of bar length scaling (only used if .maxValueOfDataset() public method called)

//=================== INITIALISATION CODE ====================================

//Declare and append SVG element
var svg = d3
    .select(targetDOMelement)
    .append("svg")
    .attr("width", svgWidth)
    .attr("height", svgHeight)
    .classed("barchart",true);  

//Declare and add group for y axis
var yAxis = svg
    .append("g")
    .classed("yAxis", true);    

//Declare and add group for x axis
var xAxis = svg
    .append("g")
    .classed("xAxis", true);            


//===================== ACCESSOR FUNCTIONS =========================================

var dataField = function(d){return d.datafield} //The length of the bars
var tooltip = function(d){return  d.key + ": "+ d.datafield} //tooltip text for bars
var yAxisCategoryFunction = function(d){return d.key} //Categories for y-axis
var GUPkeyField = yAxisCategoryFunction; //For 'keyed' GUP rendering (set to y-axis category)


//=================== OTHER PRIVATE FUNCTIONS ====================================  
var maxValueOfDataField = function(){
    //Find the maximum value of the data field for the x scaling function using a handy d3 max() method 
    //This will be used to set (normally used ) 
    return d3.max(dataset, dataField)
};  

var appendedMouseOutFunction = function(){};

var appendedMouseOverFunction = function(){};

var mouseOverFunction = function (d,i){
    d3.select(this).classed("highlight", true).classed("noHighlight", false);
    appendedMouseOverFunction(d,i);
}

var mouseOutFunction = function (d,i){
    d3.select(this).classed("highlight", false).classed("noHighlight", true);
    appendedMouseOutFunction(d,i);
}   

var mouseClick2Function = function (d,i){
    console.log("barchart click function = nothing at the moment, d=",d)
};

function render () {
    updateScalesAndRenderAxes();
    GUP_bars();
}

function updateScalesAndRenderAxes(){
    //Set scales to reflect any change in svgWidth, svgHeight or the dataset size or max value
    xScale
        .domain([0, maxValueOfDataField()])
        .range([0, svgWidth-(yAxisIndent+10)]);
    yScale
        .domain(dataset.map(yAxisCategoryFunction)) //Load y-axis categories into yScale
        .rangeRound([25, svgHeight-40])
        .padding([.1]);

    //Now render the y-axis using the new yScale
    var yAxisGenerator = d3.axisLeft(yScale);
    svg.select(".yAxis")
        .transition().duration(1000).delay(1000)
        .attr("transform", "translate(" + yAxisIndent + ",0)")
        .call(yAxisGenerator);  

    //Now render the x-axis using the new xScale
    var xAxisGenerator = d3.axisTop(xScale);
    svg.select(".xAxis")
        .transition().duration(1000).delay(1000)
        .attr("transform", "translate(" + yAxisIndent + ",20)")
        .call(xAxisGenerator);
};

function GUP_bars(){
    //GUP = General Update Pattern to render bars 

    //GUP: BIND DATA to DOM placeholders
    var selection = svg
        .selectAll(".bars")
        .data(dataset, GUPkeyField);


   //GUP: ENTER SELECTION 
    var enterSel = selection //Create DOM rectangles, positioned @ x=yAxisIndent
        .enter()
        .append("rect")
        .attr("x", yAxisIndent)

    enterSel //Add CSS classes  
        .attr("class", d=>("key--"+GUPkeyField(d)))
        .classed("bars enterSelection", true)
        .classed("highlight", d=>d.highlight)

    enterSel //Size the bars
        .transition()
        .duration(1000)
        .delay(2000)
            .attr("width", function(d) {return xScale(dataField(d));})
            .attr("y", function(d, i) {return yScale(yAxisCategoryFunction(d));})
            .attr("height", function(){return yScale.bandwidth()});

    enterSel //Add tooltip
        .append("title")
            .text(tooltip)


    //GUP UPDATE (anything that is already on the page)
    var updateSel = selection //update CSS classes
        .classed("noHighlight updateSelection", true)
        .classed("highlight enterSelection exitSelection", false)
        .classed("highlight", d=>d.highlight)

    updateSel   //update bars
        .transition()
        .duration(1000)
        .delay(1000)
            .attr("width", function(d) {return xScale(dataField(d));})
            .attr("y", function(d, i) {return yScale(yAxisCategoryFunction(d));})
            .attr("height", function(){return yScale.bandwidth()});

    updateSel //update tool tip
        .select("title") //Note that we already created a <title></title> in the Enter selection
            .text(tooltip)


    //GUP: Merged Enter & Update selections (so we don't write these twice) 
    var mergedSel = enterSel.merge(selection)
        .on("mouseover", mouseOverFunction)
        .on("mouseout", mouseOutFunction)
        .on("click", mouseClick2Function)           


    //GUP EXIT selection 
    var exitSel = selection.exit()
        .classed("highlight updateSelection enterSelection", false)
        .classed("exitSelection", true)
        .transition()
        .duration(1000)
            .attr("width",0)
            .remove() 
};

return barchartObject;'

}

任何帮助将不胜感激,如果我要问的内容不清楚,我会建议。谢谢

1 个答案:

答案 0 :(得分:0)

将输入数据格式化为{key:"",value:""}之类的对象,并将其传递给d3,以便他们可以理解和呈现图表。

var input = {'a':1,"b":2};

function parseData(input){
  return Object.keys(input).reduce(function(output, key){
     output.push({"key":key,"value":input[key]});
     return output;
  },[])
}

console.log(parseData(input));
// [{"key":"a","value":1},{"key":"b","value":2}]

jsFiddle演示-https://jsfiddle.net/1kdsoyg2/1/