You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

236 lines
6.3 KiB
Vue

<template>
<div class="box" v-if="mixinState.mSelectMode === 'one'">
<!-- 字体属性 -->
<div v-show="textTypeConf.includes(mixinState.mSelectOneType)">
<!-- 字体属性 -->
</div>
<!-- ID属性 -->
<div>
<div class="flex-view">
<div class="flex-item">
<span class="label">{{ $t("attributes.id") }}</span>
<div class="content slider-box">
<input
v-model="baseAttr.id"
@change="changeCommon('id', baseAttr.id)"
/>
</div>
</div>
</div>
</div>
<!-- 用户属性 -->
<!-- TODO 缺少删除 图标 -->
<div>
<ul>
<li class="flex-view" v-for="(v, k) in baseAttr.userProperty" :key="k">
<div class="flex-item">
<span class="content slider-box">
<input
v-model="baseAttr.userProperty[k].key"
@change="
changeCommon('userProperty_key', baseAttr.userProperty)
"
/>
</span>
<div class="content slider-box">
<input
v-model="baseAttr.userProperty[k].value"
@change="
changeCommon('userProperty_value', baseAttr.userProperty)
"
/>
</div>
</div>
</li>
<li
class="flex-view"
style="justify-content: center; color: dodgerblue; text-align: center"
@click="
() => {
baseAttr.userProperty.push({
key: 'key' + baseAttr.userProperty.length,
value: 'value'
});
}
"
>
<span>新增一项</span>
</li>
</ul>
</div>
</div>
</template>
<script setup name="AttrBute">
import useSelect from "@/hooks/select";
import { fetchArrayByAttrObject, setAttrObjectByArray } from "@/utils/utils";
// 属性选项
import { textTypeConf } from "@/config/attribute/baseType";
const event = inject("event");
const update = getCurrentInstance();
const { mixinState, canvasEditor } = useSelect();
// 通用属性
const baseAttr = reactive({
id: "",
opacity: 0,
angle: 0,
fill: "#fff",
left: 0,
top: 0,
strokeWidth: 0,
strokeDashArray: [],
stroke: "#fff",
shadow: {
color: "#fff",
blur: 0,
offsetX: 0,
offsetY: 0
},
points: {},
selectable: false,
userProperty: [
{
key: "key",
value: "value"
}
]
});
// 动效属性
const animationAttr = reactive({
type: "None"
});
// 字体属性
const fontAttr = reactive({
fontSize: 0,
fontFamily: "",
lineHeight: 0,
charSpacing: 0,
fontWeight: "",
textBackgroundColor: "#fff",
textAlign: "",
fontStyle: "",
underline: false,
linethrough: false,
overline: false
});
const getObjectAttr = e => {
const activeObject = canvasEditor.canvas.getActiveObject();
// 不是当前obj跳过
if (e && e.target && e.target !== activeObject) return;
if (activeObject) {
// base
baseAttr.id = activeObject.get("id");
baseAttr.userProperty = fetchArrayByAttrObject(
activeObject.get("userProperty")
);
baseAttr.opacity = activeObject.get("opacity") * 100;
baseAttr.fill = activeObject.get("fill");
baseAttr.left = activeObject.get("left");
baseAttr.top = activeObject.get("top");
baseAttr.stroke = activeObject.get("stroke");
baseAttr.strokeWidth = activeObject.get("strokeWidth");
baseAttr.shadow = activeObject.get("shadow") || {};
baseAttr.angle = activeObject.get("angle") || 0;
baseAttr.points = activeObject.get("points") || {};
baseAttr.selectable = activeObject.get("selectable");
console.log("activeObject", activeObject);
const textTypes = ["i-text", "text", "textbox"];
if (textTypes.includes(activeObject.type)) {
fontAttr.fontSize = activeObject.get("fontSize");
fontAttr.fontFamily = activeObject.get("fontFamily");
fontAttr.lineHeight = activeObject.get("lineHeight");
fontAttr.textAlign = activeObject.get("textAlign");
fontAttr.underline = activeObject.get("underline");
fontAttr.linethrough = activeObject.get("linethrough");
fontAttr.charSpacing = activeObject.get("charSpacing");
fontAttr.overline = activeObject.get("overline");
fontAttr.fontStyle = activeObject.get("fontStyle");
fontAttr.textBackgroundColor = activeObject.get("textBackgroundColor");
fontAttr.fontWeight = activeObject.get("fontWeight");
}
// update 动画属性
if (activeObject?.animation && activeObject?.animation?.type != "None") {
const animateObject = activeObject.get("animation");
animationAttr.type = animateObject.type;
}
}
};
const selectCancel = () => {
baseAttr.fill = "";
update?.proxy?.$forceUpdate();
};
const init = () => {
// 获取字体数据
event.on("selectCancel", selectCancel);
event.on("selectOne", getObjectAttr);
canvasEditor.canvas.on("object:modified", getObjectAttr);
};
// 通用属性改变
const changeCommon = (key, value) => {
const activeObject = canvasEditor.canvas.getActiveObjects()[0];
// 透明度特殊转换
if (key === "opacity") {
activeObject && activeObject.set(key, value / 100);
canvasEditor.canvas.renderAll();
return;
}
// 旋转角度适配
if (key === "angle") {
activeObject.rotate(value);
canvasEditor.canvas.renderAll();
return;
}
// 用户属性
if (key === "userProperty_key") {
activeObject &&
activeObject.set(
"userProperty",
setAttrObjectByArray(baseAttr.userProperty)
);
canvasEditor.canvas.renderAll();
return;
}
if (key === "userProperty_value") {
activeObject &&
activeObject.set(
"userProperty",
setAttrObjectByArray(baseAttr.userProperty)
);
canvasEditor.canvas.renderAll();
return;
}
activeObject && activeObject.set(key, value);
canvasEditor.canvas.renderAll();
// 更新属性
getObjectAttr();
};
onMounted(init);
onBeforeUnmount(() => {
event.off("selectCancel", selectCancel);
event.off("selectOne", getObjectAttr);
canvasEditor.canvas.off("object:modified", getObjectAttr);
});
</script>
<style scoped>
.flex-view {
width: 100%;
margin-bottom: 5px;
padding: 5px;
display: inline-flex;
justify-content: space-between;
border-radius: 5px;
background: #f6f7f9;
}
</style>