Как вы переводите элементы HTML вместе с элементами SVG при масштабировании и панорамировании с помощью D3 - PullRequest
0 голосов
/ 10 сентября 2018

Я использую D3, чтобы нарисовать группу элементов на холсте SVG, а также всплывающую подсказку в html. Затем я использую zoom, чтобы разрешить панорамирование / масштабирование на холсте. Я хочу, чтобы подсказки следовали за положением кружков. Кажется, я не могу понять, как это вычислить.

Соответствующий код

const svg = select('svg');

const width = +svg.attr('width');
const height = +svg.attr('height');

// Define the div for the tooltip
const tooltip = select('body')
  .append('div')
  .attr('class', 'tooltip')
  .style('opacity', 0);

const g = svg.append('g')
  .attr('width', width)
  .attr('height', height);


const zoomHandler = zoom()
  .scaleExtent([1 / 10, 100])
  .on('zoom', () => {
    g.attr('transform', event.transform);
    const { x, y, k } = event.transform;
    tooltip.attr('data-offset-x', x);
    tooltip.attr('data-offset-y', y);
    tooltip.attr('data-offset-k', k);
  });

zoomHandler(svg);

let overTooltip = false;

const moveTooltip = (d) => {
  if (!overTooltip) return;
  tooltip.transition()
    .duration(100)
    .style('opacity', 0.9);

  const x = parseInt(tooltip.attr('data-offset-x') || 0, 10);
  const y = parseInt(tooltip.attr('data-offset-y') || 0, 10);
  const k = parseInt(tooltip.attr('data-offset-k') || 0, 10);
  tooltip.html(d.id)
    .style('left', `${(d.x / k + x)}px`)
    .style('top', `${(d.y / k + y - radius(d) - 5)}px`);
};

const node = g.append('g')
  .selectAll('circle')
  .data(nodes)
  .enter()
  .append('circle')
  .attr('r', radius)
  .attr('fill', d => (colors[d.type]))
  .on('mouseover', (d) => {
    overTooltip = true;
    moveTooltip(d);
  })
  .on('mousemove', moveTooltip)
  .on('mouseout', () => {
    overTooltip = false;
    tooltip.transition()
      .duration(100)
      .style('opacity', 0);
  })

1 Ответ

0 голосов
/ 10 сентября 2018

Разобрался! Использование getBoundingClientRect() на this возвращает абсолютную позицию SVG-элемента

function onMouseOverCircle(d) {
  const {
    x, y, width,
  } = this.getBoundingClientRect();

  tooltip.transition()
    .duration(100)
    .style('opacity', 0.9);

  tooltip.html(d.id)
    .style('left', `${x + width / 2}px`)
    .style('top', `${y - 10}px`);
}

const node = g.append('g')
  .attr('stroke', '#fff')
  .attr('stroke-width', 1.5)
  .selectAll('circle')
  .data(nodes)
  .enter()
  .append('circle')
  .attr('r', radius)
  .attr('fill', d => (colors[d.type]))
  .on('mouseover', onMouseOverCircle)
  .on('mouseout', () => {
    tooltip.transition()
      .duration(100)
      .style('opacity', 0);
  })
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...