120 lines
3.9 KiB
Vue
120 lines
3.9 KiB
Vue
<script setup lang="ts">
|
|
import type { FileUploadUploadEvent } from '~/node_modules/primevue/fileupload/FileUpload.d.ts'
|
|
import PF, { Grid } from 'pathfinding'
|
|
|
|
interface SvgContext {
|
|
array: number[][],
|
|
paths: string[],
|
|
width: number,
|
|
height: number
|
|
}
|
|
const config = useRuntimeConfig()
|
|
const plan: Ref<SvgContext | {}> = useState('plan', () => ({}));
|
|
|
|
const loading = ref<boolean>(false)
|
|
|
|
const canvasElement: Ref<HTMLCanvasElement | undefined> = ref();
|
|
const context: Ref<CanvasRenderingContext2D | undefined> = ref();
|
|
|
|
const grid = ref<Grid>()
|
|
const startPoint = ref<number[]>()
|
|
const endPoint = ref<number[]>()
|
|
const startToEndPath = ref()
|
|
|
|
const chunkSize = 2
|
|
|
|
const beforeUpload = () => {
|
|
loading.value = true
|
|
}
|
|
|
|
const onUpload = (event: FileUploadUploadEvent) => {
|
|
try {
|
|
const data = JSON.parse(event.xhr.response)
|
|
plan.value = data.response
|
|
newDraw()
|
|
loading.value = false
|
|
} catch (error) {
|
|
console.log(error)
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const newDraw = () => {
|
|
startPoint.value = undefined
|
|
endPoint.value = undefined
|
|
startToEndPath.value = undefined
|
|
|
|
context.value = canvasElement.value?.getContext('2d') || undefined;
|
|
const lines = (plan.value as SvgContext).array
|
|
lines.forEach((line, indexY) => {
|
|
line.forEach((point, indexX) => {
|
|
if (canvasElement.value && context.value) {
|
|
context.value.fillStyle = point > 0 ? 'red' : 'WHITE'
|
|
context.value.fillRect(indexX, indexY, 1, 1)
|
|
}
|
|
})
|
|
});
|
|
|
|
// const t = [...chunks(lines, chunkSize)].map(y => y.map(x => x.some(i => i > 0) > 0 ? 1 : 0))
|
|
// console.log(t)
|
|
|
|
grid.value = new PF.Grid((plan.value as SvgContext).array.map(y => y.map(x => x > 0 ? 1 : 0)))
|
|
}
|
|
|
|
const setPoint = (event: MouseEvent) => {
|
|
try {
|
|
if (!event.currentTarget) return
|
|
const target = (<HTMLCanvasElement>event.currentTarget)
|
|
const bound = target.getBoundingClientRect()
|
|
|
|
const targetX = event.x - bound.x
|
|
const targetY = event.y - bound.y
|
|
|
|
const ctx = (context.value as CanvasRenderingContext2D)
|
|
|
|
if (!startPoint.value) {
|
|
startPoint.value = [targetX, targetY]
|
|
ctx.fillStyle = 'rgb(0,255,0,0.75)';
|
|
ctx.beginPath();
|
|
ctx.arc(targetX, targetY, 10, 0, 2 * Math.PI);
|
|
ctx.fill();
|
|
} else
|
|
if (!endPoint.value) {
|
|
endPoint.value = [targetX, targetY]
|
|
ctx.fillStyle = 'rgb(0,0,255,0.75)';
|
|
ctx.beginPath();
|
|
ctx.arc(targetX, targetY, 10, 0, 2 * Math.PI);
|
|
ctx.fill();
|
|
|
|
const finder = new PF.DijkstraFinder();
|
|
|
|
startToEndPath.value = finder.findPath(
|
|
Math.round(startPoint.value[0]),
|
|
Math.round(startPoint.value[1]),
|
|
Math.round(endPoint.value[0]),
|
|
Math.round(endPoint.value[1]),
|
|
(grid.value as Grid)
|
|
);
|
|
startToEndPath.value.forEach((element: number[]) => {
|
|
ctx.fillRect(element[0], element[1], 1, 1)
|
|
});
|
|
} else {
|
|
newDraw()
|
|
}
|
|
} catch (error) {
|
|
console.log(error)
|
|
}
|
|
}
|
|
</script>
|
|
<template>
|
|
<div class="flex flex-col gap-4">
|
|
<Panel header="Загрузка файла">
|
|
<FileUpload mode="basic" name="demo" :url="`${config.public.apiBase}/api/floorplan`" accept="image/*"
|
|
:maxFileSize="10000000" @upload="onUpload" @before-upload="beforeUpload" :auto="true"
|
|
chooseLabel="Выберите файл" :disabled="loading" />
|
|
</Panel>
|
|
<Panel :header="loading ? `Идет отрисовка` : `Отрисовка из массива значений`">
|
|
<canvas ref="canvasElement" :width="1200" height="400" @click="setPoint"></canvas>
|
|
</Panel>
|
|
</div>
|
|
</template> |