深度画布调整属性设置
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
<span class="label">{{ item.label }}</span>
|
||||
</div>
|
||||
<button @click="onCreate">创建</button>
|
||||
<button @click="onReset">重置</button>
|
||||
</div>
|
||||
</transition>
|
||||
<brush-control-panel v-if="show" :currentTool="currentTool2" style="top: 14rem" />
|
||||
@@ -61,6 +62,9 @@
|
||||
const onCreate = () => {
|
||||
stateManager.aiSelectboxToolManager.createSelectbox()
|
||||
}
|
||||
const onReset = () => {
|
||||
stateManager.aiSelectboxToolManager.resetDemoObject()
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
// 淡入淡出动画
|
||||
|
||||
@@ -1,64 +1,153 @@
|
||||
<template>
|
||||
<div class="basic-info">
|
||||
<div class="basic-info h">
|
||||
<div>
|
||||
<span class="label">X:</span>
|
||||
<span class="value">{{ object.left }}</span>
|
||||
<div class="title">Position</div>
|
||||
<div class="content">
|
||||
<div>
|
||||
<depth-input
|
||||
before="X"
|
||||
type="number"
|
||||
v-model="data.left"
|
||||
@input="onInpot"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<span class="label">Y:</span>
|
||||
<span class="value">{{ object.top }}</span>
|
||||
<depth-input
|
||||
before="Y"
|
||||
type="number"
|
||||
v-model="data.top"
|
||||
@input="onInpot"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div>
|
||||
<depth-input
|
||||
before="W"
|
||||
type="number"
|
||||
v-model="data.width"
|
||||
@input="onInpot"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<span class="label">Width:</span>
|
||||
<span class="value">{{ object.width }}</span>
|
||||
<depth-input
|
||||
before="H"
|
||||
type="number"
|
||||
v-model="data.height"
|
||||
@input="onInpot"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span class="label">Height:</span>
|
||||
<span class="value">{{ object.height }}</span>
|
||||
<div class="title">Scale</div>
|
||||
<div class="content">
|
||||
<div>
|
||||
<depth-input
|
||||
type="number"
|
||||
before="X"
|
||||
after="%"
|
||||
v-model="data.scaleX"
|
||||
@input="onInpot"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<span class="label">缩放X:</span>
|
||||
<span class="value">{{ object.scaleX }}</span>
|
||||
<depth-input
|
||||
type="number"
|
||||
before="Y"
|
||||
after="%"
|
||||
v-model="data.scaleY"
|
||||
@input="onInpot"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<span class="label">缩放Y:</span>
|
||||
<span class="value">{{ object.scaleY }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="label">Angle:</span>
|
||||
<span class="value">{{ object.angle }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, inject, computed, watch, onMounted } from 'vue'
|
||||
import { ref, inject, computed, nextTick, onBeforeUnmount, reactive, watch } from 'vue'
|
||||
import DepthInput from '../tools/depth-input.vue'
|
||||
const objectManager = inject('objectManager') as any
|
||||
const stateManager = inject('stateManager') as any
|
||||
const props = defineProps({
|
||||
object: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
onMounted(() => {})
|
||||
const id = computed(() => props.object.info.id)
|
||||
|
||||
const data = reactive({
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
scaleX: 1,
|
||||
scaleY: 1
|
||||
})
|
||||
const updateData = async () => {
|
||||
await nextTick()
|
||||
data.top = Math.round(props.object.top)
|
||||
data.left = Math.round(props.object.left)
|
||||
data.width = Math.round(props.object.width)
|
||||
data.height = Math.round(props.object.height)
|
||||
data.scaleX = Math.round(props.object.scaleX * 100)
|
||||
data.scaleY = Math.round(props.object.scaleY * 100)
|
||||
}
|
||||
updateData()
|
||||
watch(() => props.object, updateData)
|
||||
|
||||
const onInpot = () => setPriority(false)
|
||||
const onChange = () => setPriority(true)
|
||||
const setPriority = (isRecord: boolean) => {
|
||||
const options = {
|
||||
...data,
|
||||
scaleX: data.scaleX / 100,
|
||||
scaleY: data.scaleY / 100
|
||||
}
|
||||
objectManager.updateProperty(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>
|
||||
.basic-info {
|
||||
--details-item-margin-bottom: 1.6rem;
|
||||
> div {
|
||||
padding: 0.8rem 0;
|
||||
> .content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
> .label {
|
||||
font-size: 1.6rem;
|
||||
color: #000;
|
||||
font-weight: bold;
|
||||
min-width: 7rem;
|
||||
text-align: right;
|
||||
margin-right: 0.8rem;
|
||||
justify-content: center;
|
||||
> div {
|
||||
flex: 1;
|
||||
margin-right: 3rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
--depth-input-height: 2.4rem;
|
||||
--depth-input-bg-color: rgba(249, 249, 250, 1);
|
||||
--depth-input-border-color: rgba(230, 230, 231, 1);
|
||||
--depth-input-decorate-color: rgba(69, 71, 84, 0.1);
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
> .label {
|
||||
font-size: 1.2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
}
|
||||
> .value {
|
||||
font-size: 1.6rem;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, inject, computed, nextTick, onBeforeUnmount } from 'vue'
|
||||
import { ref, inject, computed, nextTick, onBeforeUnmount, watch } from 'vue'
|
||||
import DepthOffsetTool from '../tools/depth-offset-tool.vue'
|
||||
import DepthSlider from '../tools/depth-slider.vue'
|
||||
import DepthInput from '../tools/depth-input.vue'
|
||||
@@ -134,6 +134,7 @@
|
||||
opacity.value = Math.round(props.object.opacity * 100)
|
||||
}
|
||||
updateData()
|
||||
watch(() => props.object, updateData)
|
||||
|
||||
const inputFillTransform = () => setFillTransform(false)
|
||||
const changeFillTransform = () => setFillTransform(true)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="content" v-if="isShow" v-show="show">
|
||||
<!-- <basic-info :object="activeObject" /> -->
|
||||
<basic-info :object="activeObject" />
|
||||
<fill-repeat :object="activeObject" v-if="isRepeat" />
|
||||
<shape-setting :object="activeObject" v-if="isShape && !isRepeat" />
|
||||
</div>
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, inject, computed, watch, onMounted } from 'vue'
|
||||
import BasicInfo from './basic-info.vue'
|
||||
import FillRepeat from './fill-repeat.vue'
|
||||
import ShapeSetting from './shape-setting.vue'
|
||||
const props = defineProps({})
|
||||
@@ -27,10 +28,11 @@
|
||||
const layers = computed(() => layerManager.layers.value)
|
||||
const activeObject = ref(null)
|
||||
|
||||
const shapes = ['rect', 'line', 'path', 'triangle', 'polygon', 'ellipse']
|
||||
const shapes = ['rect', 'path', 'triangle', 'polygon', 'ellipse']
|
||||
const isImage = computed(() => activeObject.value?.type === 'image')
|
||||
const isShape = computed(() => shapes.includes(activeObject.value?.type))
|
||||
const isRepeat = computed(() => activeObject.value?.fill?.repeat === 'repeat')
|
||||
const isShow = computed(() => isRepeat.value || isShape.value)
|
||||
const isShow = computed(() => isImage.value || isRepeat.value || isShape.value)
|
||||
|
||||
const updateActiveObject = () => {
|
||||
const layer = layerManager.getActiveLayer()
|
||||
@@ -87,6 +89,12 @@
|
||||
padding: 1.6rem;
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
> * {
|
||||
margin-bottom: 1.6rem;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
&:deep(> div) {
|
||||
> div {
|
||||
margin-bottom: var(--details-item-margin-bottom, 1.6rem);
|
||||
|
||||
@@ -1,74 +1,5 @@
|
||||
<template>
|
||||
<div class="shape-setting h">
|
||||
<div>
|
||||
<div class="title">Position</div>
|
||||
<div class="content">
|
||||
<div>
|
||||
<depth-input
|
||||
before="X"
|
||||
type="number"
|
||||
v-model="data.left"
|
||||
@input="onInpot"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<depth-input
|
||||
before="Y"
|
||||
type="number"
|
||||
v-model="data.top"
|
||||
@input="onInpot"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div>
|
||||
<depth-input
|
||||
before="W"
|
||||
type="number"
|
||||
v-model="data.width"
|
||||
@input="onInpot"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<depth-input
|
||||
before="H"
|
||||
type="number"
|
||||
v-model="data.height"
|
||||
@input="onInpot"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="title">Scale</div>
|
||||
<div class="content">
|
||||
<div>
|
||||
<depth-input
|
||||
type="number"
|
||||
before="X"
|
||||
after="%"
|
||||
v-model="data.scaleX"
|
||||
@input="onInpot"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<depth-input
|
||||
type="number"
|
||||
before="Y"
|
||||
after="%"
|
||||
v-model="data.scaleY"
|
||||
@input="onInpot"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="title">Appearance</div>
|
||||
<div class="content">
|
||||
@@ -96,12 +27,32 @@
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
<div v-else-if="object.type === 'path'">
|
||||
<span class="label">Stroke Width</span>
|
||||
<depth-input
|
||||
type="number"
|
||||
v-model="data.strokeWidth"
|
||||
min="0"
|
||||
step="1"
|
||||
@input="onInpot"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
<div v-else></div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div>
|
||||
<span class="label">Color</span>
|
||||
<depth-input
|
||||
v-if="object.type === 'path'"
|
||||
type="color"
|
||||
v-model="data.stroke"
|
||||
after="%"
|
||||
@input="onInpot"
|
||||
@change="onChange"
|
||||
/>
|
||||
<depth-input
|
||||
v-else
|
||||
type="color"
|
||||
v-model="data.fill"
|
||||
after="%"
|
||||
@@ -116,10 +67,6 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, inject, computed, nextTick, onBeforeUnmount, reactive, watch } from 'vue'
|
||||
import { ElColorPicker } from 'element-plus'
|
||||
import { getTransformScaleAngle } from '../../manager/ObjectManager'
|
||||
import DepthOffsetTool from '../tools/depth-offset-tool.vue'
|
||||
import DepthSlider from '../tools/depth-slider.vue'
|
||||
import DepthInput from '../tools/depth-input.vue'
|
||||
const objectManager = inject('objectManager') as any
|
||||
const stateManager = inject('stateManager') as any
|
||||
@@ -132,32 +79,20 @@
|
||||
const id = computed(() => props.object.info.id)
|
||||
|
||||
const data = reactive({
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
opacity: 100,
|
||||
radius: 0,
|
||||
|
||||
fill: ''
|
||||
// stroke: '',
|
||||
// strokeWidth: 0
|
||||
fill: '',
|
||||
stroke: '',
|
||||
strokeWidth: 0
|
||||
})
|
||||
const updateData = async () => {
|
||||
await nextTick()
|
||||
data.top = Math.round(props.object.top)
|
||||
data.left = Math.round(props.object.left)
|
||||
data.width = Math.round(props.object.width)
|
||||
data.height = Math.round(props.object.height)
|
||||
data.scaleX = Math.round(props.object.scaleX * 100)
|
||||
data.scaleY = Math.round(props.object.scaleY * 100)
|
||||
data.opacity = Math.round(props.object.opacity * 100)
|
||||
data.radius = Math.round(props.object.rx)
|
||||
data.fill = props.object.fill
|
||||
// data.stroke = props.object.stroke
|
||||
// data.strokeWidth = props.object.strokeWidth
|
||||
data.stroke = props.object.stroke
|
||||
data.strokeWidth = props.object.strokeWidth
|
||||
}
|
||||
updateData()
|
||||
watch(() => props.object, updateData)
|
||||
@@ -167,14 +102,16 @@
|
||||
const setPriority = (isRecord: boolean) => {
|
||||
const options = {
|
||||
...data,
|
||||
opacity: data.opacity / 100,
|
||||
scaleX: data.scaleX / 100,
|
||||
scaleY: data.scaleY / 100
|
||||
opacity: data.opacity / 100
|
||||
}
|
||||
if (props.object.type === 'rect') {
|
||||
options['rx'] = data.radius
|
||||
options['ry'] = data.radius
|
||||
}
|
||||
if (props.object.type !== 'path') {
|
||||
delete options.stroke
|
||||
delete options.strokeWidth
|
||||
}
|
||||
delete options.radius
|
||||
objectManager.updateProperty(id.value, options, isRecord)
|
||||
}
|
||||
|
||||
@@ -101,6 +101,10 @@ export class AISelectboxToolManager {
|
||||
this.canvasManager.canvas.remove(this.indicatorObject)
|
||||
this.indicatorObject = null
|
||||
}
|
||||
resetDemoObject() {
|
||||
this.clearDemoObject()
|
||||
this.createDemoObject()
|
||||
}
|
||||
// 创建临时画布对象
|
||||
async createStaticCanvas(object: fabric.Object) {
|
||||
if (!this.demoObject) this.createDemoObject()
|
||||
|
||||
@@ -3,7 +3,7 @@ import { fabric } from 'fabric-with-all'
|
||||
import { createId } from '../../tools/tools'
|
||||
import { exportObjectsToImage, exportObjectToThumbnail } from '../tools/exportMethod'
|
||||
import { OperationType, BlendMode } from '../tools/layerHelper'
|
||||
import { getArrowPath, cloneObjects, getStarArr } from '../tools/canvasMethod'
|
||||
import { getArrowPath, getLinePath, cloneObjects, getStarArr } from '../tools/canvasMethod'
|
||||
|
||||
export class LayerManager {
|
||||
stateManager: any
|
||||
@@ -274,25 +274,27 @@ export class LayerManager {
|
||||
}
|
||||
/** 创建直线图层 */
|
||||
async createLineLayer(options?: any, isRecord = true, isActive = true) {
|
||||
const line = [options?.x1 || 0, options?.y1 || 0, options?.x2 || 100, options?.y2 || 0]
|
||||
delete options.x1
|
||||
delete options.y1
|
||||
delete options.x2
|
||||
delete options.y2
|
||||
const lineObject = new fabric.Line(line, {
|
||||
stroke: 'black', // 线条颜色
|
||||
strokeWidth: 2, // 线条粗细
|
||||
const width = options?.width || 100
|
||||
const height = options?.height || 2
|
||||
delete options.width
|
||||
delete options.height
|
||||
const arrowObject = new fabric.Path(getLinePath(width, height), {
|
||||
stroke: '#000', // 只设置边框颜色
|
||||
strokeWidth: 2, // 边框宽度
|
||||
fill: 'transparent', // 不填充
|
||||
strokeLineCap: 'round',
|
||||
strokeLineJoin: 'round',
|
||||
...(options || {}),
|
||||
info: {
|
||||
id: createId("line"),
|
||||
name: '直线图层',
|
||||
...(options?.info || {}),
|
||||
}
|
||||
})
|
||||
this.setLayerPosition(lineObject, options)
|
||||
await this.canvasManager.add(lineObject, isRecord)
|
||||
if (isActive) this.setActiveID(lineObject.info.id)
|
||||
return lineObject
|
||||
});
|
||||
this.setLayerPosition(arrowObject, options)
|
||||
await this.canvasManager.add(arrowObject, isRecord)
|
||||
if (isActive) this.setActiveID(arrowObject.info.id)
|
||||
return arrowObject
|
||||
}
|
||||
/** 创建椭圆图层 */
|
||||
async createEllipseLayer(options?: any, isRecord = true, isActive = true) {
|
||||
@@ -353,18 +355,18 @@ export class LayerManager {
|
||||
/** 创建箭头图层 */
|
||||
async createArrowLayer(options?: any, isRecord = true, isActive = true) {
|
||||
const width = options?.width || 100
|
||||
const height = options?.height || 10
|
||||
const strokeWidth = options?.strokeWidth || 4
|
||||
delete options.width
|
||||
delete options.height
|
||||
const arrowObject = new fabric.Path(getArrowPath(width, height), {
|
||||
delete options.strokeWidth
|
||||
const arrowObject = new fabric.Path(getArrowPath(width, strokeWidth), {
|
||||
stroke: '#000', // 只设置边框颜色
|
||||
strokeWidth: 3, // 边框宽度
|
||||
strokeWidth, // 边框宽度
|
||||
fill: 'transparent', // 不填充
|
||||
strokeLineCap: 'round',
|
||||
strokeLineJoin: 'round',
|
||||
...(options || {}),
|
||||
info: {
|
||||
id: createId("star"),
|
||||
id: createId("arrow"),
|
||||
name: '箭头图层',
|
||||
...(options?.info || {}),
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { OperationType, OperationTypes } from "../tools/layerHelper";
|
||||
import { getStarArr, getArrowPath, distance, angleBetweenPointsDegrees } from "../tools/canvasMethod";
|
||||
import { getStarArr, getArrowPath, getLinePath, distance, angleBetweenPointsDegrees } from "../tools/canvasMethod";
|
||||
import { fabric } from 'fabric-with-all'
|
||||
/** 形状管理器 */
|
||||
export class ShapeToolManager {
|
||||
@@ -136,23 +136,48 @@ export class ShapeToolManager {
|
||||
|
||||
/** 绘制直线 */
|
||||
downLine() {
|
||||
const line = new fabric.Line([this.startX, this.startY, this.startX, this.startY], {
|
||||
stroke: 'black', // 线条颜色
|
||||
strokeWidth: 2 // 线条粗细
|
||||
})
|
||||
return line
|
||||
// const line = new fabric.Line([this.startX, this.startY, this.startX, this.startY], {
|
||||
// stroke: 'black', // 线条颜色
|
||||
// strokeWidth: 2 // 线条粗细
|
||||
// })
|
||||
// return line
|
||||
return new fabric.Path();
|
||||
}
|
||||
moveLine({ x, y }) {
|
||||
this.demoObject.set({
|
||||
x1: this.startX,
|
||||
y1: this.startY,
|
||||
x2: x,
|
||||
y2: y,
|
||||
})
|
||||
// this.demoObject.set({
|
||||
// x1: this.startX,
|
||||
// y1: this.startY,
|
||||
// x2: x,
|
||||
// y2: y,
|
||||
// })
|
||||
const width = distance(this.startX, this.startY, x, y)
|
||||
const angle = angleBetweenPointsDegrees(this.startX, this.startY, x, y)
|
||||
this.canvasManager.canvas.remove(this.demoObject)
|
||||
const arrow = new fabric.Path(getLinePath(width, 2), {
|
||||
left: this.startX,
|
||||
top: this.startY,
|
||||
stroke: '#000', // 只设置边框颜色
|
||||
strokeWidth: 2, // 边框宽度
|
||||
fill: 'transparent', // 不填充
|
||||
strokeLineCap: 'round',
|
||||
strokeLineJoin: 'round',
|
||||
originY: 'center',
|
||||
angle: angle,
|
||||
});
|
||||
this.canvasManager.canvas.add(arrow)
|
||||
this.demoObject = arrow
|
||||
}
|
||||
upLine(object) {
|
||||
if (object.originY !== "center") {
|
||||
this.layerManager.createLineLayer({
|
||||
left: this.startX,
|
||||
top: this.startY,
|
||||
})
|
||||
} else {
|
||||
this.layerManager.createLineLayer(object)
|
||||
}
|
||||
// this.layerManager.createLineLayer(object)
|
||||
}
|
||||
|
||||
/** 绘制椭圆 */
|
||||
downEllipse() {
|
||||
@@ -228,11 +253,11 @@ export class ShapeToolManager {
|
||||
const width = distance(this.startX, this.startY, x, y)
|
||||
const angle = angleBetweenPointsDegrees(this.startX, this.startY, x, y)
|
||||
this.canvasManager.canvas.remove(this.demoObject)
|
||||
const arrow = new fabric.Path(getArrowPath(width, 10), {
|
||||
const arrow = new fabric.Path(getArrowPath(width, 4), {
|
||||
left: this.startX,
|
||||
top: this.startY,
|
||||
stroke: '#000', // 只设置边框颜色
|
||||
strokeWidth: 3, // 边框宽度
|
||||
strokeWidth: 4, // 边框宽度
|
||||
fill: 'transparent', // 不填充
|
||||
strokeLineCap: 'round',
|
||||
strokeLineJoin: 'round',
|
||||
@@ -247,7 +272,7 @@ export class ShapeToolManager {
|
||||
this.layerManager.createArrowLayer({
|
||||
left: this.startX,
|
||||
top: this.startY,
|
||||
}, true)
|
||||
})
|
||||
} else {
|
||||
this.layerManager.createArrowLayer(object)
|
||||
}
|
||||
|
||||
@@ -73,7 +73,6 @@ export class StateManager {
|
||||
/** 记录状态 */
|
||||
recordState() {
|
||||
if (this.running.value) return
|
||||
console.log("recordState")
|
||||
this.running.value = true
|
||||
if (this.historyIndex.value < this.historyList.value.length - 1) {
|
||||
this.historyList.value.splice(this.historyIndex.value + 1)
|
||||
|
||||
@@ -61,13 +61,26 @@ export function getStarArr(width = 0, height = 0) {
|
||||
}))
|
||||
}
|
||||
/** 获取箭头路径 */
|
||||
export function getArrowPath(width = 0, height = 0) {
|
||||
export function getArrowPath(width = 0, strokeWidth = 4) {
|
||||
const height = strokeWidth * 4
|
||||
const arr = [
|
||||
["M", 0, height / 2],
|
||||
["L", width, height / 2],
|
||||
["M", width - 8, 0],
|
||||
["M", width - height, 0],
|
||||
["L", width, height / 2],
|
||||
["L", width - height, height],
|
||||
]
|
||||
var path = ""
|
||||
arr.forEach(item => {
|
||||
path += item.join(" ") + " "
|
||||
})
|
||||
return path
|
||||
}
|
||||
/** 获取直线路径 */
|
||||
export function getLinePath(width = 0, height = 0) {
|
||||
const arr = [
|
||||
["M", 0, height / 2],
|
||||
["L", width, height / 2],
|
||||
["L", width - 8, height],
|
||||
]
|
||||
var path = ""
|
||||
arr.forEach(item => {
|
||||
|
||||
Reference in New Issue
Block a user