feat: ts
This commit is contained in:
parent
656de5b2b3
commit
4146933039
|
|
@ -8,8 +8,7 @@
|
|||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
<script type="module" src="node_modules/hover-tilt/dist/hover-tilt.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
2874
package-lock.json
generated
2874
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
|
@ -1,13 +1,20 @@
|
|||
<script setup lang="ts">
|
||||
import { useEditorStore } from '@/stores/editor';
|
||||
|
||||
const store = useEditorStore();
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
img {
|
||||
width: 400px;
|
||||
display: block;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<hover-tilt :width="200">
|
||||
<img src="https://images.pokemontcg.io/swsh4/25_hires.png" />
|
||||
<hover-tilt>
|
||||
<img
|
||||
src="https://images.pokemontcg.io/swsh4/25_hires.png"
|
||||
:style="store.imageStyle"
|
||||
/>
|
||||
</hover-tilt>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,35 +1,19 @@
|
|||
<script lang="ts" setup>
|
||||
import { folders } from "@/const/editor"
|
||||
import { onMounted, ref, reactive } from 'vue'
|
||||
import * as Tweakpane from 'tweakpane'
|
||||
|
||||
const Pane = Tweakpane.Pane
|
||||
import { useEditorStore } from "@/stores/editor"
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { Pane } from 'tweakpane'
|
||||
const editorStore = useEditorStore()
|
||||
|
||||
const paneContainer = ref<HTMLDivElement | null>(null)
|
||||
let pane: any = null
|
||||
|
||||
// 创建响应式数据对象来存储表单值
|
||||
const formData = reactive<Record<string, any>>({})
|
||||
|
||||
// 初始化表单数据
|
||||
function initializeFormData() {
|
||||
folders.flatMap(f => f.type === 'folder' ? f.children : []).forEach((item: any) => {
|
||||
formData[item.label] = item.value
|
||||
})
|
||||
}
|
||||
|
||||
// 创建 tweakpane 面板
|
||||
function createPane() {
|
||||
function createPane(container: HTMLDivElement) {
|
||||
if (!paneContainer.value) return
|
||||
|
||||
// 清理旧的 pane
|
||||
if (pane) {
|
||||
pane.dispose()
|
||||
}
|
||||
|
||||
pane = new Pane({
|
||||
container: paneContainer.value
|
||||
})
|
||||
const pane = new Pane({ container })
|
||||
|
||||
// 遍历 folders 并创建对应的控制项
|
||||
folders.forEach(folder => {
|
||||
|
|
@ -40,15 +24,17 @@ function createPane() {
|
|||
})
|
||||
|
||||
folder.children.forEach((item: any) => {
|
||||
f.addBinding(formData, item.label, item.params)
|
||||
f.addBinding(editorStore.formData, item.label, item.params)
|
||||
})
|
||||
} else {
|
||||
pane.addBinding(editorStore.formData, folder.label, folder.params)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
initializeFormData()
|
||||
createPane()
|
||||
editorStore.initializeFormData()
|
||||
createPane(paneContainer.value as HTMLDivElement)
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,33 +1,26 @@
|
|||
const editorConfig = [
|
||||
{
|
||||
value: 'Hello World',
|
||||
label: "Text",
|
||||
params: {}
|
||||
},
|
||||
{
|
||||
label: "Range",
|
||||
label: "border-radius",
|
||||
value: 50,
|
||||
|
||||
params: {
|
||||
min: 0,
|
||||
step: 1,
|
||||
max: 100
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "Step",
|
||||
value: 50,
|
||||
label: "width",
|
||||
value: 200,
|
||||
params: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
min: 100,
|
||||
max: 500,
|
||||
step: 10
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "quality",
|
||||
value: 0,
|
||||
params: {
|
||||
options: { "medium": 0, "high": 1, "ultra": 2 }
|
||||
}
|
||||
label: "background-color",
|
||||
value: "#fff",
|
||||
params: {}
|
||||
}
|
||||
].map((i, index) => ({ ...i, id: index }));
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import './assets/main.css'
|
|||
|
||||
import { createApp } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
||||
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
|
@ -9,6 +10,7 @@ import router from './router'
|
|||
const app = createApp(App)
|
||||
app.use(router)
|
||||
|
||||
const pinia = createPinia();
|
||||
const pinia = createPinia()
|
||||
pinia.use(piniaPluginPersistedstate)
|
||||
app.use(pinia)
|
||||
app.mount('#app')
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
|
||||
const routes = [
|
||||
const routes: any[] = [
|
||||
|
||||
]
|
||||
|
||||
42
src/stores/editor.ts
Normal file
42
src/stores/editor.ts
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import { reactive, computed } from 'vue'
|
||||
import { folders } from '@/const/editor'
|
||||
|
||||
// 定义哪些属性需要添加 px 单位
|
||||
const PX_PROPERTIES = ['width', 'border-radius']
|
||||
|
||||
export const useEditorStore = defineStore('editor', () => {
|
||||
// 存储表单数据
|
||||
const formData = reactive<Record<string, any>>({})
|
||||
|
||||
// 初始化表单数据
|
||||
function initializeFormData() {
|
||||
folders.flatMap(f => f.type === 'folder' ? f.children : []).forEach((item: any) => {
|
||||
if (!(item.label in formData)) {
|
||||
formData[item.label] = item.value
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 获取动态样式对象
|
||||
const imageStyle = computed(() => {
|
||||
const style: Record<string, any> = {}
|
||||
Object.entries(formData).forEach(([key, value]) => {
|
||||
if (PX_PROPERTIES.includes(key) && typeof value === 'number') {
|
||||
style[key] = `${value}px`
|
||||
} else {
|
||||
style[key] = value
|
||||
}
|
||||
})
|
||||
return style
|
||||
})
|
||||
|
||||
return {
|
||||
formData,
|
||||
imageStyle,
|
||||
initializeFormData,
|
||||
}
|
||||
}, {
|
||||
persist: false
|
||||
})
|
||||
31
tsconfig.json
Normal file
31
tsconfig.json
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "preserve",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
|
||||
/* Path mapping */
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
10
tsconfig.node.json
Normal file
10
tsconfig.node.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user