|
@@ -2,33 +2,34 @@
|
|
|
<div class="props">
|
|
|
<t-tabs v-model="data.tab">
|
|
|
<t-tab-panel :value="1" label="外观">
|
|
|
- <t-space direction="vertical" class="panel">
|
|
|
+ <t-space direction="vertical" class="py-16 w-full">
|
|
|
<div class="form-item">
|
|
|
- <t-input-number
|
|
|
+ <t-input
|
|
|
+ class="ml-4"
|
|
|
label="X"
|
|
|
- v-model="data.rect.x"
|
|
|
- placeholder="x"
|
|
|
- theme="normal"
|
|
|
+ placeholder="x坐标"
|
|
|
+ v-model.number="data.rect.x"
|
|
|
style="width: 80px"
|
|
|
- @change="changeRect"
|
|
|
+ :format="decimalPlaces"
|
|
|
+ @change="changeValue('x')"
|
|
|
/>
|
|
|
<t-icon name="link" class="hidden ml-4" />
|
|
|
- <t-input-number
|
|
|
- class="ml-8"
|
|
|
+ <t-input
|
|
|
+ class="ml-4"
|
|
|
label="Y"
|
|
|
- placeholder="y"
|
|
|
- theme="normal"
|
|
|
- v-model="data.rect.y"
|
|
|
+ placeholder="y坐标"
|
|
|
+ v-model.number="data.rect.y"
|
|
|
style="width: 80px"
|
|
|
- @change="changeRect"
|
|
|
+ :format="decimalPlaces"
|
|
|
+ @change="changeValue('y')"
|
|
|
/>
|
|
|
-
|
|
|
<t-input
|
|
|
- class="ml-8"
|
|
|
- v-model="data.pen.rotate"
|
|
|
+ class="ml-16"
|
|
|
+ v-model.number="data.pen.rotate"
|
|
|
placeholder="旋转"
|
|
|
- style="width: 72px"
|
|
|
- @change="changeValue"
|
|
|
+ style="width: 80px"
|
|
|
+ :format="decimalRound"
|
|
|
+ @change="changeValue('rotate')"
|
|
|
>
|
|
|
<template #prefix-icon>
|
|
|
<svg class="l-icon" aria-hidden="true">
|
|
@@ -38,14 +39,15 @@
|
|
|
</t-input>
|
|
|
</div>
|
|
|
<div class="form-item hover-icons" style="margin-top: -12px">
|
|
|
- <t-input-number
|
|
|
+ <t-input
|
|
|
+ class="ml-4"
|
|
|
label="W"
|
|
|
- v-model="data.rect.width"
|
|
|
+ v-model.number="data.rect.width"
|
|
|
placeholder="宽"
|
|
|
- theme="normal"
|
|
|
min="1"
|
|
|
style="width: 80px"
|
|
|
- @change="changeRect(1)"
|
|
|
+ :format="decimalPlaces"
|
|
|
+ @change="changeValue('width')"
|
|
|
/>
|
|
|
<t-tooltip v-if="data.pen.ratio" content="固定比例" placement="top">
|
|
|
<t-icon
|
|
@@ -62,23 +64,23 @@
|
|
|
/>
|
|
|
</t-tooltip>
|
|
|
|
|
|
- <t-input-number
|
|
|
- class="ml-8"
|
|
|
+ <t-input
|
|
|
+ class="ml-4"
|
|
|
label="H"
|
|
|
placeholder="高"
|
|
|
- theme="normal"
|
|
|
+ v-model.number="data.rect.height"
|
|
|
min="1"
|
|
|
- v-model="data.rect.height"
|
|
|
style="width: 80px"
|
|
|
- @change="changeRect(2)"
|
|
|
+ :format="decimalPlaces"
|
|
|
+ @change="changeValue('height')"
|
|
|
/>
|
|
|
|
|
|
<t-input
|
|
|
- class="ml-8"
|
|
|
+ class="ml-16"
|
|
|
v-model.number="data.pen.borderRadius"
|
|
|
placeholder="圆角"
|
|
|
- style="width: 72px"
|
|
|
- @change="changeValue"
|
|
|
+ style="width: 80px"
|
|
|
+ @change="changeValue('borderRadius')"
|
|
|
>
|
|
|
<template #prefix-icon>
|
|
|
<svg class="l-icon" aria-hidden="true">
|
|
@@ -87,33 +89,320 @@
|
|
|
</template>
|
|
|
</t-input>
|
|
|
</div>
|
|
|
+
|
|
|
<t-divider style="margin: -8px 0" />
|
|
|
- <div class="form-item" style="margin-top: -12px">
|
|
|
+ <div class="form-item px-16" style="margin-top: -12px">
|
|
|
<label>不透明度</label>
|
|
|
<t-slider
|
|
|
v-model="data.pen.globalAlpha"
|
|
|
:min="0"
|
|
|
:max="1"
|
|
|
:step="0.01"
|
|
|
- @change="changeValue"
|
|
|
+ @change="changeValue('globalAlpha')"
|
|
|
/>
|
|
|
<span class="ml-16" style="width: 50px; line-height: 30px">
|
|
|
{{ data.pen.globalAlpha }}
|
|
|
</span>
|
|
|
</div>
|
|
|
- <div class="form-item" style="margin-top: -12px">
|
|
|
- <label>不透明度</label>
|
|
|
- <t-slider
|
|
|
- v-model="data.pen.globalAlpha"
|
|
|
- :min="0"
|
|
|
- :max="1"
|
|
|
- :step="0.01"
|
|
|
- @change="changeValue"
|
|
|
- />
|
|
|
- <span class="ml-16" style="width: 50px; line-height: 30px">
|
|
|
- {{ data.pen.globalAlpha }}
|
|
|
- </span>
|
|
|
+ <t-divider style="margin: -8px 0" />
|
|
|
+ <div class="form-item px-16" style="margin-top: -12px">
|
|
|
+ <t-checkbox
|
|
|
+ v-model="data.pen.flipX"
|
|
|
+ @change="changeValue('flipX')"
|
|
|
+ style="width: 100px"
|
|
|
+ >
|
|
|
+ 水平翻转
|
|
|
+ </t-checkbox>
|
|
|
+ <t-checkbox
|
|
|
+ v-model="data.pen.flipY"
|
|
|
+ @change="changeValue('flipY')"
|
|
|
+ style="width: 100px"
|
|
|
+ >
|
|
|
+ 垂直翻转
|
|
|
+ </t-checkbox>
|
|
|
</div>
|
|
|
+ <t-collapse
|
|
|
+ :defaultValue="['1']"
|
|
|
+ expandIconPlacement="right"
|
|
|
+ :borderless="true"
|
|
|
+ >
|
|
|
+ <t-collapse-panel
|
|
|
+ v-if="data.pen.props.color !== false"
|
|
|
+ value="1"
|
|
|
+ header="外观"
|
|
|
+ >
|
|
|
+ <t-space direction="vertical" size="small" class="w-full">
|
|
|
+ <div class="form-item">
|
|
|
+ <t-color-picker
|
|
|
+ class="simple mt-8 mr-4"
|
|
|
+ format="CSS"
|
|
|
+ :enable-alpha="true"
|
|
|
+ :color-modes="['monochrome']"
|
|
|
+ :show-primary-color-preview="false"
|
|
|
+ :clearable="true"
|
|
|
+ v-model="data.pen.color"
|
|
|
+ @change="changeValue('color')"
|
|
|
+ />
|
|
|
+ <label style="width: 44px">前景</label>
|
|
|
+ <t-color-picker
|
|
|
+ class="simple mt-8 mr-4"
|
|
|
+ format="CSS"
|
|
|
+ :color-modes="['monochrome']"
|
|
|
+ :show-primary-color-preview="false"
|
|
|
+ v-model="data.pen.background"
|
|
|
+ @change="changeValue('background')"
|
|
|
+ />
|
|
|
+ <label style="width: 44px">背景</label>
|
|
|
+
|
|
|
+ <t-color-picker
|
|
|
+ class="simple mt-8 mr-4"
|
|
|
+ format="CSS"
|
|
|
+ :color-modes="['monochrome']"
|
|
|
+ :show-primary-color-preview="false"
|
|
|
+ v-model="data.pen.hoverColor"
|
|
|
+ @change="changeValue('hoverColor')"
|
|
|
+ />
|
|
|
+ <label style="width: 44px">悬停</label>
|
|
|
+
|
|
|
+ <t-color-picker
|
|
|
+ class="simple mt-8 mr-4"
|
|
|
+ format="CSS"
|
|
|
+ :color-modes="['monochrome']"
|
|
|
+ :show-primary-color-preview="false"
|
|
|
+ v-model="data.pen.activeColor"
|
|
|
+ @change="changeValue('activeColor')"
|
|
|
+ />
|
|
|
+ <label style="width: 44px">选中</label>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="form-item">
|
|
|
+ <label style="width: 32px">线条 </label>
|
|
|
+ <t-select
|
|
|
+ v-model="data.pen.dash"
|
|
|
+ size="small"
|
|
|
+ placeholder="线条样式"
|
|
|
+ @change="changeValue('dash')"
|
|
|
+ style="width: 80px"
|
|
|
+ >
|
|
|
+ <template #valueDisplay="{ value }">
|
|
|
+ <svg
|
|
|
+ xmlns="http://www.w3.org/2000/svg"
|
|
|
+ version="1.1"
|
|
|
+ style="width: 100%; height: 20px"
|
|
|
+ >
|
|
|
+ <g fill="none" stroke="var(--color)" stroke-width="1">
|
|
|
+ <path v-if="value === 0" d="M0 9 l85 0" />
|
|
|
+ <path
|
|
|
+ v-else-if="value === 1"
|
|
|
+ stroke-dasharray="5 5"
|
|
|
+ d="M0 9 l85 0"
|
|
|
+ />
|
|
|
+ <path
|
|
|
+ v-else-if="value === 2"
|
|
|
+ stroke-dasharray="10 10"
|
|
|
+ d="M0 9 l85 0"
|
|
|
+ />
|
|
|
+ <path
|
|
|
+ v-else-if="value === 3"
|
|
|
+ stroke-dasharray="10 10 2 10"
|
|
|
+ d="M0 9 l85 0"
|
|
|
+ />
|
|
|
+ </g>
|
|
|
+ </svg>
|
|
|
+ </template>
|
|
|
+ <t-option :key="0" :value="0">
|
|
|
+ <svg
|
|
|
+ xmlns="http://www.w3.org/2000/svg"
|
|
|
+ version="1.1"
|
|
|
+ style="width: 80px; height: 14px"
|
|
|
+ >
|
|
|
+ <g fill="none" stroke="var(--color)" stroke-width="1">
|
|
|
+ <path d="M0 9 l85 0" />
|
|
|
+ </g>
|
|
|
+ </svg>
|
|
|
+ </t-option>
|
|
|
+ <t-option :key="1" :value="1">
|
|
|
+ <svg
|
|
|
+ xmlns="http://www.w3.org/2000/svg"
|
|
|
+ version="1.1"
|
|
|
+ style="width: 80px; height: 14px"
|
|
|
+ >
|
|
|
+ <g fill="none" stroke="var(--color)" stroke-width="1">
|
|
|
+ <path stroke-dasharray="5 5" d="M0 9 l85 0" />
|
|
|
+ </g>
|
|
|
+ </svg>
|
|
|
+ </t-option>
|
|
|
+ <t-option :key="2" :value="2">
|
|
|
+ <svg
|
|
|
+ xmlns="http://www.w3.org/2000/svg"
|
|
|
+ version="1.1"
|
|
|
+ style="width: 80px; height: 14px"
|
|
|
+ >
|
|
|
+ <g fill="none" stroke="var(--color)" stroke-width="1">
|
|
|
+ <path stroke-dasharray="10 10" d="M0 9 l85 0" />
|
|
|
+ </g>
|
|
|
+ </svg>
|
|
|
+ </t-option>
|
|
|
+ <t-option :key="3" :value="3">
|
|
|
+ <svg
|
|
|
+ xmlns="http://www.w3.org/2000/svg"
|
|
|
+ version="1.1"
|
|
|
+ style="width: 80px; height: 14px"
|
|
|
+ >
|
|
|
+ <g fill="none" stroke="var(--color)" stroke-width="1">
|
|
|
+ <path stroke-dasharray="10 10 2 10" d="M0 9 l85 0" />
|
|
|
+ </g>
|
|
|
+ </svg>
|
|
|
+ </t-option>
|
|
|
+ </t-select>
|
|
|
+ <t-input-number
|
|
|
+ theme="normal"
|
|
|
+ placeholder="线条宽度"
|
|
|
+ v-model="data.pen.lineWidth"
|
|
|
+ :min="1"
|
|
|
+ :decimalPlaces="0"
|
|
|
+ @change="changeValue('lineWidth')"
|
|
|
+ class="ml-4"
|
|
|
+ style="width: 40px"
|
|
|
+ />
|
|
|
+ <t-tooltip content="线条渐变" placement="top">
|
|
|
+ <div class="flex middle ml-8">
|
|
|
+ <t-checkbox
|
|
|
+ v-model="data.pen.strokeType"
|
|
|
+ @change="changeValue('strokeType')"
|
|
|
+ style="width: 22px"
|
|
|
+ />
|
|
|
+
|
|
|
+ <t-color-picker
|
|
|
+ v-if="data.pen.strokeType"
|
|
|
+ class="simple mr-4"
|
|
|
+ format="CSS"
|
|
|
+ :color-modes="['linear-gradient']"
|
|
|
+ :show-primary-color-preview="false"
|
|
|
+ :clearable="true"
|
|
|
+ :enableAlpha="true"
|
|
|
+ v-model="data.pen.lineGradientColors"
|
|
|
+ @change="changeValue('lineGradientColors')"
|
|
|
+ placeholder="无"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </t-tooltip>
|
|
|
+ </div>
|
|
|
+ <div class="flex" style="margin-left: 40px">
|
|
|
+ <div class="flex column middle">
|
|
|
+ <t-radio-group
|
|
|
+ size="small"
|
|
|
+ v-model="data.pen.lineCap"
|
|
|
+ default-value="butt"
|
|
|
+ @change="changeValue('lineCap')"
|
|
|
+ >
|
|
|
+ <t-radio-button value="butt">
|
|
|
+ <t-tooltip content="默认" placement="top">
|
|
|
+ <svg class="l-icon" aria-hidden="true">
|
|
|
+ <use xlink:href="#l-duandian1"></use>
|
|
|
+ </svg>
|
|
|
+ </t-tooltip>
|
|
|
+ </t-radio-button>
|
|
|
+ <t-radio-button value="round">
|
|
|
+ <t-tooltip content="圆形" placement="top">
|
|
|
+ <svg class="l-icon" aria-hidden="true">
|
|
|
+ <use xlink:href="#l-duandian2"></use>
|
|
|
+ </svg>
|
|
|
+ </t-tooltip>
|
|
|
+ </t-radio-button>
|
|
|
+ <t-radio-button value="square">
|
|
|
+ <t-tooltip content="方形" placement="top">
|
|
|
+ <svg class="l-icon" aria-hidden="true">
|
|
|
+ <use xlink:href="#l-duandian3"></use>
|
|
|
+ </svg>
|
|
|
+ </t-tooltip>
|
|
|
+ </t-radio-button>
|
|
|
+ </t-radio-group>
|
|
|
+ <div class="mt-4" style="font-size: 12px">末端样式</div>
|
|
|
+ </div>
|
|
|
+ <div class="flex column middle ml-16">
|
|
|
+ <t-radio-group
|
|
|
+ size="small"
|
|
|
+ v-model="data.pen.lineJoin"
|
|
|
+ default-value="miter"
|
|
|
+ @change="changeValue('lineJoin')"
|
|
|
+ >
|
|
|
+ <t-radio-button value="miter">
|
|
|
+ <t-tooltip content="默认" placement="top">
|
|
|
+ <svg class="l-icon" aria-hidden="true">
|
|
|
+ <use xlink:href="#l-jiedian1"></use>
|
|
|
+ </svg>
|
|
|
+ </t-tooltip>
|
|
|
+ </t-radio-button>
|
|
|
+ <t-radio-button value="round">
|
|
|
+ <t-tooltip content="圆形" placement="top">
|
|
|
+ <svg class="l-icon" aria-hidden="true">
|
|
|
+ <use xlink:href="#l-jiedian2"></use>
|
|
|
+ </svg>
|
|
|
+ </t-tooltip>
|
|
|
+ </t-radio-button>
|
|
|
+ <t-radio-button value="bevel">
|
|
|
+ <t-tooltip content="斜角" placement="top">
|
|
|
+ <svg class="l-icon" aria-hidden="true">
|
|
|
+ <use xlink:href="#l-jiedian3"></use>
|
|
|
+ </svg>
|
|
|
+ </t-tooltip>
|
|
|
+ </t-radio-button>
|
|
|
+ </t-radio-group>
|
|
|
+ <div class="mt-4" style="font-size: 12px">连接样式</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="form-item">
|
|
|
+ <label style="width: 32px">阴影 </label>
|
|
|
+ <div class="flex middle ml-8">
|
|
|
+ <t-checkbox
|
|
|
+ v-model="data.pen.shadow"
|
|
|
+ @change="changeValue('shadow')"
|
|
|
+ style="width: 22px"
|
|
|
+ />
|
|
|
+ <t-color-picker
|
|
|
+ v-if="data.pen.shadow"
|
|
|
+ class="simple"
|
|
|
+ format="CSS"
|
|
|
+ :color-modes="['monochrome']"
|
|
|
+ :show-primary-color-preview="false"
|
|
|
+ v-model="data.pen.shadowColor"
|
|
|
+ @change="changeValue('shadowColor')"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="form-item" v-if="data.pen.shadow">
|
|
|
+ <label style="width: 28px"></label>
|
|
|
+ <div class="flex" style="margin-top: -8px">
|
|
|
+ <t-input
|
|
|
+ class="ml-4"
|
|
|
+ label="X"
|
|
|
+ placeholder="x偏移"
|
|
|
+ v-model.number="data.pen.shadowOffsetX"
|
|
|
+ style="width: 60px"
|
|
|
+ @change="changeValue('x')"
|
|
|
+ />
|
|
|
+ <t-input
|
|
|
+ class="ml-4"
|
|
|
+ label="Y"
|
|
|
+ placeholder="y偏移"
|
|
|
+ v-model.number="data.pen.shadowOffsetY"
|
|
|
+ style="width: 60px"
|
|
|
+ @change="changeValue('shadowOffsetY')"
|
|
|
+ />
|
|
|
+ <t-input
|
|
|
+ class="ml-4"
|
|
|
+ label="模糊"
|
|
|
+ placeholder="模糊"
|
|
|
+ v-model.number="data.pen.shadowBlur"
|
|
|
+ style="width: 64px"
|
|
|
+ @change="changeValue('shadowBlur')"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </t-space>
|
|
|
+ </t-collapse-panel>
|
|
|
+ </t-collapse>
|
|
|
</t-space>
|
|
|
</t-tab-panel>
|
|
|
<t-tab-panel :value="2" label="事件"> </t-tab-panel>
|
|
@@ -143,6 +432,16 @@ const { selections } = useSelection();
|
|
|
|
|
|
onBeforeMount(() => {
|
|
|
data.pen = selections.pen;
|
|
|
+ if (!data.pen.props) {
|
|
|
+ data.pen.props = {};
|
|
|
+ }
|
|
|
+ if (!data.pen.globalAlpha) {
|
|
|
+ data.pen.globalAlpha = 1;
|
|
|
+ }
|
|
|
+ if (!data.pen.dash) {
|
|
|
+ data.pen.dash = 0;
|
|
|
+ }
|
|
|
+ data.pen.shadow = !!data.pen.shadowColor;
|
|
|
getRect();
|
|
|
meta2d.on('translatePens', getRect);
|
|
|
meta2d.on('resizePens', getRect);
|
|
@@ -153,25 +452,38 @@ const getRect = () => {
|
|
|
data.rect = meta2d.getPenRect(data.pen);
|
|
|
};
|
|
|
|
|
|
-const changeRect = (mode?: number) => {
|
|
|
- //宽高比锁定
|
|
|
- if (data.pen.ratio) {
|
|
|
- if (mode === 1) {
|
|
|
- data.rect.height = (data.rect.width / data.pen.width) * data.pen.height;
|
|
|
- } else if (mode === 2) {
|
|
|
- data.rect.width = (data.rect.height / data.pen.height) * data.pen.width;
|
|
|
- }
|
|
|
+const decimalPlaces = (val: number) => {
|
|
|
+ if (!val) {
|
|
|
+ return 0;
|
|
|
}
|
|
|
+ return Math.round(+val * 100) / 100;
|
|
|
+};
|
|
|
|
|
|
- meta2d.setPenRect(data.pen, data.rect, true);
|
|
|
+const decimalRound = (val: number) => {
|
|
|
+ return Math.round(+val || 0);
|
|
|
};
|
|
|
|
|
|
-const changeValue = (mode?: number) => {
|
|
|
- switch (mode) {
|
|
|
- case 1:
|
|
|
- break;
|
|
|
+const changeValue = (prop: string) => {
|
|
|
+ const v: any = { id: data.pen.id };
|
|
|
+ v[prop] = data.pen[prop];
|
|
|
+ if (prop === 'x') {
|
|
|
+ v.x = data.rect.x;
|
|
|
+ } else if (prop === 'y') {
|
|
|
+ v.y = data.rect.y;
|
|
|
+ } else if (prop === 'width') {
|
|
|
+ v.height = (data.rect.width / data.pen.width) * data.pen.height;
|
|
|
+ } else if (prop === 'height') {
|
|
|
+ v.width = (data.rect.height / data.pen.height) * data.pen.width;
|
|
|
+ } else if (prop === 'shadow') {
|
|
|
+ if (v[prop]) {
|
|
|
+ !v.shadowOffsetX && (v.shadowOffsetX = 0);
|
|
|
+ !v.shadowOffsetY && (v.shadowOffsetY = 0);
|
|
|
+ !v.shadowBlur && (v.shadowBlur = 0);
|
|
|
+ } else {
|
|
|
+ v.shadowColor = '';
|
|
|
+ }
|
|
|
}
|
|
|
- meta2d.render();
|
|
|
+ meta2d.setValue(v);
|
|
|
};
|
|
|
|
|
|
onUnmounted(() => {
|
|
@@ -182,5 +494,17 @@ onUnmounted(() => {
|
|
|
</script>
|
|
|
<style lang="postcss" scoped>
|
|
|
.props {
|
|
|
+ :deep(.t-color-picker__trigger) {
|
|
|
+ &.small {
|
|
|
+ width: 90px;
|
|
|
+
|
|
|
+ .t-input {
|
|
|
+ width: 90px;
|
|
|
+ .t-input__inner {
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|