diff --git a/src/components/webtopo-svgedit/components/center-panel/index.vue b/src/components/webtopo-svgedit/components/center-panel/index.vue index 3337da2..fbb802b 100644 --- a/src/components/webtopo-svgedit/components/center-panel/index.vue +++ b/src/components/webtopo-svgedit/components/center-panel/index.vue @@ -39,10 +39,17 @@ @mouseenter="onSvgMouseEnter(item, index, $event)" @mouseleave="onSvgMouseLeave(item, index, $event)" > + - @@ -136,13 +145,7 @@ IDoneJson } from '@/store/global/types'; import { useSvgEditLayoutStore } from '@/store/svgedit-layout'; - import { - getCenterPoint, - randomString, - positionArrarToPath, - getSvgNowPosition, - setSvgActualInfo - } from '@/utils'; + import { getCenterPoint, randomString, getSvgNowPosition, setSvgActualInfo } from '@/utils'; import { calculateBottom, calculateLeft, @@ -156,6 +159,8 @@ import HandlePanel from '@/components/webtopo-svgedit/components/handle-panel/index.vue'; import ConnectionPanel from '@/components/webtopo-svgedit/components/connection-panel/index.vue'; import { EDoneJsonType } from '@/config-center/types'; + import ConnectionLine from '@/components/webtopo-svgedit/components/connection-line/index.vue'; + import { IVisiableInfo } from './types'; // import HandlePanel from '../handle-panel/index.vue'; const globalStore = useGlobalStore(); const configStore = useConfigStore(); @@ -167,14 +172,19 @@ ? "url('/src/assets/icons/rotate.svg') 12 12, auto" : 'default' ); - const visiable_info = reactive({ + const visiable_info: IVisiableInfo = reactive({ handle_panel: computed( () => globalStore.intention === EGlobalStoreIntention.Select || globalStore.intention === EGlobalStoreIntention.Zoom || globalStore.intention === EGlobalStoreIntention.Rotate ), - connection_panel: false + connection_panel: false, + connection_line: false, + select_item: { + info: null, + index: -1 + } }); const dropEvent = (e: DragEvent) => { if (globalStore.intention == EGlobalStoreIntention.None) { @@ -251,12 +261,12 @@ e.preventDefault(); }; const onSvgMouseDown = (select_item: IDoneJson, index: number, e: MouseEvent) => { - console.log(172, e); + console.log('触发选中', e); if (globalStore.intention === EGlobalStoreIntention.Connection) { return; } e.preventDefault(); - e.cancelBubble = true; + e.stopPropagation(); //鼠标在画布上的组件按下记录选中的组件信息和鼠标位置信息等 globalStore.intention = EGlobalStoreIntention.Select; globalStore.setHandleSvgInfo(select_item, index); @@ -272,13 +282,33 @@ }; const onSvgMouseEnter = (select_item: IDoneJson, index: number, e: MouseEvent) => { e.preventDefault(); - e.cancelBubble = true; + e.stopPropagation(); visiable_info.connection_panel = true; + visiable_info.connection_line = true; + if ( + (globalStore.intention === EGlobalStoreIntention.Connection || + globalStore.intention === EGlobalStoreIntention.SetConnectionLineNode) && + select_item.type === EDoneJsonType.ConnectionLine + ) { + return; + } + visiable_info.select_item.info = select_item; + visiable_info.select_item.index = index; }; const onSvgMouseLeave = (select_item: IDoneJson, index: number, e: MouseEvent) => { e.preventDefault(); - e.cancelBubble = true; + e.stopPropagation(); + if ( + (globalStore.intention === EGlobalStoreIntention.Connection || + globalStore.intention === EGlobalStoreIntention.SetConnectionLineNode) && + select_item.type === EDoneJsonType.ConnectionLine + ) { + return; + } visiable_info.connection_panel = false; + visiable_info.connection_line = false; + visiable_info.select_item.info = null; + visiable_info.select_item.index = -1; }; const onCanvasMouseMove = (e: MouseEvent) => { //如果鼠标不是按下状态 连线除外 @@ -471,6 +501,24 @@ ) }; // console.log('连线', start_x, start_y, end_x, end_y, clientX, clientY); + } else if ( + globalStore.intention === EGlobalStoreIntention.SetConnectionLineNode && + globalStore.handle_svg_info + ) { + globalStore.handle_svg_info.info.props.point_position.val[ + globalStore.connection_line_node_info.point_index + ] = { + x: getSvgNowPosition( + globalStore.mouse_info.position_x, + clientX, + globalStore.connection_line_node_info.init_pos.x + ), + y: getSvgNowPosition( + globalStore.mouse_info.position_y, + clientY, + globalStore.connection_line_node_info.init_pos.y + ) + }; } }; const onCanvasMouseUp = (e: MouseEvent) => { diff --git a/src/components/webtopo-svgedit/components/center-panel/types.ts b/src/components/webtopo-svgedit/components/center-panel/types.ts new file mode 100644 index 0000000..f09f52a --- /dev/null +++ b/src/components/webtopo-svgedit/components/center-panel/types.ts @@ -0,0 +1,11 @@ +import { IDoneJson } from '@/store/global/types'; + +export interface IVisiableInfo { + handle_panel: boolean; + connection_panel: boolean; + connection_line: boolean; + select_item: { + info: null | IDoneJson; + index: number; + }; +} diff --git a/src/components/webtopo-svgedit/components/connection-line/index.vue b/src/components/webtopo-svgedit/components/connection-line/index.vue new file mode 100644 index 0000000..d93b775 --- /dev/null +++ b/src/components/webtopo-svgedit/components/connection-line/index.vue @@ -0,0 +1,127 @@ + + + diff --git a/src/components/webtopo-svgedit/components/connection-panel/index.vue b/src/components/webtopo-svgedit/components/connection-panel/index.vue index 4089f9b..030eece 100644 --- a/src/components/webtopo-svgedit/components/connection-panel/index.vue +++ b/src/components/webtopo-svgedit/components/connection-panel/index.vue @@ -10,7 +10,7 @@ stroke="rgba(0,0,0,0)" stroke-width="2" :fill="fill" - :style="{ 'vector-effect': 'non-scaling-stroke'}" + :style="{ 'vector-effect': 'non-scaling-stroke','cursor': 'pointer'}" pointer-events="all" @mousedown="onConnectionMouseDown(ELineBindAnchors.TopCenter,$event)"/> @@ -148,19 +148,10 @@ }, ...create_line_info }; - done_item_json.props.point_position.val.push( - { - x: configStore.svg.svg_position_center.x, - y: configStore.svg.svg_position_center.y - }, - //push一个用来实时显示鼠标移动的 - { - x: configStore.svg.svg_position_center.x, - y: configStore.svg.svg_position_center.y - } - ); - - done_item_json.props.point_position.val.push(); + done_item_json.props.point_position.val.push({ + x: configStore.svg.svg_position_center.x, + y: configStore.svg.svg_position_center.y + }); globalStore.setHandleSvgInfo(done_item_json, globalStore.done_json.length); globalStore.setDoneJson(done_item_json); diff --git a/src/components/webtopo-svgedit/components/handle-panel/index.vue b/src/components/webtopo-svgedit/components/handle-panel/index.vue index bd4871f..1ace811 100644 --- a/src/components/webtopo-svgedit/components/handle-panel/index.vue +++ b/src/components/webtopo-svgedit/components/handle-panel/index.vue @@ -144,7 +144,7 @@ const onHandleMouseDown = (type: EScaleInfoType, e: MouseEvent) => { console.log('onHandleMouseDown', e); const { clientX, clientY } = e; - e.cancelBubble = true; + e.stopPropagation(); globalStore.intention = EGlobalStoreIntention.Zoom; globalStore.setMouseInfo({ state: EMouseInfoState.Down, @@ -178,7 +178,7 @@ }; const onRotateCircleMouseDown = (e: MouseEvent) => { const { clientX, clientY } = e; - e.cancelBubble = true; + e.stopPropagation(); globalStore.intention = EGlobalStoreIntention.Rotate; globalStore.rotate_info = { angle: props.itemInfo.rotate diff --git a/src/components/webtopo-svgedit/components/right-panel/dynamic-el-form-item.vue b/src/components/webtopo-svgedit/components/right-panel/dynamic-el-form-item.vue new file mode 100644 index 0000000..05b2b85 --- /dev/null +++ b/src/components/webtopo-svgedit/components/right-panel/dynamic-el-form-item.vue @@ -0,0 +1,62 @@ + + diff --git a/src/components/webtopo-svgedit/components/right-panel/index.vue b/src/components/webtopo-svgedit/components/right-panel/index.vue index 02c4468..5c006ba 100644 --- a/src/components/webtopo-svgedit/components/right-panel/index.vue +++ b/src/components/webtopo-svgedit/components/right-panel/index.vue @@ -42,9 +42,22 @@ + + + + + + - @@ -63,14 +76,14 @@ ElInput } from 'element-plus'; import { ref } from 'vue'; - import { useConfigStore } from '../../../../store/config'; - import { useGlobalStore } from '../../../../store/global'; - import { EGlobalStoreIntention } from '../../../../store/global/types'; + import { useConfigStore } from '@/store/config'; + import { useGlobalStore } from '@/store/global'; + import { EGlobalStoreIntention } from '@/store/global/types'; + import DynamicElFormItem from './dynamic-el-form-item.vue'; const configStore = useConfigStore(); const globalStore = useGlobalStore(); const activeName = ref('style'); - const handleClick = (tab: TabsPaneContext, event: Event) => { console.log(tab, event); }; diff --git a/src/config-center/svg-file/stateful/circuit-breaker/index.ts b/src/config-center/svg-file/stateful/circuit-breaker/index.ts index a82e04c..12a27dc 100644 --- a/src/config-center/svg-file/stateful/circuit-breaker/index.ts +++ b/src/config-center/svg-file/stateful/circuit-breaker/index.ts @@ -6,12 +6,13 @@ export const circuit_breaker_svg_file: IConfigItem = { type: EDoneJsonType.File, config: { can_zoom: true, - have_anchor: true + have_anchor: true, + actual_rect: true }, props: { fill: { - title: '填充色', - type: EConfigItemPropsType.Switch, + title: '开关', + type: EConfigItemPropsType.Select, val: '#ff0000', options: [ { diff --git a/src/config-center/svg-file/stateless/alternator/index.ts b/src/config-center/svg-file/stateless/alternator/index.ts index e23b8b1..e9a92a1 100644 --- a/src/config-center/svg-file/stateless/alternator/index.ts +++ b/src/config-center/svg-file/stateless/alternator/index.ts @@ -6,7 +6,8 @@ export const alternator_svg_file: IConfigItem = { type: EDoneJsonType.File, config: { can_zoom: true, - have_anchor: true + have_anchor: true, + actual_rect: true }, props: { fill: { diff --git a/src/config-center/svg-file/stateless/traction-transformer/index.ts b/src/config-center/svg-file/stateless/traction-transformer/index.ts index bd3cba0..3958f35 100644 --- a/src/config-center/svg-file/stateless/traction-transformer/index.ts +++ b/src/config-center/svg-file/stateless/traction-transformer/index.ts @@ -6,7 +6,8 @@ export const traction_transformer_svg_file: IConfigItem = { type: EDoneJsonType.File, config: { can_zoom: true, - have_anchor: true + have_anchor: true, + actual_rect: true }, props: { fill: { diff --git a/src/config-center/svg-file/system/index.ts b/src/config-center/svg-file/system/index.ts index f0e8d69..7291fb7 100644 --- a/src/config-center/svg-file/system/index.ts +++ b/src/config-center/svg-file/system/index.ts @@ -1,4 +1,4 @@ -import { EConfigItemPropsType, EDoneJsonType } from '@/config-center/types'; +import { EConfigAnimationsType, EConfigItemPropsType, EDoneJsonType } from '@/config-center/types'; import type { ISystemStraightLine } from './types'; export const straight_line_system: ISystemStraightLine = Object.seal({ @@ -7,7 +7,8 @@ export const straight_line_system: ISystemStraightLine = Object.seal({ type: EDoneJsonType.StraightLine, config: { can_zoom: false, - have_anchor: false + have_anchor: false, + actual_rect: false }, props: { fill: { @@ -47,11 +48,12 @@ export const connection_line_system: ISystemStraightLine = Object.freeze({ type: EDoneJsonType.ConnectionLine, config: { can_zoom: false, - have_anchor: false + have_anchor: false, + actual_rect: false }, props: { - fill: { - title: '填充色', + stroke: { + title: '线条颜色', type: EConfigItemPropsType.Color, val: '#ff0000' }, @@ -61,6 +63,40 @@ export const connection_line_system: ISystemStraightLine = Object.freeze({ val: [] } }, + animations: { + type: { + title: '动画类型', + type: EConfigItemPropsType.Select, + val: EConfigAnimationsType.None, + options: [ + { + label: '无', + value: EConfigAnimationsType.None + }, + { + label: '电流', + value: EConfigAnimationsType.Electricity + }, + { + label: '轨迹', + value: EConfigAnimationsType.Track + }, + { + label: '水珠', + value: EConfigAnimationsType.WaterDrop + } + ] + }, + dur: { title: '持续时间', type: EConfigItemPropsType.InputNumber, val: 20 }, + repeatCount: { + title: '循环次数', + type: EConfigItemPropsType.Input, + val: 'indefinite', + disabled: true + }, + color: { title: '颜色', type: EConfigItemPropsType.Color, val: '#0a7ae2' }, + reverse: { title: '反转动画', type: EConfigItemPropsType.Switch, val: false } + }, bind_anchors: { start: null, end: null diff --git a/src/config-center/types.ts b/src/config-center/types.ts index 02057f8..66659f2 100644 --- a/src/config-center/types.ts +++ b/src/config-center/types.ts @@ -21,6 +21,7 @@ export interface IConfigItem { props: IConfigItemProps; type: EDoneJsonType; config: IDoneJsonConfig; + animations?: IConfigItemProps; } export interface IConfigItemProps { [key: string]: { @@ -28,14 +29,23 @@ export interface IConfigItemProps { type: EConfigItemPropsType; val: any; options?: { value: any; label: string }[]; + disabled?: boolean; }; } + +export enum EConfigAnimationsType { + None = 'None', + Electricity = 'Electricity', //电流效果 + WaterDrop = 'WaterDrop', //水珠 + Track = 'Track' //轨迹 +} export enum EConfigItemPropsType { Input = 'Input', Color = 'Color', InputNumber = 'InputNumber', Switch = 'Switch', //此类型option默认索引0为关闭 - JsonEdit = 'JsonEdit' + JsonEdit = 'JsonEdit', + Select = 'Select' } export enum EDoneJsonType { File = 'File', @@ -45,4 +55,5 @@ export enum EDoneJsonType { interface IDoneJsonConfig { can_zoom: boolean; have_anchor: boolean; + actual_rect: boolean; } diff --git a/src/store/global/index.ts b/src/store/global/index.ts index 6798e07..ab72fdb 100644 --- a/src/store/global/index.ts +++ b/src/store/global/index.ts @@ -49,6 +49,13 @@ export const useGlobalStore = defineStore('global-store', { }, rotate_info: { angle: 0 + }, + connection_line_node_info: { + init_pos: { + x: 0, + y: 0 + }, + point_index: 0 } }; }, @@ -72,11 +79,16 @@ export const useGlobalStore = defineStore('global-store', { setMouseInfo(mouse_info: IMouseInfo) { this.mouse_info = mouse_info; }, - setHandleSvgInfo(info: IDoneJson | null, index: number) { + setHandleSvgInfo(info: IDoneJson | null, index?: number) { + let current_index = index; if (info) { + if (!current_index && current_index != 0) { + //如果索引没传 在这根据id查出索引 + current_index = this.done_json.findIndex((f) => f.id === info.id) ?? -1; + } this.handle_svg_info = { info: info, - index: index + index: current_index }; } else { this.handle_svg_info = info; diff --git a/src/store/global/types.ts b/src/store/global/types.ts index db875db..e309fc0 100644 --- a/src/store/global/types.ts +++ b/src/store/global/types.ts @@ -9,6 +9,7 @@ export interface IGlobalStore { handle_svg_info: IHandleSvgInfo | null; scale_info: IScaleInfo; rotate_info: IRotateInfo; + connection_line_node_info: IConnectionLineNodeInfo; } export interface IDoneJson extends IConfigItem { id: string; @@ -43,7 +44,8 @@ export enum EGlobalStoreIntention { Select = 'Select', Zoom = 'Zoom', Rotate = 'Rotate', - Connection = 'Connection' + Connection = 'Connection', + SetConnectionLineNode = 'SetConnectionLineNode' } export interface IMouseInfo { state: EMouseInfoState; @@ -103,3 +105,10 @@ export interface ICoordinate { x: number; y: number; } +export interface IConnectionLineNodeInfo { + init_pos: { + x: number; + y: number; + }; + point_index: number; +}