У меня есть .attr
, которые создают мои пути ссылок в d3, как показано ниже, строки 42 в демо :
link.each(function (d){})
.attr('x1', function (d) {
return d.source.x;
})
.attr('y1', function (d) {
return d.source.y;
})
.attr('x2', function (d) {
return d.target.x;
})
.attr('y2', function (d) {
return d.target.y;
});
Вышеприведенное рисует мои ссылки на пути. Я изменил это, чтобы рассчитать уменьшение путей ссылок. Однако существует много повторяющейся логики, и я не уверен, как вызвать функцию, чтобы вернуть требуемые значения. Как показано ниже:
link.attr("x1", function(d) {
// Total difference in x and y from source to target
let diffX = d.target.x - d.source.x;
let diffY = d.target.y - d.source.y;
// Length of path from center of source node to center of target node
let pathLength = Math.sqrt((diffX * diffX) + (diffY * diffY));
// x and y distances from center to outside edge of target node
let offsetX = (diffX * 40) / pathLength;
return d.source.x + offsetX;
}).attr("y1", function(d) {
let diffX = d.target.x - d.source.x;
let diffY = d.target.y - d.source.y;
let pathLength = Math.sqrt((diffX * diffX) + (diffY * diffY));
let offsetY = (diffY * 40) / pathLength;
return d.source.y + offsetY;
}).attr("x2", function(d) {
let diffX = d.target.x - d.source.x;
let diffY = d.target.y - d.source.y;
let pathLength = Math.sqrt((diffX * diffX) + (diffY * diffY));
let offsetX = (diffX * 40) / pathLength;
return d.target.x - offsetX;
}).attr("y2", function(d) {
let diffX = d.target.x - d.source.x;
let diffY = d.target.y - d.source.y;
let pathLength = Math.sqrt((diffX * diffX) + (diffY * diffY));
let offsetY = (diffY * 40) / pathLength;
return d.target.y - offsetY;
})
Он возвращает offsetX
для значений d.source.x
/d.target.x
и offsetY
для d.source.y
/d.target.y
.
В идеале я не хочу всей этой повторяющейся логики и пытался сделать .call()
ссылку, которая переходит в функцию, но тогда я не знаю, как вернуть результат в сами атрибуты, например.
.attr('x1', function (d) {
return d.source.x; //function return from .call()
})
Я также пытался поместить вызов функции в указанный выше атрибут, но получаю сообщение об ошибке «не является функцией», например
.attr('x1', function (d) {
return this.myNewPathFunction(d);
})
Строки 42 в демо
правильно... как видите, для каждого атрибута их много. Нужно втянуть в функцию
Вы можете переместить свою логику в такую функцию:
const coordinate = (position, d, index, nodes) => {
// Total difference in x and y from source to target
let diffX = d.target.x - d.source.x;
let diffY = d.target.y - d.source.y;
// Length of path from center of source node to center of target node
let pathLength = Math.sqrt(diffX * diffX + diffY * diffY);
// x and y distances from center to outside edge of target node
let offsetX = (diffX * 40) / pathLength;
let offsetY = (diffY * 40) / pathLength;
if (position === 'x1') return d.source.x + offsetX;
if (position === 'y1') return d.source.y + offsetY;
if (position === 'x2') return d.target.x - offsetX;
if (position === 'y2') return d.target.y - offsetY;
};
link
.attr('x1', (d, i, nodes) => coordinate('x1', d, i, nodes))
.attr('y1', (d, i, nodes) => coordinate('y1', d, i, nodes))
.attr('x2', (d, i, nodes) => coordinate('x2', d, i, nodes))
.attr('y2', (d, i, nodes) => coordinate('y2', d, i, nodes));
Ваша цель — писать меньше строк повторяющегося кода и уменьшать количество необходимых вычислений.
Одно из идиоматических решений D3 использует selection.each()
;
Таким образом, в вашем случае:
link.each(d, i, n) {
// Total difference in x and y from source to target
let diffX = d.target.x - d.source.x;
let diffY = d.target.y - d.source.y;
// Length of path from center of source node to center of target node
let pathLength = Math.sqrt(diffX * diffX + diffY * diffY);
// x and y distances from center to outside edge of target node
let offsetX = (diffX * 40) / pathLength;
let offsetY = (diffY * 40) / pathLength;
d3.select(n[i])
.attr("x1", d.source.x + offsetX)
.attr("y1", d.source.y + offsetY)
.attr("x2", d.target.x - offsetX)
.attr("y2", d.target.y - offsetY);
};
Обратите внимание, что вычисление offsetX
и offsetY
происходит только один раз для каждого элемента. В вашем конкретном случае это не тяжелые вычисления, но когда это так, это хорошая идея, уменьшающая нагрузку на браузер.
Итак, вы не хотите писать повторяющуюся логику, если я правильно ее понимаю?