Я пытаюсь добавить «g» в случайные места внутри svg. Ниже мой код. Удивительно, но все 10 'g рисуются в одной и той же позиции. Я указал случайную позицию в строке 5, но все g получили одинаковые x и y. Что я делаю не так?
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))
Если второй параметр .attr()
или .style()
является функцией, .attr()
/.style()
выполнит ее один раз для каждого элемента в выборе. Если второй параметр оценивается как строка или число (некоторое постоянное значение), это постоянное значение будет передано в .attr()
/.style()
. В любом случае .attr()
и .style()
вызываются только один раз.
Ваш код попадает во второй случай: вы не передаете функцию .attr()
, вы передаете одну строку:
`translate(${d3.randomInt(padding, width-padding)()},${d3.randomInt(padding, height-padding)()})`
Вы не можете передать эту строку кода без оценки какому-либо методу или функции, она должна быть оценена, а затем передана методу .attr()
. Поскольку метод .attr()
вызывается только один раз, вы получаете только одно случайное число.
Если вы создали функцию для получения случайной строки:
function random() {
return `translate(${d3.randomInt(padding, width-padding)()},${d3.randomInt(padding, height-padding)()})`
}
Вы делаете эквивалент:
select.attr("translate", random()); // pass the return value to .attr (a string)
Но то, что вы хотите сделать, это передать саму функцию:
select.attr("translate", random); // pass the function itself to .attr so it can execute it
Этот метод по-прежнему выполняется только один раз, но внутри он будет вызывать random
для каждого элемента в выборе.
Итак, вы можете сделать, как указано выше, или использовать анонимную функцию:
selection.attr("translate",function() { /* return random translate */ })
Большое спасибо за ваш подробный ответ. Вы не только ответили, но и указали на проблему. Еще раз спасибо!