Вызов функции для подачи .attr() в d3

У меня есть .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 в демо

Итак, вы не хотите писать повторяющуюся логику, если я правильно ее понимаю?

shrys 03.02.2023 12:36

правильно... как видите, для каждого атрибута их много. Нужно втянуть в функцию

Tom Rudge 03.02.2023 12:42
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
2
55
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете переместить свою логику в такую ​​функцию:

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 происходит только один раз для каждого элемента. В вашем конкретном случае это не тяжелые вычисления, но когда это так, это хорошая идея, уменьшающая нагрузку на браузер.

Другие вопросы по теме