D3 Как сохранить размер элемента при преобразовании масштаба / перевода

Этот пример иллюстрирует мою проблему: https://bl.ocks.org/feketegy/ce9ab2efa9439f3c59c381f567522dd3

У меня есть несколько путей в элементе группы, и я хочу панорамировать / масштабировать эти элементы, кроме синего прямоугольника, который находится в другом элементе группы.

Увеличение и панорамирование осуществляется путем применения transform="translate(0,0) scale(1) к внешнему элементу самой группы, затем захватывает дельту масштабирования и применяет ее к same-size элемент группы, чтобы сохранить его в том же размере.

Это работает, но позиция синего прямоугольника, которая должна оставаться того же размера, испорчена, я хотел бы сохранить ее в той же относительной позиции к другим путям.

Визуализированная структура HTML выглядит следующим образом:

<svg width="100%" height="100%">
  <g class="outer-group" transform="translate(0,0)scale(1)">
    <path d="M100,100 L140,140 L200,250 L100,250 Z" fill="#cccccc" stroke="#8191A2" stroke-width="2px"></path>
    <path d="M400,100 L450,100 L450,250 L400,250 Z" fill="#cccccc" stroke="#8191A2" stroke-width="2px"></path>

    <g class="same-size-position" transform="translate(300,250)">
      <g class="same-size" transform="scale(1)">
        <path d="M0,0 L50,0 L50,50 L0,50 Z" fill="#0000ff"></path>
      </g>
    </g>
  </g>
</svg>

Я пытался получить положение X/Y same-size-position сгруппировать и создать дельту из перевода х / у outer-group, но это не похоже на работу.

1 ответ

Решение

После того, как я отряхнул свои школьные учебники по геометрии, я нашел решение.

Вам нужно получить ограничивающий прямоугольник элемента, размер которого вы хотите сохранить, и рассчитать для него преобразование матрицы следующим образом:

const zoomDelta = 1 / d3.event.transform.k;

const sameSizeElem = d3.select('.same-size');
const bbox = sameSizeElem.node().getBBox();

const cx = bbox.x + (bbox.width / 2);
const cy = bbox.y + (bbox.height / 2);
const zx = cx - zoomDelta * cx;
const zy = cy - zoomDelta * cy;

sameSizeElem
  .attr('transform', 'matrix(' + zoomDelta + ', 0, 0, ' + zoomDelta + ', ' + zx + ', ' + zy + ')');

Преобразование матрицы сохранит относительную позицию элемента, размер которого останется прежним, а остальные элементы будут панорамировать / масштабировать.

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