Skip to content

ZoomableContainer ​

В'юпорт із перетягуванням і масштабуванням у стилі Figma. Покладіть усередину будь-який елемент і керуйте ним жестами. Залишає навколо вмісту відступ у половину в'юпорту, тож можна прокручувати за його краї.

Жести ​

ВвідДія
Прокрутка / 2 пальціПанорамування
Shift + прокруткаГоризонтальне панорамування
Ctrl/Cmd + прокруткаМасштаб у точці курсора
Щипок на трекпадіМасштаб у точці курсора
Перетягування середньою кнопкоюПанорамування будь-де
Space + перетягуванняПанорамування будь-де
Перетягування по фонуПанорамування

Живе демо — власні div ​

Прокручуйте для панорамування, Ctrl/Cmd+прокрутка (або щипок) — масштаб, Space+перетягування чи середня кнопка миші — захоплення.
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

Зображення ​

Canvas усередині ​

Дочірній <canvas> працює як будь-який інший елемент — браузер масштабує його растр. Для піксельно точного рендеру за будь-якого масштабу перемальовуйте canvas під час зміни масштабу.

Використання ​

Базове ​

vue
<template>
  <orio-zoomable-container style="width: 100%; height: 600px;">
    <div style="width: 2000px; height: 1500px;">
      <!-- any content -->
    </div>
  </orio-zoomable-container>
</template>

Із зображенням ​

vue
<template>
  <orio-zoomable-container :min-scale="0.5" :max-scale="10">
    <img src="/large-photo.jpg" alt="" />
  </orio-zoomable-container>
</template>

З canvas ​

vue
<template>
  <orio-zoomable-container>
    <canvas ref="canvasEl" width="1600" height="1200" />
  </orio-zoomable-container>
</template>

Програмне керування ​

vue
<template>
  <orio-zoomable-container ref="zoomRef">
    <div class="board">...</div>
  </orio-zoomable-container>
  <orio-button @click="zoomRef?.resetView()">Reset</orio-button>
</template>

<script setup>
import { useTemplateRef } from "vue";
const zoomRef = useTemplateRef("zoomRef");
</script>

Реакція на масштаб через проп слоту ​

Використовуйте scoped-слот, щоб компенсувати масштаб оверлеїв (наприклад, тримати підписи сталого розміру):

vue
<template>
  <orio-zoomable-container v-slot="{ scale }">
    <div class="board">
      <div class="pin" :style="{ transform: `scale(${1 / scale})` }">
        Always same size
      </div>
    </div>
  </orio-zoomable-container>
</template>

Пропси ​

ПропТипЗа замовчуваннямОпис
minScalenumber0.1Нижня межа масштабу
maxScalenumber10Верхня межа масштабу
initialScalenumber1Рівень масштабу під час монтування
zoomSpeednumber0.0015Множник дельти колеса для масштабу
wheelPanSpeednumber1Множник дельти колеса для панорамування

Події ​

ПодіяДаніОпис
update:scalenumberСпрацьовує під час зміни масштабу
update:translate(x: number, y)Спрацьовує під час панорамування

Слоти ​

СлотПропсиОпис
default{ scale, tx, ty }Вміст для трансформації

Відкриті методи ​

Доступ через ref:

МетодОпис
setScaleAt(scale, px, py)Масштабувати з прив'язкою до точки
panBy(dx, dy)Зсунути на дельту в пікселях
centerWorld()Відцентрувати вміст у в'юпорті
resetView()Скинути масштаб і відцентрувати
scale, tx, tyРеактивні ref поточного стану

Примітки ​

  • В'юпорт залишає навколо вмісту з кожного боку порожній простір у половину свого розміру по осі — панорамувати можна, доки край вмісту не дійде до центру в'юпорту.
  • transform: scale() прискорюється GPU; за нецілих рівнів масштабу текст може виглядати розмитим, але лишається доступним для виділення та скрінрідерів.
  • Дочірні елементи з position: fixed виходять з-під трансформації (обмеження браузера).
  • Координати кліку у світовому просторі: worldX = (clientX - rect.left - tx) / scale.