185 lines
4.4 KiB
Vue
185 lines
4.4 KiB
Vue
<template>
|
|
<div class="fill-repeat">
|
|
<div>
|
|
<div class="title">Image</div>
|
|
<div class="content">
|
|
<img :src="object.info.fill.source" alt="" />
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div class="title">Sttings</div>
|
|
<div class="content">
|
|
<div>
|
|
<div class="label">Rotation</div>
|
|
<div class="value">
|
|
<depth-input
|
|
v-model="angle"
|
|
type="number"
|
|
@input="inputFillTransform"
|
|
@change="changeFillTransform"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div class="label">Scale</div>
|
|
<div class="value">
|
|
<depth-slider
|
|
v-model="scale"
|
|
:min="10"
|
|
:max="1000"
|
|
:tipFormatter="(v) => v + '%'"
|
|
@input="inputFillTransform"
|
|
@change="changeFillTransform"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div class="label">Gap X</div>
|
|
<div class="value">
|
|
<depth-slider
|
|
v-model="gapX"
|
|
:min="0"
|
|
:max="1000"
|
|
:tipFormatter="(v) => v + 'px'"
|
|
@input="inputFillGap"
|
|
@change="changeFillGap"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div class="label">Gap Y</div>
|
|
<div class="value">
|
|
<depth-slider
|
|
v-model="gapY"
|
|
:min="0"
|
|
:max="1000"
|
|
:tipFormatter="(v) => v + 'px'"
|
|
@input="inputFillGap"
|
|
@change="changeFillGap"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div class="label">Offset</div>
|
|
<div class="value">
|
|
<depth-offset-tool
|
|
v-model="offset"
|
|
:show-dish="false"
|
|
@input="inputFillTransform"
|
|
@change="changeFillTransform"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div class="offset-tool-dish">
|
|
<depth-offset-tool
|
|
v-model="offset"
|
|
:show-input="false"
|
|
@input="inputFillTransform"
|
|
@change="changeFillTransform"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, inject, computed, nextTick, onBeforeUnmount } from 'vue'
|
|
import DepthOffsetTool from '../tools/depth-offset-tool.vue'
|
|
import { getTransformScaleAngle } from '../../manager/ObjectManager'
|
|
const objectManager = inject('objectManager') as any
|
|
const stateManager = inject('stateManager') as any
|
|
const props = defineProps({
|
|
object: {
|
|
type: Object,
|
|
default: () => ({})
|
|
}
|
|
})
|
|
const id = computed(() => props.object.info.id)
|
|
const angle = ref(0)
|
|
const scale = ref(100)
|
|
const gapX = ref(0)
|
|
const gapY = ref(0)
|
|
const offset = ref({ x: 0, y: 0 })
|
|
|
|
const updateData = async () => {
|
|
await nextTick()
|
|
const fill = props.object.fill
|
|
angle.value = getTransformScaleAngle(fill?.patternTransform).angle
|
|
scale.value = Math.round(getTransformScaleAngle(fill?.patternTransform).scale * 100)
|
|
gapX.value = props.object.info.fill.gapX
|
|
gapY.value = props.object.info.fill.gapY
|
|
offset.value = {
|
|
x: Math.round((fill.offsetX / props.object.width) * 100),
|
|
y: Math.round((fill.offsetY / props.object.height) * 100)
|
|
}
|
|
}
|
|
updateData()
|
|
|
|
const inputFillTransform = () => setFillTransform(false)
|
|
const changeFillTransform = () => setFillTransform(true)
|
|
const setFillTransform = (isRecord: boolean) => {
|
|
const options = {
|
|
scale: scale.value / 100,
|
|
angle: angle.value,
|
|
offsetX: props.object.width * (offset.value.x / 100),
|
|
offsetY: props.object.height * (offset.value.y / 100)
|
|
}
|
|
objectManager.updateFillRepeatTransform(id.value, options, isRecord)
|
|
}
|
|
|
|
const inputFillGap = () => setFillGap(false)
|
|
const changeFillGap = () => setFillGap(true)
|
|
const setFillGap = (isRecord: boolean) => {
|
|
const options = {
|
|
gapX: gapX.value,
|
|
gapY: gapY.value
|
|
}
|
|
objectManager.updateFillRepeatGap(id.value, options, isRecord)
|
|
}
|
|
|
|
stateManager.event.add('canvas:undo', updateData)
|
|
stateManager.event.add('canvas:redo', updateData)
|
|
onBeforeUnmount(() => {
|
|
stateManager.event.remove('canvas:undo', updateData)
|
|
stateManager.event.remove('canvas:redo', updateData)
|
|
})
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.fill-repeat {
|
|
> div {
|
|
> .content {
|
|
> img {
|
|
display: block;
|
|
width: 55%;
|
|
height: auto;
|
|
margin: 0 auto;
|
|
}
|
|
> div {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-bottom: 1.6rem;
|
|
&:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
> .label {
|
|
min-width: 6rem;
|
|
margin-right: 0.8rem;
|
|
font-size: 1.2rem;
|
|
}
|
|
> .value {
|
|
flex: 1;
|
|
}
|
|
}
|
|
> .offset-tool-dish {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|