5 changed files with 238 additions and 10 deletions
@ -0,0 +1,216 @@ |
|||
<script setup lang="ts"> |
|||
import { reactive } from "vue"; |
|||
import { ElInputNumber, useFormItem } from "element-plus"; |
|||
import { Typeof } from "@ease-forge/shared"; |
|||
import { renderIcon } from "@/utils/webutils.js"; |
|||
|
|||
defineOptions({ |
|||
name: 'TransformEditor', |
|||
}); |
|||
|
|||
// 组件事件定义 |
|||
const emit = defineEmits<{ |
|||
/** 更新内联表格数据 */ |
|||
"update:modelValue": [value: ItemJson["tf"]]; |
|||
}>(); |
|||
|
|||
// // 定义组件插槽 |
|||
// const slots = defineSlots<{ |
|||
// /** 提交区域插槽 */ |
|||
// slots01?: (props?: any) => Array<VueNode>; |
|||
// }>(); |
|||
|
|||
// // 组件属性 |
|||
// const attrs = useAttrs(); |
|||
// // 组件插槽 |
|||
// const slots = useSlots(); |
|||
// 当前组件对象 |
|||
// const instance = getCurrentInstance(); |
|||
|
|||
// // 双向绑定的 value 属性 |
|||
// const value = defineModel<string>(); |
|||
|
|||
// 定义 Props 类型 |
|||
interface TransformEditorProps { |
|||
modelValue: ItemJson["tf"]; |
|||
} |
|||
|
|||
// 读取组件 props 属性 |
|||
const props = withDefaults(defineProps<TransformEditorProps>(), {}); |
|||
|
|||
// 定义 State 类型 |
|||
interface TransformEditorState { |
|||
} |
|||
|
|||
// state 属性 |
|||
const state = reactive<TransformEditorState>({}); |
|||
|
|||
// 定义 Data 类型 |
|||
interface TransformEditorData { |
|||
} |
|||
|
|||
// 内部数据 |
|||
const data: TransformEditorData = {}; |
|||
const { formItem } = useFormItem(); |
|||
|
|||
|
|||
function updateValue(value: number | undefined, prs: 0 | 1 | 2, xyz: 0 | 1 | 2) { |
|||
const rawValue: any = props.modelValue; |
|||
if (!rawValue[prs]) rawValue[prs] = []; |
|||
if (prs === 1) value = calcRotation(value); |
|||
rawValue[prs][xyz] = value; |
|||
emit("update:modelValue", rawValue); |
|||
console.log("updateValue", rawValue); |
|||
// formItem?.validate('change', (valid) => console.log(valid)); |
|||
} |
|||
|
|||
function getPosition(idx: 0 | 1 | 2) { |
|||
return props.modelValue?.[0]?.[idx]; |
|||
} |
|||
|
|||
function getRotation(idx: 0 | 1 | 2) { |
|||
const radian = props.modelValue?.[1]?.[idx]; |
|||
if (Typeof.noValue(radian)) return; |
|||
return Math.round(radian * 180 / Math.PI); |
|||
} |
|||
|
|||
function getScale(idx: 0 | 1 | 2) { |
|||
return props.modelValue?.[2]?.[idx]; |
|||
} |
|||
|
|||
function calcRotation(rotation?: number) { |
|||
if (Typeof.noValue(rotation)) return; |
|||
return rotation * Math.PI / 180; |
|||
} |
|||
|
|||
interface TransformEditorExpose { |
|||
state: TransformEditorState; |
|||
data: TransformEditorData; |
|||
} |
|||
|
|||
const expose: TransformEditorExpose = { |
|||
state, |
|||
data, |
|||
}; |
|||
// 定义组件公开内容 |
|||
defineExpose(expose); |
|||
|
|||
export type { |
|||
TransformEditorProps, |
|||
TransformEditorState, |
|||
} |
|||
</script> |
|||
|
|||
<template> |
|||
<div class="transform-editor gui-toolbar"> |
|||
<div class="gui-row"> |
|||
<div class="gui-item-name"></div> |
|||
<div class="gui-item">X</div> |
|||
<div class="gui-item">Y</div> |
|||
<div class="gui-item">Z</div> |
|||
</div> |
|||
<div class="gui-row"> |
|||
<div class="gui-item-name"> |
|||
<component :is="renderIcon('element Rank')"></component> |
|||
</div> |
|||
<div class="gui-item"> |
|||
<ElInputNumber |
|||
:modelValue="getPosition(0)" |
|||
size="small" |
|||
:precision="3" |
|||
:controls="false" |
|||
@change="(currentValue: number) => updateValue(currentValue, 0, 0)" |
|||
/> |
|||
</div> |
|||
<div class="gui-item"> |
|||
<ElInputNumber |
|||
:modelValue="getPosition(1)" |
|||
size="small" |
|||
:precision="3" |
|||
:controls="false" |
|||
@change="(currentValue: number) => updateValue(currentValue, 0, 1)" |
|||
/> |
|||
</div> |
|||
<div class="gui-item"> |
|||
<ElInputNumber |
|||
:modelValue="getPosition(2)" |
|||
size="small" |
|||
:precision="3" |
|||
:controls="false" |
|||
@change="(currentValue: number) => updateValue(currentValue, 0, 2)" |
|||
/> |
|||
</div> |
|||
</div> |
|||
<div class="gui-row"> |
|||
<div class="gui-item-name"> |
|||
<component :is="renderIcon('element RefreshLeft')"></component> |
|||
</div> |
|||
<div class="gui-item"> |
|||
<ElInputNumber |
|||
:modelValue="getRotation(0)" |
|||
size="small" |
|||
:precision="3" |
|||
:controls="false" |
|||
@change="(currentValue: number) => updateValue(currentValue, 1, 0)" |
|||
/> |
|||
</div> |
|||
<div class="gui-item"> |
|||
<ElInputNumber |
|||
:modelValue="getRotation(1)" |
|||
size="small" |
|||
:precision="3" |
|||
:controls="false" |
|||
@change="(currentValue: number) => updateValue(currentValue, 1, 1)" |
|||
/> |
|||
</div> |
|||
<div class="gui-item"> |
|||
<ElInputNumber |
|||
:modelValue="getRotation(2)" |
|||
size="small" |
|||
:precision="3" |
|||
:controls="false" |
|||
@change="(currentValue: number) => updateValue(currentValue, 1, 2)" |
|||
/> |
|||
</div> |
|||
</div> |
|||
<div class="gui-row"> |
|||
<div class="gui-item-name"> |
|||
<component :is="renderIcon('element ScaleToOriginal')"></component> |
|||
</div> |
|||
<div class="gui-item"> |
|||
<ElInputNumber |
|||
:modelValue="getScale(0)" |
|||
size="small" |
|||
:precision="3" |
|||
:controls="false" |
|||
@change="(currentValue: number) => updateValue(currentValue, 2, 0)" |
|||
/> |
|||
</div> |
|||
<div class="gui-item"> |
|||
<ElInputNumber |
|||
:modelValue="getScale(1)" |
|||
size="small" |
|||
:precision="3" |
|||
:controls="false" |
|||
@change="(currentValue: number) => updateValue(currentValue, 2, 1)" |
|||
/> |
|||
</div> |
|||
<div class="gui-item"> |
|||
<ElInputNumber |
|||
:modelValue="getScale(2)" |
|||
size="small" |
|||
:precision="3" |
|||
:controls="false" |
|||
@change="(currentValue: number) => updateValue(currentValue, 2, 2)" |
|||
/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<style scoped> |
|||
div.transform-editor.gui-toolbar { |
|||
border: none; |
|||
margin: 0; |
|||
} |
|||
</style> |
|||
Loading…
Reference in new issue