D3 js set data from data-attribute

元气小坏坏 提交于 2019-12-14 04:19:25

问题


During creating graphs I need to set data. Those data(Array of Objects) I have already in HTML like this:

<svg  class="graph-n" data-stuff="{simplified data}"></svg>

Then with Javascript and D3 JS I initialize and setup graphs with the following code:

<script>
    var margin = { top: 20, right: 20, bottom: 30, left: 50},
        width = 1500 - margin.left - margin.right,
        height = 350 - margin.top - margin.bottom;

    var x = d3.scaleTime().range([0, width]);
    var y = d3.scaleLinear().range([height, 0]);


    var valueline = d3.line()
        .x(function(d) { return x(new Date(d.t)); })
        .y(function(d) { return y(d.y); });

    var svg = d3.selectAll(".graph-n")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");


        x.domain(d3.extent(data, function(d) { return new Date(d.t); }));
        y.domain([0, d3.max(data, function(d) { return d.y; })]);

        svg.append("path")
            .attr("class", "line")
            .attr("d", valueline);

        svg.append("g")
            .attr("transform", "translate(0," + height + ")")
            .call(d3.axisBottom(x));

        svg.append("g")
            .call(d3.axisLeft(y));
</script>

The question is how shall I say, that data are inside each element during Selection in data attribute 'data-stuff' ? Each SVG has data to plot in his own data attribute.

Or is my approach wrong and I shall use different approach?

Thank you for your responses.


回答1:


There is no way to just tell d3 explicitly "take data from this attribute". You can however set the data programatically, loading it from the attribute of your choosing. There are several ways on how to achieve it, as demonstrated on these selection examples (they use <ul> and <li> for simplicity, <svg> is usage is analogous):

// the pure D3 way
d3.selectAll("ul.d3-pure")                // select the element
    .datum(function() { return this.getAttribute("data-list").split(",")}) // set selection's data based on its data attribute
    .selectAll("li")                      // create new selection
        .data((d) => d)                   // set the data from the parent element
        .enter().append("li")             // create missing elements
            .text((content) => content);  // set elements' contents

// the DOM way      
var domUls = document.querySelectorAll("ul.dom");     // select elements
for(var i = 0; i < domUls.length; i++) {              // iterate over those elements
    const ul = domUls[i];
    const d3_ul = d3.select(ul);                      // create D3 object from the node
    const data = ul.getAttribute("data-list").split(",");
    d3_ul.selectAll("li").data(data)                  // create new selection and assign its data
        .enter().append("li")                         // create missing elements
            .text((content) => content)               // set elements' content
}

// the hybrid D3-DOM way
d3.selectAll("ul.d3-hybrid")                // select elements
    .each(function() {                      // iterate over each node of the selection
        const ul = d3.select(this);         // "this" is the "ul" HTML node
        const data = ul.attr("data-list").split(",");
        ul.selectAll("li").data(data)       // create new selection, assign its data
            .enter().append("li")           // create missing elements
                .text((content) => content) // set elements' content
        });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<ul class="d3-pure" data-list="1,2,3">
</ul>
<ul class="dom" data-list="a,b,c">
</ul>
<ul class="d3-hybrid" data-list="I,II,III">
</ul>



回答2:


Modern browsers accepts node().dataset

Using D3_selection.node() and pure Javascript's DOM-node dataset property, as commented by @altocumulus before.

It is an old Javascript standard for HTML elements (since Chorme 8 and Firefox 6) but new for SVG (since Chorme 55 and Firefox 51).

The values of dataset's key-values are pure strings, but a good practice is to adopt JSON string format for non-string datatypes, to parse it by JSON.parse().

Using it

Code snippet to get and set key-value datasets at HTML and SVG.

console.log("-- GET values --")
var x = d3.select("#html_example").node().dataset;
console.log("s:", x.s );
for (var i of JSON.parse(x.list)) console.log("list_i:",i)

var y = d3.select("#svg_example g").node().dataset;
console.log("s:", y.s );
for (var i of JSON.parse(y.list)) console.log("list_i:",i)

console.log("-- SET values --");
y.s="BYE!"; y.list="null";
console.log( d3.select("#svg_example").node().innerHTML )
<script src="https://d3js.org/d3.v5.min.js"></script>
<p id="html_example" data-list="[1,2,3]" data-s="Hello123">Hello dataset!</p>
<svg id="svg_example">
  <g data-list="[4,5,6]" data-s="Hello456 SVG"></g>
</svg>


来源:https://stackoverflow.com/questions/50391062/d3-js-set-data-from-data-attribute

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!