demo-int-table/front/src/components/Gallery/gallery.vue

94 lines
3.0 KiB
Vue

<script setup lang="ts">
import * as d3 from "d3"
import { onMounted } from "vue"
import { IMAGE_URL } from '../../constants'
const props = defineProps(['files'])
onMounted(async () => {
const files = props.files
// const width = 1920
// const height = 1080
const width = window.innerWidth
const height = window.innerHeight
const svg = d3.select('#gallery').append("svg")
.attr("viewBox", [0, 0, width, height])
.attr("stroke-width", 2);
var defs = svg.append('svg:defs');
files.forEach((element: any, i: number) => {
// const src = element[1].default
const src = `${IMAGE_URL}/${element.file}`
defs.append("svg:pattern")
.attr("id", `img${i}`)
.attr("width", width)
.attr("height", height)
.attr("patternUnits", "userSpaceOnUse")
.attr("preserveAspectRatio", "none")
.append("svg:image")
.attr("xlink:href", src)
.attr("width", width)
.attr("height", height)
.attr("x", 0)
.attr("y", 0);
});
const range = files.length + 2
const circles = d3.range(range).map(() => ({
x: Math.random() * width,
y: Math.random() * height,
}));
let voronoi = d3.Delaunay
.from(circles, d => d.x, d => d.y)
.voronoi([0, 0, width, height]);
const circle = svg.append("g")
.selectAll("circle")
.data(circles)
.join("circle")
.attr("cx", d => d.x)
.attr("cy", d => d.y)
.attr("r", 0)
.attr("fill", 'none');
const mesh = svg.append("path")
.attr("fill", "none")
.attr("stroke", "#ccc")
.attr("stroke-width", 0)
.attr("d", voronoi.render());
const cell = svg.append("g")
.attr("fill", "none")
.attr("pointer-events", "all")
.selectAll("path")
.data(circles)
.join("path")
.attr("d", (d, i) => voronoi.renderCell(i))
.attr('fill', (d, i) => i < (range - 2) ? `url(#img${i})` : 'none')
.call(d3.drag()
.on("start", (event, d) => circle.filter(p => p === d).raise().attr("stroke", "black"))
.on("drag", (event, d: any) => (d.x = event.x, d.y = event.y))
.on("end", (event, d) => circle.filter(p => p === d).attr("stroke", null))
.on("start.update drag.update end.update", update) as any)
function update() {
voronoi = d3.Delaunay.from(circles, d => d.x, d => d.y).voronoi([0, 0, width, height]);
circle.attr("cx", d => d.x).attr("cy", d => d.y);
cell.attr("d", (d, i) => voronoi.renderCell(i));
mesh.attr("d", voronoi.render());
}
if (document.querySelector('.pin')) {
const rect = (document.querySelector('.pin') as HTMLElement).getBoundingClientRect()
circles[circles.length - 1] = { x: rect.x + rect.width, y: rect.y + rect.height }
circles[circles.length - 2] = { x: rect.x, y: rect.y }
update()
}
})
</script>
<template>
<div id="gallery"></div>
</template>