feat: add dragging

This commit is contained in:
wancat committed 2024-07-31 18:00:19 +08:00
1 parent 1572b2ea06
commit ca36f6391a
2 files changed
+80 -54

No files matched your search

+75 -54
View File
@@ -1,10 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, watch } from 'vue' import { ref, onMounted, watch } from 'vue'
import { IQuest } from '@linux-odyssey/models'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { useToast } from 'vue-toastification' import { useToast } from 'vue-toastification'
import { DAG } from '@linux-odyssey/utils' import { DAG } from '@linux-odyssey/utils'
import api from '../utils/api' import { getQuests } from '../utils/api'
import useUserProfile from '../store/userProfile' import useUserProfile from '../store/userProfile'
const store = useUserProfile() const store = useUserProfile()
@@ -14,22 +13,12 @@ const toast = useToast()
const svgWidth = ref(window.innerWidth) const svgWidth = ref(window.innerWidth)
const svgHeight = ref(window.innerHeight) const svgHeight = ref(window.innerHeight)
const marginX = 80 const marginX = 100
const marginY = 80 const marginY = 100
const nodeWidth = 150 const nodeWidth = 150
const nodeHeight = 50 const nodeHeight = 50
async function getQuests() {
try {
const res = await api.get<IQuest[]>('/quests')
return res.data
} catch (err) {
console.error(err)
throw err
}
}
type Node = { type Node = {
id: string id: string
title: string title: string
@@ -49,6 +38,28 @@ const graphData = ref<{ nodes: Node[]; edges: Edge[] }>({
edges: [], edges: [],
}) })
const isDragging = ref(false)
const dragStartX = ref(0)
const dragStartY = ref(0)
const offsetX = ref(0)
const offsetY = ref(0)
function startDrag(event: MouseEvent) {
isDragging.value = true
dragStartX.value = event.clientX - offsetX.value
dragStartY.value = event.clientY - offsetY.value
}
function drag(event: MouseEvent) {
if (!isDragging.value) return
offsetX.value = event.clientX - dragStartX.value
offsetY.value = event.clientY - dragStartY.value
}
function endDrag() {
isDragging.value = false
}
async function computeGraphData() { async function computeGraphData() {
if (!store.progress) return if (!store.progress) return
@@ -112,47 +123,57 @@ watch(() => store.progress, computeGraphData, { deep: true })
> >
踏上你的Linux冒險之旅吧! 踏上你的Linux冒險之旅吧!
</h1> </h1>
<svg :width="svgWidth" :height="svgHeight" class="absolute"> <svg
<!-- <g :width="svgWidth"
v-for="edge in graphData.edges" :height="svgHeight"
:key="`${edge.source.id}-${edge.target.id}`" class="absolute"
> @mousedown="startDrag"
<line @mousemove="drag"
:x1="edge.source.x" @mouseup="endDrag"
:y1="edge.source.y" @mouseleave="endDrag"
:x2="edge.target.x" >
:y2="edge.target.y" <g :transform="`translate(${offsetX}, ${offsetY})`">
:stroke="edge.target.unlocked ? '#ADADB5' : '#454552'" <!-- <g
:stroke-dasharray="edge.target.unlocked ? 'none' : '5,5'" v-for="edge in graphData.edges"
stroke-width="3" :key="`${edge.source.id}-${edge.target.id}`"
/>
</g> -->
<g
v-for="node in graphData.nodes"
:key="node.id"
@click="handleNodeClick(node)"
>
<rect
:x="node.x - nodeWidth / 2"
:y="node.y - nodeHeight / 2"
:width="nodeWidth"
:height="nodeHeight"
rx="10"
ry="10"
:fill="
node.completed ? '#00bb00' : node.unlocked ? '#ADADB5' : '#505050'
"
/>
<text
:x="node.x"
:y="node.y"
text-anchor="middle"
alignment-baseline="middle"
fill="white"
font-size="16"
> >
{{ node.title }} <line
</text> :x1="edge.source.x"
:y1="edge.source.y"
:x2="edge.target.x"
:y2="edge.target.y"
:stroke="edge.target.unlocked ? '#ADADB5' : '#454552'"
:stroke-dasharray="edge.target.unlocked ? 'none' : '5,5'"
stroke-width="3"
/>
</g> -->
<g
v-for="node in graphData.nodes"
:key="node.id"
@click="handleNodeClick(node)"
>
<rect
:x="node.x - nodeWidth / 2"
:y="node.y - nodeHeight / 2"
:width="nodeWidth"
:height="nodeHeight"
rx="10"
ry="10"
:fill="
node.completed ? '#00bb00' : node.unlocked ? '#ADADB5' : '#505050'
"
/>
<text
:x="node.x"
:y="node.y"
text-anchor="middle"
alignment-baseline="middle"
fill="white"
font-size="16"
>
{{ node.title }}
</text>
</g>
</g> </g>
</svg> </svg>
</div> </div>
+5
View File
@@ -43,3 +43,8 @@ export async function getActiveSession(
}) })
return res.data return res.data
} }
export async function getQuests(): Promise<IQuest[]> {
const res = await api.get<IQuest[]>('/quests')
return res.data
}