mirror of
https://github.com/palxiao/poster-design.git
synced 2025-07-15 16:02:19 +08:00
feat: convert wSvg component to composition API
This commit is contained in:
parent
15c0fc9b2b
commit
2edc820364
@ -13,7 +13,8 @@ import wImageSetting from '@/components/modules/widgets/wImage/wImageSetting'
|
||||
// import wText from '@/components/modules/widgets/wText/wText.vue'
|
||||
import { wTextSetting } from '@/components/modules/widgets/wText/wTextSetting'
|
||||
import wImage from '@/components/modules/widgets/wImage/wImage.vue'
|
||||
import wSvg from '@/components/modules/widgets/wSvg/wSvg.vue'
|
||||
// import wSvg from '@/components/modules/widgets/wSvg/wSvg.vue'
|
||||
import { wSvgSetting } from '@/components/modules/widgets/wSvg/wSvgSetting'
|
||||
|
||||
export default async function(type: string, item: TCommonItemData, data: Record<string, any>) {
|
||||
let setting = data
|
||||
@ -36,7 +37,7 @@ export default async function(type: string, item: TCommonItemData, data: Record<
|
||||
setting.mask = item.value.url
|
||||
}
|
||||
if (type === 'svg') {
|
||||
setting = JSON.parse(JSON.stringify(wSvg.setting))
|
||||
setting = JSON.parse(JSON.stringify(wSvgSetting))
|
||||
const img = await setImageData(item.value)
|
||||
setting.width = img.width
|
||||
setting.height = img.height // parseInt(100 / item.value.ratio, 10)
|
||||
|
@ -43,7 +43,8 @@ import { defineComponent, reactive, toRefs, onMounted, watch } from 'vue'
|
||||
import api from '@/api'
|
||||
// import wImage from '../../widgets/wImage/wImage.vue'
|
||||
import wImageSetting from '../../widgets/wImage/wImageSetting'
|
||||
import wSvg from '../../widgets/wSvg/wSvg.vue'
|
||||
// import wSvg from '../../widgets/wSvg/wSvg.vue'
|
||||
import { wSvgSetting } from '../../widgets/wSvg/wSvgSetting'
|
||||
import { mapActions, mapGetters } from 'vuex'
|
||||
import setImageData from '@/common/methods/DesignFeatures/setImage'
|
||||
import DragHelper from '@/common/hooks/dragHelper'
|
||||
@ -160,7 +161,7 @@ export default defineComponent({
|
||||
return
|
||||
}
|
||||
this.$store.commit('setShowMoveable', false) // 清理掉上一次的选择
|
||||
let setting = item.type === 'svg' ? JSON.parse(JSON.stringify(wSvg.setting)) : JSON.parse(JSON.stringify(wImageSetting))
|
||||
let setting = item.type === 'svg' ? JSON.parse(JSON.stringify(wSvgSetting)) : JSON.parse(JSON.stringify(wImageSetting))
|
||||
const img: any = await setImageData(item)
|
||||
|
||||
setting.width = img.width
|
||||
|
@ -42,7 +42,8 @@
|
||||
import api from '@/api'
|
||||
import { toRefs, reactive, watch, onMounted, nextTick } from 'vue'
|
||||
import { ElRadioGroup, ElRadioButton } from 'element-plus'
|
||||
import wSvg from '@/components/modules/widgets/wSvg/wSvg.vue'
|
||||
// import wSvg from '@/components/modules/widgets/wSvg/wSvg.vue'
|
||||
import {wSvgSetting} from '@/components/modules/widgets/wSvg/wSvgSetting'
|
||||
import { TGetListResult } from '@/api/material';
|
||||
|
||||
type TProps = {
|
||||
@ -75,7 +76,7 @@ const state = reactive<TState>({
|
||||
|
||||
const select = (value: string = '') => {
|
||||
state.visiable = false
|
||||
const setting = JSON.parse(JSON.stringify(wSvg.setting))
|
||||
const setting = JSON.parse(JSON.stringify(wSvgSetting))
|
||||
setting.svgUrl = value
|
||||
emit('change', setting)
|
||||
}
|
||||
|
@ -4,10 +4,10 @@
|
||||
<template>
|
||||
<div
|
||||
:id="params.uuid"
|
||||
ref="widget"
|
||||
ref="widgetRef"
|
||||
class="w-svg"
|
||||
:style="{
|
||||
position,
|
||||
position: state.position,
|
||||
left: params.left - parent.left + 'px',
|
||||
top: params.top - parent.top + 'px',
|
||||
width: params.width + 'px',
|
||||
@ -17,40 +17,34 @@
|
||||
></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script lang="ts" setup>
|
||||
// svg
|
||||
const NAME = 'w-svg'
|
||||
// const NAME = 'w-svg'
|
||||
import { mapGetters, mapActions, useStore } from 'vuex'
|
||||
import { TWSvgSetting } from './wSvgSetting'
|
||||
import { CSSProperties, computed, nextTick, onBeforeMount, onMounted, onUpdated, reactive, ref, watch } from 'vue';
|
||||
import { useSetupMapGetters } from '@/common/hooks/mapGetters';
|
||||
|
||||
import { mapGetters, mapActions } from 'vuex'
|
||||
type TProps = {
|
||||
params: TWSvgSetting
|
||||
parent: {
|
||||
left: number
|
||||
top: number
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: NAME,
|
||||
setting: {
|
||||
name: '矢量图形',
|
||||
type: NAME,
|
||||
uuid: -1,
|
||||
width: 100,
|
||||
height: 100,
|
||||
colors: [],
|
||||
left: 0,
|
||||
top: 0,
|
||||
// zoom: 1.5,
|
||||
transform: '',
|
||||
radius: 0,
|
||||
opacity: 1,
|
||||
parent: '-1',
|
||||
svgUrl: '',
|
||||
setting: [],
|
||||
record: {
|
||||
width: 0,
|
||||
height: 0,
|
||||
minWidth: 10,
|
||||
minHeight: 10,
|
||||
},
|
||||
},
|
||||
props: ['params', 'parent'],
|
||||
data() {
|
||||
return {
|
||||
type TState = {
|
||||
position: CSSProperties['position'], // 'absolute'relative
|
||||
editBoxStyle: CSSProperties,
|
||||
editBoxs: Record<string, any>,
|
||||
editingKey: string,
|
||||
cropWidgetXY: Record<string, any>, // 裁剪框移动作用
|
||||
attrRecord: Record<string, any>, // 记录可更改的属性
|
||||
svgImg: Record<string, any> | null
|
||||
}
|
||||
|
||||
const props = defineProps<TProps>()
|
||||
const state = reactive<TState>({
|
||||
position: 'absolute', // 'absolute'relative
|
||||
editBoxStyle: {
|
||||
transformOrigin: 'center',
|
||||
@ -59,66 +53,90 @@ export default {
|
||||
editingKey: '',
|
||||
cropWidgetXY: {}, // 裁剪框移动作用
|
||||
attrRecord: {}, // 记录可更改的属性
|
||||
svgImg: null
|
||||
})
|
||||
const store = useStore()
|
||||
// ...mapGetters(['dActiveElement', 'dZoom', 'dMouseXY']),
|
||||
const {
|
||||
dActiveElement, dZoom, dMouseXY
|
||||
} = useSetupMapGetters(['dActiveElement', 'dZoom', 'dMouseXY'])
|
||||
|
||||
const widgetRef = ref<HTMLElement | null>(null)
|
||||
|
||||
let svgElements: Record<string, any>[] | null = null
|
||||
let viewBox = { width: 0, height: 0 }
|
||||
|
||||
const tZoom = computed(() => {
|
||||
return props.params.zoom
|
||||
})
|
||||
const cropEdit = computed(() => {
|
||||
return props.params.cropEdit
|
||||
})
|
||||
const imgChange = computed(() => {
|
||||
return props.params.imgUrl
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.params,
|
||||
() => {
|
||||
attrsChange()
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
() => tZoom.value,
|
||||
async () => {
|
||||
await nextTick()
|
||||
updateRecord()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['dActiveElement', 'dZoom', 'dMouseXY']),
|
||||
tZoom() {
|
||||
return this.params.zoom
|
||||
},
|
||||
cropEdit() {
|
||||
return this.params.cropEdit
|
||||
},
|
||||
imgChange() {
|
||||
return this.params.imgUrl
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
params: {
|
||||
async handler(nval) {
|
||||
this.attrsChange()
|
||||
},
|
||||
immediate: true,
|
||||
deep: true,
|
||||
},
|
||||
async tZoom() {
|
||||
await this.$nextTick()
|
||||
this.updateRecord()
|
||||
},
|
||||
imgChange() {
|
||||
// TODO 更新所有图片
|
||||
this.svgImg.attr({
|
||||
'xlink:href': this.params.imgUrl,
|
||||
)
|
||||
|
||||
watch(
|
||||
() => imgChange.value,
|
||||
() => {
|
||||
if (!state.svgImg) return
|
||||
state.svgImg.attr({
|
||||
'xlink:href': props.params.imgUrl,
|
||||
})
|
||||
},
|
||||
cropEdit(val) {
|
||||
// TODO 移动事件绑定
|
||||
if (val) {
|
||||
document.getElementById(this.params.uuid).addEventListener('mousedown', this.touchstart, false)
|
||||
} else {
|
||||
document.getElementById(this.params.uuid).removeEventListener('mousedown', this.touchstart, false)
|
||||
}
|
||||
},
|
||||
},
|
||||
updated() {
|
||||
this.updateRecord()
|
||||
this.$store.commit('updateRect')
|
||||
},
|
||||
async mounted() {
|
||||
await this.$nextTick()
|
||||
await this.loadSvg()
|
||||
this.updateRecord()
|
||||
// document.getElementById(this.params.uuid).addEventListener('mousedown', this.touchstart, false)
|
||||
document.addEventListener('mouseup', this.touchend, false)
|
||||
this.params.transform && (this.$refs.widget.style.transform = this.params.transform)
|
||||
this.params.rotate && (this.$refs.widget.style.transform += `rotate(${this.params.rotate})`)
|
||||
},
|
||||
beforeUnmount() {
|
||||
document.removeEventListener('mouseup', this.touchend, false)
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['updateWidgetData']),
|
||||
touchstart(e) {
|
||||
)
|
||||
|
||||
watch(
|
||||
() => cropEdit.value,
|
||||
(val) => {
|
||||
const el = document.getElementById(props.params.uuid)
|
||||
if (val) {
|
||||
el?.addEventListener('mousedown', touchstart, false)
|
||||
} else {
|
||||
el?.removeEventListener('mousedown', touchstart, false)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
onUpdated(() => {
|
||||
updateRecord()
|
||||
store.commit('updateRect')
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick()
|
||||
await loadSvg()
|
||||
updateRecord()
|
||||
document.getElementById(props.params.uuid)?.addEventListener('mousedown', touchstart, false)
|
||||
document.addEventListener('mouseup', touchend, false)
|
||||
if (!widgetRef.value) return
|
||||
props.params.transform && (widgetRef.value.style.transform = props.params.transform)
|
||||
props.params.rotate && (widgetRef.value.style.transform += `rotate(${props.params.rotate})`)
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
// document.removeEventListener('mouseup', touchend, false)
|
||||
})
|
||||
|
||||
// ...mapActions(['updateWidgetData'])
|
||||
|
||||
function touchstart(e: MouseEvent) {
|
||||
// TODO move start
|
||||
// const imgKey = e.target.getAttribute('img-key')
|
||||
// this.editingKey = imgKey
|
||||
@ -126,47 +144,52 @@ export default {
|
||||
// transformOrigin: 'center',
|
||||
// }
|
||||
// const editBox = this.$refs[this.params.uuid + '_ebox_' + imgKey]
|
||||
const editBox = this.$refs[this.params.uuid + '_ebox']
|
||||
this.cropWidgetXY = {
|
||||
// const editBox = this.$refs[this.params.uuid + '_ebox']
|
||||
const editBox = document.getElementById(props.params.uuid + '_ebox')
|
||||
if (editBox) {
|
||||
state.cropWidgetXY = {
|
||||
x: Number(editBox.style.left.replace('px', '')) || 0,
|
||||
y: Number(editBox.style.top.replace('px', '')) || 0,
|
||||
}
|
||||
}
|
||||
// 绑定鼠标移动事件
|
||||
document.addEventListener('mousemove', this.handlemousemove, true)
|
||||
},
|
||||
touchend() {
|
||||
document.addEventListener('mousemove', handlemousemove, true)
|
||||
}
|
||||
|
||||
function touchend() {
|
||||
// 取消鼠标移动事件
|
||||
document.removeEventListener('mousemove', this.handlemousemove, true)
|
||||
document.removeEventListener('mousemove', handlemousemove, true)
|
||||
// document.removeEventListener('mouseup', () => {}, true)
|
||||
},
|
||||
handlemousemove(e) {
|
||||
}
|
||||
|
||||
function handlemousemove(e: MouseEvent) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
const { left, top } = this.move(e)
|
||||
const { left, top } = move(e)
|
||||
// TODO
|
||||
this.editBoxStyle.left = left + 'px'
|
||||
this.editBoxStyle.top = top + 'px'
|
||||
state.editBoxStyle.left = left + 'px'
|
||||
state.editBoxStyle.top = top + 'px'
|
||||
// this.editBoxs[this.editingKey].left = left + 'px'
|
||||
// this.editBoxs[this.editingKey].top = top + 'px'
|
||||
const { width, height } = this.params
|
||||
const { width: vWidth, height: vHeight } = this.viewBox
|
||||
const { width, height } = props.params
|
||||
const { width: vWidth, height: vHeight } = viewBox
|
||||
const params = {
|
||||
x: left / (width / vWidth) / this.params.zoom,
|
||||
y: top / (height / vHeight) / this.params.zoom,
|
||||
x: left / (width / vWidth) / (props.params.zoom || 0),
|
||||
y: top / (height / vHeight) / (props.params.zoom || 0),
|
||||
}
|
||||
// this.svgImg.attr(params)
|
||||
this.changeFinish('x', params.x)
|
||||
this.changeFinish('y', params.y)
|
||||
changeFinish('x', params.x)
|
||||
changeFinish('y', params.y)
|
||||
// console.log('-----', left / (width / vWidth) / this.params.zoom)
|
||||
},
|
||||
loadSvg() {
|
||||
}
|
||||
|
||||
function loadSvg() {
|
||||
// console.log(this.params)
|
||||
const _this = this
|
||||
const Snap = window.Snap
|
||||
return new Promise((resolve) => {
|
||||
const Snap = (window as any).Snap
|
||||
return new Promise<void>((resolve) => {
|
||||
Snap.load(
|
||||
this.params.svgUrl,
|
||||
function (svg) {
|
||||
props.params.svgUrl,
|
||||
function (svg: Record<string, any>) {
|
||||
let svg2 = Snap(svg.node)
|
||||
// let item = svg2.select('circle')
|
||||
// item.attr({
|
||||
@ -179,18 +202,18 @@ export default {
|
||||
svg2.node.removeAttribute('height')
|
||||
svg2.node.setAttribute('style', 'height: inherit;width: inherit;')
|
||||
// svg2.node.setAttribute('height', 'inherit')
|
||||
_this.svgElements = []
|
||||
const colorsObj = _this.color2obj()
|
||||
svgElements = []
|
||||
const colorsObj = color2obj()
|
||||
|
||||
deepElement(items)
|
||||
|
||||
function deepElement(els) {
|
||||
function deepElement(els: Record<string, any>) {
|
||||
// 判断是NodeList对象则继续递归,否则进入元素处理工厂
|
||||
if (els.item) {
|
||||
els.forEach((element) => {
|
||||
els.forEach((element: Record<string, any>) => {
|
||||
elementFactory(element)
|
||||
if (element.childNodes.length > 0) {
|
||||
element.childNodes.forEach((element) => {
|
||||
element.childNodes.forEach((element: Record<string, any>) => {
|
||||
deepElement(element)
|
||||
})
|
||||
}
|
||||
@ -200,19 +223,19 @@ export default {
|
||||
}
|
||||
}
|
||||
// 元素工厂: 遍历元素中是否存在可自定义的颜色属性
|
||||
function elementFactory(element) {
|
||||
const attrsColor = {}
|
||||
function elementFactory(element: Record<string, any>) {
|
||||
const attrsColor: Record<string, any> = {}
|
||||
try {
|
||||
element.attributes.forEach((attr) => {
|
||||
element.attributes.forEach((attr: Record<string, any>) => {
|
||||
if (colorsObj[attr.value]) {
|
||||
// console.log(attr.name, colorsObj[attr.value])
|
||||
attr.value = colorsObj[attr.value]
|
||||
attrsColor[attr.name] = _this.params.colors.findIndex((x) => x == attr.value)
|
||||
attrsColor[attr.name] = props.params.colors.findIndex((x) => x == attr.value)
|
||||
}
|
||||
})
|
||||
} catch (e) {}
|
||||
if (JSON.stringify(attrsColor) !== '{}') {
|
||||
_this.svgElements.push({
|
||||
if (JSON.stringify(attrsColor) !== '{}' && svgElements) {
|
||||
svgElements.push({
|
||||
item: element,
|
||||
attrsColor,
|
||||
})
|
||||
@ -229,88 +252,101 @@ export default {
|
||||
// transform: '',
|
||||
// 'xlink:href': _this.params.imgUrl || '',
|
||||
// })
|
||||
const el = this || _this.$refs.widget
|
||||
if (widgetRef.value) {
|
||||
// svg.node.classList.add('svg__box')
|
||||
el.appendChild(svg.node)
|
||||
widgetRef.value.appendChild(svg.node)
|
||||
}
|
||||
resolve()
|
||||
},
|
||||
document.getElementById(this.params.uuid),
|
||||
document.getElementById(props.params.uuid),
|
||||
)
|
||||
})
|
||||
},
|
||||
color2obj() {
|
||||
const obj = {}
|
||||
for (let i = 0; i < this.params.colors.length; i++) {
|
||||
obj[`{{colors[${i}]}}`] = this.params.colors[i]
|
||||
}
|
||||
|
||||
function color2obj() {
|
||||
const obj: Record<string, any> = {}
|
||||
for (let i = 0; i < props.params.colors.length; i++) {
|
||||
obj[`{{colors[${i}]}}`] = props.params.colors[i]
|
||||
}
|
||||
return obj
|
||||
},
|
||||
updateRecord() {
|
||||
if (this.dActiveElement.uuid === this.params.uuid) {
|
||||
let record = this.dActiveElement.record
|
||||
record.width = this.$refs.widget.offsetWidth
|
||||
record.height = this.$refs.widget.offsetHeight
|
||||
}
|
||||
|
||||
function updateRecord() {
|
||||
if (dActiveElement.value.uuid === props.params.uuid) {
|
||||
let record = dActiveElement.value.record
|
||||
if (widgetRef.value) {
|
||||
record.width = widgetRef.value.offsetWidth
|
||||
record.height = widgetRef.value.offsetHeight
|
||||
}
|
||||
this.updateZoom()
|
||||
},
|
||||
updateZoom() {
|
||||
}
|
||||
updateZoom()
|
||||
}
|
||||
|
||||
function updateZoom() {
|
||||
// TODO
|
||||
this.editBoxStyle.transform = `scale(${this.params.zoom})`
|
||||
state.editBoxStyle.transform = `scale(${props.params.zoom})`
|
||||
// this.editingKey && (this.editBoxs[this.editingKey].transform = `scale(${this.params.zoom})`)
|
||||
if (this.svgImg) {
|
||||
const { x, y } = this.params
|
||||
this.svgImg.attr({
|
||||
x: x || 0,
|
||||
y: y || 0,
|
||||
style: `transform-origin: center;transform: scale(${this.params.zoom})`,
|
||||
if (state.svgImg) {
|
||||
const { x = 0, y = 0 } = props.params
|
||||
state.svgImg.attr({
|
||||
x: x ?? 0,
|
||||
y: y ?? 0,
|
||||
style: `transform-origin: center;transform: scale(${props.params.zoom})`,
|
||||
})
|
||||
// 根据图片位置设置回editBox的位置
|
||||
const { width, height } = this.params
|
||||
const { width: vWidth, height: vHeight } = this.viewBox
|
||||
const { width, height } = props.params
|
||||
const { width: vWidth, height: vHeight } = viewBox
|
||||
const params = {
|
||||
left: x * (width / vWidth) * this.params.zoom,
|
||||
top: y * (height / vHeight) * this.params.zoom,
|
||||
left: x * (width / vWidth) * (props.params.zoom || 0),
|
||||
top: y * (height / vHeight) * (props.params.zoom || 0),
|
||||
}
|
||||
// TODO
|
||||
this.editBoxStyle.left = params.left + 'px'
|
||||
this.editBoxStyle.top = params.top + 'px'
|
||||
state.editBoxStyle.left = params.left + 'px'
|
||||
state.editBoxStyle.top = params.top + 'px'
|
||||
// if (this.editingKey) {
|
||||
// this.editBoxs[this.editingKey].left = params.left + 'px'
|
||||
// this.editBoxs[this.editingKey].top = params.top + 'px'
|
||||
// }
|
||||
}
|
||||
},
|
||||
changeFinish(key, value) {
|
||||
this.updateWidgetData({
|
||||
uuid: this.params.uuid,
|
||||
}
|
||||
|
||||
function changeFinish(key: string, value: number) {
|
||||
store.dispatch("updateWidgetData", {
|
||||
uuid: props.params.uuid,
|
||||
key: key,
|
||||
value: value,
|
||||
pushHistory: true,
|
||||
})
|
||||
},
|
||||
move(payload) {
|
||||
// this.updateWidgetData({
|
||||
// uuid: this.params.uuid,
|
||||
// key: key,
|
||||
// value: value,
|
||||
// pushHistory: true,
|
||||
// })
|
||||
}
|
||||
|
||||
function move(payload: Record<string, any>) {
|
||||
// const widgetXY = { x: this.cropWidgetXY.x / this.dZoom, y: this.cropWidgetXY.y / this.dZoom }
|
||||
const widgetXY = { x: this.cropWidgetXY.x, y: this.cropWidgetXY.y }
|
||||
const dx = Number(payload.pageX) - this.dMouseXY.x
|
||||
const dy = Number(payload.pageY) - this.dMouseXY.y
|
||||
let left = Number(widgetXY.x) + Math.floor((dx * 100) / this.dZoom)
|
||||
let top = Number(widgetXY.y) + Math.floor((dy * 100) / this.dZoom)
|
||||
const widgetXY = { x: state.cropWidgetXY.x, y: state.cropWidgetXY.y }
|
||||
const dx = Number(payload.pageX) - dMouseXY.value.x
|
||||
const dy = Number(payload.pageY) - dMouseXY.value.y
|
||||
let left = Number(widgetXY.x) + Math.floor((dx * 100) / dZoom.value)
|
||||
let top = Number(widgetXY.y) + Math.floor((dy * 100) / dZoom.value)
|
||||
return { left, top }
|
||||
},
|
||||
attrsChange() {
|
||||
if (this.dActiveElement.uuid === this.params.uuid && this.svgElements) {
|
||||
for (const element of this.svgElements) {
|
||||
}
|
||||
|
||||
function attrsChange() {
|
||||
if (dActiveElement.value.uuid === props.params.uuid && svgElements) {
|
||||
for (const element of svgElements) {
|
||||
const { item, attrsColor } = element
|
||||
for (const key in attrsColor) {
|
||||
if (Object.hasOwnProperty.call(attrsColor, key)) {
|
||||
const color = this.params.colors[attrsColor[key]]
|
||||
const color = props.params.colors[attrsColor[key]]
|
||||
item.setAttribute(key, color)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
54
src/components/modules/widgets/wSvg/wSvgSetting.ts
Normal file
54
src/components/modules/widgets/wSvg/wSvgSetting.ts
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
export type TWSvgSetting = {
|
||||
name: string,
|
||||
type: string,
|
||||
uuid: string
|
||||
width: number
|
||||
height: number
|
||||
colors: [],
|
||||
left: number
|
||||
top: number
|
||||
// zoom: 1.5,
|
||||
transform: string
|
||||
radius: number
|
||||
opacity: number
|
||||
parent: string
|
||||
svgUrl: string
|
||||
setting: [],
|
||||
record: {
|
||||
width: number
|
||||
height: number
|
||||
minWidth: number
|
||||
minHeight: number
|
||||
},
|
||||
zoom?: number
|
||||
cropEdit?: boolean
|
||||
imgUrl?: string
|
||||
rotate?: number
|
||||
x?: number
|
||||
y?: number
|
||||
}
|
||||
|
||||
export const wSvgSetting = {
|
||||
name: '矢量图形',
|
||||
type: "w-svg",
|
||||
uuid: `-1`,
|
||||
width: 100,
|
||||
height: 100,
|
||||
colors: [],
|
||||
left: 0,
|
||||
top: 0,
|
||||
// zoom: 1.5,
|
||||
transform: '',
|
||||
radius: 0,
|
||||
opacity: 1,
|
||||
parent: '-1',
|
||||
svgUrl: '',
|
||||
setting: [],
|
||||
record: {
|
||||
width: 0,
|
||||
height: 0,
|
||||
minWidth: 10,
|
||||
minHeight: 10,
|
||||
},
|
||||
}
|
@ -7,22 +7,22 @@
|
||||
-->
|
||||
<template>
|
||||
<div id="w-image-style">
|
||||
<el-collapse v-model="activeNames">
|
||||
<el-collapse v-model="state.activeNames">
|
||||
<el-collapse-item title="位置尺寸" name="1">
|
||||
<div class="line-layout">
|
||||
<number-input v-model="innerElement.left" label="X" @finish="(value) => finish('left', value)" />
|
||||
<number-input v-model="innerElement.top" label="Y" @finish="(value) => finish('top', value)" />
|
||||
<number-input v-model="innerElement.width" style="margin-top: 0.5rem" label="宽" @finish="(value) => finish('width', value)" />
|
||||
<number-input v-model="innerElement.height" style="margin-top: 0.5rem" label="高" @finish="(value) => finish('height', value)" />
|
||||
<number-input v-model="state.innerElement.left" label="X" @finish="(value) => finish('left', value)" />
|
||||
<number-input v-model="state.innerElement.top" label="Y" @finish="(value) => finish('top', value)" />
|
||||
<number-input v-model="state.innerElement.width" style="margin-top: 0.5rem" label="宽" @finish="(value) => finish('width', value)" />
|
||||
<number-input v-model="state.innerElement.height" style="margin-top: 0.5rem" label="高" @finish="(value) => finish('height', value)" />
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="设置颜色" name="2">
|
||||
<div v-for="(c, ci) in innerElement.colors" :key="ci + 'c'">
|
||||
<color-select v-model="innerElement.colors[ci]" @finish="(value) => colorFinish('colors')" />
|
||||
<div v-for="(c, ci) in state.innerElement.colors" :key="ci + 'c'">
|
||||
<color-select v-model="state.innerElement.colors[ci]" @finish="(value) => colorFinish('colors')" />
|
||||
</div>
|
||||
<br />
|
||||
<div class="slide-wrap">
|
||||
<number-slider v-model="innerElement.opacity" label="不透明" :step="0.01" :maxValue="1" @finish="(value) => finish('opacity', value)" />
|
||||
<number-slider v-model="state.innerElement.opacity" label="不透明" :step="0.01" :maxValue="1" @finish="(value) => finish('opacity', value)" />
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
<br />
|
||||
@ -33,100 +33,139 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script lang="ts" setup>
|
||||
// 图片组件样式
|
||||
const NAME = 'w-image-style'
|
||||
import { mapGetters, mapActions } from 'vuex'
|
||||
// const NAME = 'w-image-style'
|
||||
import { reactive, watch } from 'vue'
|
||||
import { mapGetters, mapActions, useStore } from 'vuex'
|
||||
import numberInput from '../../settings/numberInput.vue'
|
||||
import iconItemSelect from '../../settings/iconItemSelect.vue'
|
||||
import iconItemSelect, { TIconItemSelectData } from '../../settings/iconItemSelect.vue'
|
||||
import numberSlider from '../../settings/numberSlider.vue'
|
||||
import colorSelect from '../../settings/colorSelect.vue'
|
||||
import layerIconList from '@/assets/data/LayerIconList'
|
||||
import alignIconList from '@/assets/data/AlignListData'
|
||||
import { TWSvgSetting, wSvgSetting } from './wSvgSetting'
|
||||
import { useSetupMapGetters } from '@/common/hooks/mapGetters'
|
||||
|
||||
export default {
|
||||
name: NAME,
|
||||
components: { numberInput, numberSlider, iconItemSelect, colorSelect },
|
||||
data() {
|
||||
return {
|
||||
type TState = {
|
||||
activeNames: string[]
|
||||
innerElement: TWSvgSetting
|
||||
tag: boolean
|
||||
ingoreKeys: string[]
|
||||
layerIconList: TIconItemSelectData[]
|
||||
alignIconList: TIconItemSelectData[]
|
||||
}
|
||||
|
||||
const state = reactive<TState>({
|
||||
activeNames: ['2', '3', '4'],
|
||||
innerElement: {},
|
||||
innerElement: JSON.parse(JSON.stringify(wSvgSetting)),
|
||||
tag: false,
|
||||
ingoreKeys: ['left', 'top', 'name', 'width', 'height', 'radiusTopLeft', 'radiusTopRight', 'radiusBottomLeft', 'radiusBottomRight'],
|
||||
layerIconList,
|
||||
alignIconList,
|
||||
}
|
||||
})
|
||||
const store = useStore()
|
||||
const {
|
||||
dActiveElement, dMoving
|
||||
} = useSetupMapGetters(['dActiveElement', 'dMoving'])
|
||||
|
||||
// ...mapGetters(['dActiveElement', 'dMoving']),
|
||||
|
||||
watch(
|
||||
() => dActiveElement.value,
|
||||
() => {
|
||||
change()
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['dActiveElement', 'dMoving']),
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
() => state.innerElement,
|
||||
() => {
|
||||
changeValue()
|
||||
},
|
||||
watch: {
|
||||
dActiveElement: {
|
||||
handler(newValue, oldValue) {
|
||||
this.change()
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
innerElement: {
|
||||
handler(newValue, oldValue) {
|
||||
this.changeValue()
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.change()
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['updateWidgetData', 'updateAlign', 'updateLayerIndex']),
|
||||
change() {
|
||||
this.tag = true
|
||||
this.innerElement = JSON.parse(JSON.stringify(this.dActiveElement))
|
||||
},
|
||||
changeValue() {
|
||||
if (this.tag) {
|
||||
this.tag = false
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
function created() {
|
||||
change()
|
||||
}
|
||||
|
||||
created()
|
||||
|
||||
// ...mapActions(['updateWidgetData', 'updateAlign', 'updateLayerIndex']),
|
||||
|
||||
function change() {
|
||||
state.tag = true
|
||||
state.innerElement = JSON.parse(JSON.stringify(dActiveElement.value))
|
||||
}
|
||||
|
||||
function changeValue() {
|
||||
if (state.tag) {
|
||||
state.tag = false
|
||||
return
|
||||
}
|
||||
if (this.dMoving) {
|
||||
if (dMoving.value) {
|
||||
return
|
||||
}
|
||||
for (let key in this.innerElement) {
|
||||
if (this.ingoreKeys.indexOf(key) !== -1) {
|
||||
this.dActiveElement[key] = this.innerElement[key]
|
||||
} else if (key !== 'setting' && key !== 'record' && this.innerElement[key] !== this.dActiveElement[key]) {
|
||||
this.updateWidgetData({
|
||||
uuid: this.dActiveElement.uuid,
|
||||
for (let key in state.innerElement) {
|
||||
const itemKey = key as keyof TWSvgSetting
|
||||
if (state.ingoreKeys.indexOf(itemKey) !== -1) {
|
||||
dActiveElement.value[key] = state.innerElement[itemKey]
|
||||
} else if (itemKey !== 'setting' && itemKey !== 'record' && state.innerElement[itemKey] !== dActiveElement.value[itemKey]) {
|
||||
store.dispatch("updateWidgetData", {
|
||||
uuid: dActiveElement.value.uuid,
|
||||
key: key,
|
||||
value: this.innerElement[key],
|
||||
value: state.innerElement[itemKey],
|
||||
})
|
||||
// this.updateWidgetData({
|
||||
// uuid: this.dActiveElement.uuid,
|
||||
// key: key,
|
||||
// value: this.innerElement[key],
|
||||
// })
|
||||
}
|
||||
}
|
||||
},
|
||||
colorFinish(key) {
|
||||
this.finish(key, this.innerElement[key])
|
||||
},
|
||||
finish(key, value) {
|
||||
this.updateWidgetData({
|
||||
uuid: this.dActiveElement.uuid,
|
||||
}
|
||||
|
||||
function colorFinish(key: keyof TWSvgSetting) {
|
||||
finish(key, state.innerElement[key])
|
||||
}
|
||||
|
||||
function finish(key: string, value: any) {
|
||||
store.dispatch("updateWidgetData", {
|
||||
uuid: dActiveElement.value.uuid,
|
||||
key: key,
|
||||
value: value,
|
||||
pushHistory: true,
|
||||
})
|
||||
},
|
||||
layerAction(item) {
|
||||
this.updateLayerIndex({
|
||||
uuid: this.dActiveElement.uuid,
|
||||
// this.updateWidgetData({
|
||||
// uuid: this.dActiveElement.uuid,
|
||||
// key: key,
|
||||
// value: value,
|
||||
// pushHistory: true,
|
||||
// })
|
||||
}
|
||||
|
||||
function layerAction(item: TIconItemSelectData) {
|
||||
store.dispatch("updateLayerIndex", {
|
||||
uuid: dActiveElement.value.uuid,
|
||||
value: item.value,
|
||||
})
|
||||
},
|
||||
alignAction(item) {
|
||||
this.updateAlign({
|
||||
// this.updateLayerIndex({
|
||||
// uuid: this.dActiveElement.uuid,
|
||||
// value: item.value,
|
||||
// })
|
||||
}
|
||||
|
||||
function alignAction(item: TIconItemSelectData) {
|
||||
store.dispatch("updateAlign", {
|
||||
align: item.value,
|
||||
uuid: this.dActiveElement.uuid,
|
||||
uuid: dActiveElement.value.uuid,
|
||||
})
|
||||
},
|
||||
},
|
||||
// this.updateAlign({
|
||||
// align: item.value,
|
||||
// uuid: this.dActiveElement.uuid,
|
||||
// })
|
||||
}
|
||||
</script>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user