当前位置: 动力学知识库 > 问答 > 编程问答 >

d3.js - How to create selection from DOM element itself

问题描述:

In d3.js, if I'm given a CSS selector that uniquely identifies a DOM element, I can create a selection containing only that element, using, for example,

svg.selectAll("g.node#"+d.id)

Suppose that I'm given the DOM element itself, for example, a particular <g> that already exists. Passing the DOM element directly to selectAll or select generates an error, reported as "SyntaxError: An invalid or illegal string was specified" in Firefox, or "Uncaught SyntaxError: Failed to execute 'querySelectorAll' on 'Element': '[object SVGGElement]' is not a valid selector" in Chrome.

How can I create a selection from the reference to DOM element itself? There should be no need to cause D3 to go and search for the element using a CSS selector.

At the moment, I've got working code that gets the appropriate selection by constructing a unique CSS selector, but that seems like unnecessary work, since I already have a reference to the DOM element to which I want to append things.

EDIT:

Thanks to @meetamit and @LarsKotthoff: OK, if it should just work to selectAll on the DOM element, there's something I don't understand about my code (not surprising). I was trying to avoid dumping a lot of code into my SO question, but I don't know what else to do. Here is a fiddle. It doesn't run in jsfiddle, and I don't know why, but it runs just fine without jsfiddle in Firefox, Chrome and Safari. (Here's a fiddle that just contains my entire file in the HTML window.)

My code is supposed to add a little pack layout to each node in a force layout. There may be a purely idiomatic way to do this, but I've only succeded in getting it to work by calling each on the nodes in the force layout, adding the pack layouts from inside a separate function:

var svgnodes = svg.selectAll("g.node")

.data(data.nodes, function (d) {return d.id;})

.enter()

.append("g")

.attr("class", "node")

.attr("id", function (d) {return d.id;})

.call(layout.drag())

.on("click", click);

svgnodes.each(function (d, i) {addPersonCircles(d, svg, this);});

Here's part of the definition of addPersonCircles:

function addPersonCircles (d, svg, personG) {

// makes a data new structure for use by pack layout:

function makeroot (id) {return {"name":name, "children":[{"name":"a"}, {"name":"p"}]};}

// data structure containing three elements, one for each element generated by makeroot()

var pack = d3.layout.pack()

.size([personRadius, personRadius])

.value(function (d) {return 1;})

.nodes(makeroot(d.id));

// KLUDGE. Isn't there a way to select using the dom element personG that was passed in?

svg.selectAll("g.node#"+d.id) // find particular existing g node in person net

.selectAll("circle.person") // create new circles within g node

.data(pack)

.enter()

.append("circle")

...

}

When I add console.log(personG), i.e. display what was this inside of each(), what's displayed is something like this:

<g class="node" id="sandra" transform="translate(263.59494561798255,242.1803122208288)">...</g>

I have been puzzled at times by what this refers to, but here it seems to refer to a DOM node, and nothing else. However when I replace svg.selectAll("g.node#"+d.id) with svg.selectAll(personG), I get the error messages reported above. The result looks like the following. Thanks for any help.

网友答案:

You can turn a DOM node into a D3 selection using d3.select(). You cannot turn a DOM node into a D3 selection using selection.selectAll(). The code you want is

d3.select(personG) 
    .selectAll("circle.person")  // create new circles within g node
    // ...

Note two important points:

  1. The root of the statement is the global d3. not the selection svg.
  2. The selection is made using select() not selectAll()

Meetamit has it exactly correct.

分享给朋友:
您可能感兴趣的文章:
随机阅读: