问题
I am trying to append 'g' in random locations within an svg. Below is my code. Surprisingly, all the 10 'g's are being drawn on the same position. I specified random position in line 5 but all g got the same x and y. What am I doing wrong?
const art = svg.selectAll('g')
.data(d3.range(10))
.enter()
.append('g')
.attr("transform", `translate(${d3.randomInt(padding, width-padding)()},${d3.randomInt(padding, height-padding)()})`) //this line
.selectAll('snowflake')
.data(d3.range(6))
.enter()
.append('line')
.style("stroke", "lightblue")
.style("stroke-width", 5)
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", d=>r*Math.cos(d*Math.PI/3))
.attr("y2", d=>r*Math.sin(d*Math.PI/3))
回答1:
If the second parameter of .attr() or .style() is a function, .attr()/.style() will execute it once for every element in the selection. If the second parameter evaluates to be a string or a number (some constant value), that constant value will be passed to .attr()/.style(). Either way, the .attr() and .style() are called only once.
Your code falls into the second case: you aren't passing a function to .attr(), you are passing a single string:
`translate(${d3.randomInt(padding, width-padding)()},${d3.randomInt(padding, height-padding)()})`
You cannot pass this line of code unevaluated to any method or function, it must be evaluated and then passed to the .attr() method. As the .attr() method is called only once, you only get one random number.
If you had created a function to get you your random string:
function random() {
return `translate(${d3.randomInt(padding, width-padding)()},${d3.randomInt(padding, height-padding)()})`
}
You are doing the equivalent of:
select.attr("translate", random()); // pass the return value to .attr (a string)
But what you want to be doing is passing the function itself:
select.attr("translate", random); // pass the function itself to .attr so it can execute it
This method is still only executed once, but internally it will call random for each element in the selection.
So you can do like the above, or use an anonymous function:
selection.attr("translate",function() { /* return random translate */ })
来源:https://stackoverflow.com/questions/65272426/random-translation-in-d3-js