简体   繁体   中英

How Do I iterate through d3.select(this)

I'm afraid I still don't understand d3-object.
I created d3-elements and assigned select.on("mouseover", onGraphicMouseOver) events to them.
Now I'm in my function and have this .

If I log this I get my straight svg-string:

<g id="a29" style="touch-action: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">
  <line class="hotwater graphic" x1="270" y1="110" x2="540" y2="110" id="g29"></line>
  <line class="hotwater graphic" x1="270" y1="120" x2="540" y2="120"></line>
</g>

So far, so fine.

Now I want to wark with the lines, like assigning classes to them and for this, I want to iterate through them.
What is the best way to do?

My first idea:

for (var i = 0; i < this.childNodes.length; i++) {
    this.childNodes[i].classList.add("graphicmouseover");
}

But isn't there a simpler way, using d3.js.
And if so, how can I find such informations by myself. I now played around with d3 since many weeks but don't have a really complete idea of the concept. Perhaps someone knows a more informative documentation than the original, for a dumb like me :(
I really appreciate a helpful hint, so I don't have to annoy you with these noob-questions.

Thanks Carsten

Update because of request: I load the svg-string of the inner element (here both lines) as text out of a database. Then:

function loadGraphicIntoEditor(svgGraphics, editor) {
//svgGraphics are the json-recordsets, editor is the d3.selected svg-area

  for (var i = 0; i < svgGraphics.length; i++) {
    var graphic = svgGraphics[i];

    const graph = editor.append("g")             //appending the g-tag to the svg-area
        .attr("id", "a" + graphic.Id.toString())
        .html(graphic.SvgString)                 //the string <line...></line>
        .on("mouseenter", onGraphicMouseEnter)
        .on("mouseover", onGraphicMouseOver)
        .on("mouseout", onGraphicMouseOut)
        .on("mousedown", onGraphicMouseDown)
        .on("dblclick", onGraphicDblClick)
        .on("contextmenu", onGraphicContext)
        .call(d3.drag()
            .on("start", graphicDragStart)
            .on("drag", graphicDragging)
            .on("end", graphicDragEnd));
    d3.select(graph.node().childNodes[0]).attr("id", "g" + graphic.Id.toString());
  }
}

FINAL UPDATE:

This is my solution now:

function onGraphicMouseOver(d, i) {
    d3.select(this).selectAll('.graphic').classed("graphicmouseover", true);
}

...life could be so easy :)

thank you guys

Try something like:

 var lines = d3.selectAll('line.hotwater'); //console.log(lines); lines.each(function(d,i) { //console.log(i, d, this); //console.log(this); d3.select(this) .attr("stroke", "black") .attr("stroke-width", "5px") })
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <svg width="1000" height="1000" style="background:#ff0000"> <g id="a29" style="touch-action: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"> <line class="hotwater graphic" x1="270" y1="110" x2="540" y2="110" id="g29"></line> <line class="hotwater graphic" x1="270" y1="120" x2="540" y2="120"></line> </g> </svg>

Output:

在此处输入图片说明

NOTE: I set the svg background to red in the HTML

But then I used d3.selectAll('line.hotwater'); to select both of our lines. And then used lines.each() to loop over them. And used d3.select(this) to turn that into a d3 selection which we can then modify like usual:

d3.select(this)
    .attr("stroke", "black")
    .attr("stroke-width", "5px")

This adds the black stoke and the 5px stroke width to the lines so that we see them on the svg.

I am using d3.js V5.x here but I think the API has been like this for a few versions.

Update: as OP clarified

Easiest method is just to use d3's selectAll:

select(this).selectAll('.graphic').classed("graphicmouseover", true);

This is essentially doing a descendent querySelectorAll of “this” (from the event) and then looping over and setting the class for each of those selected. D3 manages this for us with its select all.

Update after understanding the OP's problem more fully.

Problem is that the events are attached to the group and not the lines.

But I think there is a way to achieve this with a pattern like:

const graph = editor.append("g")             //appending the g-tag to the svg-area
        .attr("id", "a" + graphic.Id.toString())
        .html(graphic.SvgString);                 //the string <line...></line>

    console.log(graph.selectAll('line.graphic').size()); //gives the size of the selection

    graph.selectAll('line.graphic')
        // .attr('stroke', 'blue')
        .on('click', onClick);

I tried to make a minimal reproducible example from the OP's code here: https://codepen.io/Alexander9111/pen/MWwmVLr

Also here:

 const svgGraphics = [ { Id: '29', SvgString: `<line class="hotwater graphic" x1="270" y1="110" x2="540" y2="110" id="g29"></line> <line class="hotwater graphic" x1="270" y1="120" x2="540" y2="120"></line>` } ] const editor = d3.select('svg'); loadGraphicIntoEditor(svgGraphics, editor); function onClick(d,i){ console.log('clicked'); //console.log(this); //or console.log(event.target); } function loadGraphicIntoEditor(svgGraphics, editor) { //svgGraphics are the json-recordsets, editor is the d3.selected svg-area for (var i = 0; i < svgGraphics.length; i++) { var graphic = svgGraphics[i]; const graph = editor.append("g") //appending the g-tag to the svg-area .attr("id", "a" + graphic.Id.toString()) .html(graphic.SvgString); //the string <line...></line> console.log(graph.selectAll('line.graphic').size()); graph.selectAll('line.graphic') // .attr('stroke', 'blue') .on('click', onClick); // .on("mouseenter", onGraphicMouseEnter) // .on("mouseover", onGraphicMouseOver) // .on("mouseout", onGraphicMouseOut) // .on("mousedown", onGraphicMouseDown) // .on("dblclick", onGraphicDblClick) // .on("contextmenu", onGraphicContext) // .call(d3.drag() // .on("start", graphicDragStart) // .on("drag", graphicDragging) // .on("end", graphicDragEnd)); d3.select(graph.node().childNodes[0]).attr("id", "g" + graphic.Id.toString()); } }
 line { stroke: black; stroke-width: 5px; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <svg width="1000" height="1000" style="background:#ff0000"> </svg>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM