Я хотел бы использовать useDraggable vueuse с компонентами svg, устанавливая позицию svg вместо использования стиля для перемещения элемента.
Благодаря комментарию yoduh, красный кружок теперь работает, но как лучше всего сделать несколько элементов, сгенерированных с помощью v-for (синие кружочки в примере кода), перетаскиваемыми?
Другой способ задать вопрос: как лучше всего организовать вывод useDraggable для нескольких элементов из v-for? Есть ли способ поместить вывод {x,y}, как показано в красном кружке, в какую-то более крупную структуру данных, которую я могу передать в шаблон? Или как мне заставить работать подход, который я опробовал в примере?
(Я также пока не знаю, как обрабатывать ссылки на шаблоны в этом случае.)
Простой пример:
import { useDraggable } from '@vueuse/core'
import { ref, reactive } from 'vue';
const circs = reactive([]);
for (let i = 0; i < 3; i++) {
const circ = reactive({ x: 10, y: 10, r: 10 });
circs.push(circ);
}
const circRefs = circs.map(() => ref(null));
const redCirc = reactive({ x: 40, y: 40, r: 10 });
const redCircRef = ref(null);
circs.forEach((circ, index) => {
const el = circRefs[index];
useDraggable(el, {
initialValue: { x: circ.x, y: circ.y },
onMove: (x, y) => {
circ.x = x;
circ.y = y;
},
});
});
const {x, y} = useDraggable(redCircRef, {
initialValue: { x: redCirc.x, y: redCirc.y },
onMove: (x, y) => {
redCirc.x = x;
redCirc.y = y;
},
});
<svg>
<circle
v-for = "circ, index in circs"
:cy = "circ.y"
:cx = "circ.x"
:r = "circ.r"
fill = "blue"
ref = "circRefs[index]"
/>
<circle
:cy = "y"
:cx = "x"
:r = "redCirc.r"
fill = "red"
ref = "redCircRef"
/>
</svg>





ref внутри v-for заполняются только при монтировании. Итак, вам нужно будет привязать useDraggable к каждому элементу v-for внутри onMounted().
Начальное значение массива ссылок шаблона должно быть пустым массивом []. Vue подтолкнет ссылки при монтировании. Если вы предварительно заполните массив (например: circs.map(() => ref(null));), после того, как Vue вставит ссылки в массив, вы получите null, за которыми последуют ссылки на шаблоны, и, очевидно, index-ы ссылок на шаблоны не будут соответствовать.
Вот как бы я это написал:
<script lang = "ts" setup>
import { useDraggable } from '@vueuse/core'
import { ref, onMounted } from 'vue'
const circles = ref(
Array.from({ length: 3 }).map(() => ({
cx: 20,
cy: 20,
r: 10
}))
)
const refs = ref([])
onMounted(() => {
refs.value.forEach((el, index) => {
useDraggable(el, {
onMove: ({ x: cx, y: cy }) => {
Object.assign(circles.value[index], { cx, cy })
}
})
})
})
</script>
<template>
<svg
version = "1.1"
width = "400"
height = "320"
xmlns = "http://www.w3.org/2000/svg"
>
<circle
v-for = "(circle, key) in circles"
:key = "key"
v-bind = "circle"
fill = "blue"
ref = "refs"
/>
</svg>
</template>
Рабочая демо .
Примечания:
reactive() вместо ref()s
Ссылка на шаблон должна принимать строковое значение. вы использовали v-bind, чтобы передать ему фактический объект ссылки. должно быть просто
ref = "redCircRef"(нет:перед ссылкой)