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.