重构虚拟窗口移动,调整大小逻辑
This commit is contained in:
parent
bfc271db2d
commit
e1b1ec4ee7
12
package.json
12
package.json
|
@ -14,20 +14,20 @@
|
||||||
"@types/element-resize-detector": "^1.1.3",
|
"@types/element-resize-detector": "^1.1.3",
|
||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.2",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.21.0",
|
||||||
"element-resize-detector": "^1.2.3",
|
"element-resize-detector": "^1.2.4",
|
||||||
"quasar": "^2.5.4",
|
"quasar": "^2.5.5",
|
||||||
"reconnecting-websocket": "^4.4.0",
|
"reconnecting-websocket": "^4.4.0",
|
||||||
"v-viewer": "^3.0.9",
|
"v-viewer": "^3.0.9",
|
||||||
"vue": "^3.0.0",
|
"vue": "^3.0.0",
|
||||||
"vue-i18n": "^9.0.0-beta.0",
|
"vue-i18n": "^9.1.9",
|
||||||
"vue-router": "^4.0.0",
|
"vue-router": "^4.0.0",
|
||||||
"vuex": "^4.0.1"
|
"vuex": "^4.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@quasar/app": "^3.3.2",
|
"@quasar/app": "^3.3.3",
|
||||||
"@types/node": "^10.17.15",
|
"@types/node": "^10.17.15",
|
||||||
"workbox-webpack-plugin": "^6.0.0"
|
"workbox-webpack-plugin": "^6.4.2"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"last 10 Chrome versions",
|
"last 10 Chrome versions",
|
||||||
|
|
|
@ -493,6 +493,26 @@ export default class ClientConnection {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setWindowGeometry(
|
||||||
|
window_id: number,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
) {
|
||||||
|
this.ws?.send(
|
||||||
|
JSON.stringify(
|
||||||
|
new Protocol.SetWindowGeometryRequestEntity(
|
||||||
|
window_id,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public closeWindow(window_id: number) {
|
public closeWindow(window_id: number) {
|
||||||
this.ws?.send(
|
this.ws?.send(
|
||||||
JSON.stringify(new Protocol.CloseWindowRequestEntity(window_id))
|
JSON.stringify(new Protocol.CloseWindowRequestEntity(window_id))
|
||||||
|
|
|
@ -18,7 +18,6 @@ export default class EventBus extends EventEmitter {
|
||||||
|
|
||||||
export namespace EventNamesDefine {
|
export namespace EventNamesDefine {
|
||||||
export const UnKnow = "onUnKnow";
|
export const UnKnow = "onUnKnow";
|
||||||
export const UnSelectAllWindows = "onUnSelectAllWindows";
|
|
||||||
export const WindowResize = "onWindowResize";
|
export const WindowResize = "onWindowResize";
|
||||||
export const WindowMouseDown = "onWindowMouseDown";
|
export const WindowMouseDown = "onWindowMouseDown";
|
||||||
export const WindowMouseMove = "onWindowMouseMove";
|
export const WindowMouseMove = "onWindowMouseMove";
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="window_class window_flag"
|
class="window_class window_flag"
|
||||||
:class="selected ? 'window_selected' : 'window_normal'"
|
:class="
|
||||||
|
$props.window.uuid == $store.state.selected_window
|
||||||
|
? 'window_selected'
|
||||||
|
: 'window_normal'
|
||||||
|
"
|
||||||
@click="onClick"
|
@click="onClick"
|
||||||
@mousedown="onMouseDown"
|
|
||||||
@mousemove="onMouseMove"
|
|
||||||
@mouseleave="onMouseLeave"
|
|
||||||
@mouseup="onMouseUp"
|
|
||||||
:style="{
|
:style="{
|
||||||
background: $props.window.client_color,
|
background: $props.window.client_color,
|
||||||
}"
|
}"
|
||||||
|
@ -154,87 +154,6 @@
|
||||||
}}</q-tooltip>
|
}}</q-tooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="!$props.disable && selected && can_resize"
|
|
||||||
class="resize_div absolute_up"
|
|
||||||
ref="resize_up"
|
|
||||||
@mousedown="onMouseDown"
|
|
||||||
@mousemove="(evt) => onResizeMouseMove(evt, flags.up_flag)"
|
|
||||||
@mouseleave="onMouseLeave"
|
|
||||||
@mouseup="onMouseLeave"
|
|
||||||
></div>
|
|
||||||
<div
|
|
||||||
v-if="!$props.disable && selected && can_resize"
|
|
||||||
class="resize_div absolute_down"
|
|
||||||
ref="resize_down"
|
|
||||||
@mousedown="onMouseDown"
|
|
||||||
@mousemove="(evt) => onResizeMouseMove(evt, flags.down_flag)"
|
|
||||||
@mouseleave="onMouseLeave"
|
|
||||||
@mouseup="onMouseLeave"
|
|
||||||
></div>
|
|
||||||
<div
|
|
||||||
v-if="!$props.disable && selected && can_resize"
|
|
||||||
class="resize_div absolute_left"
|
|
||||||
ref="resize_left"
|
|
||||||
@mousedown="onMouseDown"
|
|
||||||
@mousemove="(evt) => onResizeMouseMove(evt, flags.left_flag)"
|
|
||||||
@mouseleave="onMouseLeave"
|
|
||||||
@mouseup="onMouseLeave"
|
|
||||||
></div>
|
|
||||||
<div
|
|
||||||
v-if="!$props.disable && selected && can_resize"
|
|
||||||
class="resize_div absolute_right"
|
|
||||||
ref="resize_right"
|
|
||||||
@mousedown="onMouseDown"
|
|
||||||
@mousemove="(evt) => onResizeMouseMove(evt, flags.right_flag)"
|
|
||||||
@mouseleave="onMouseLeave"
|
|
||||||
@mouseup="onMouseLeave"
|
|
||||||
></div>
|
|
||||||
<div
|
|
||||||
v-if="!$props.disable && selected && can_resize"
|
|
||||||
class="resize_div absolute_left_up"
|
|
||||||
ref="resize_left_up"
|
|
||||||
@mousedown="onMouseDown"
|
|
||||||
@mousemove="
|
|
||||||
(evt) => onResizeMouseMove(evt, flags.up_flag | flags.left_flag)
|
|
||||||
"
|
|
||||||
@mouseleave="onMouseLeave"
|
|
||||||
@mouseup="onMouseLeave"
|
|
||||||
></div>
|
|
||||||
<div
|
|
||||||
v-if="!$props.disable && selected && can_resize"
|
|
||||||
class="resize_div absolute_right_up"
|
|
||||||
ref="resize_right_up"
|
|
||||||
@mousedown="onMouseDown"
|
|
||||||
@mousemove="
|
|
||||||
(evt) => onResizeMouseMove(evt, flags.up_flag | flags.right_flag)
|
|
||||||
"
|
|
||||||
@mouseleave="onMouseLeave"
|
|
||||||
@mouseup="onMouseLeave"
|
|
||||||
></div>
|
|
||||||
<div
|
|
||||||
v-if="!$props.disable && selected && can_resize"
|
|
||||||
class="resize_div absolute_left_down"
|
|
||||||
ref="resize_left_down"
|
|
||||||
@mousedown="onMouseDown"
|
|
||||||
@mousemove="
|
|
||||||
(evt) => onResizeMouseMove(evt, flags.down_flag | flags.left_flag)
|
|
||||||
"
|
|
||||||
@mouseleave="onMouseLeave"
|
|
||||||
@mouseup="onMouseLeave"
|
|
||||||
></div>
|
|
||||||
<div
|
|
||||||
v-if="!$props.disable && selected && can_resize"
|
|
||||||
class="resize_div absolute_right_down"
|
|
||||||
ref="resize_right_down"
|
|
||||||
@mousedown="onMouseDown"
|
|
||||||
@mousemove="
|
|
||||||
(evt) => onResizeMouseMove(evt, flags.down_flag | flags.right_flag)
|
|
||||||
"
|
|
||||||
@mouseleave="onMouseLeave"
|
|
||||||
@mouseup="onMouseLeave"
|
|
||||||
></div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -261,81 +180,6 @@
|
||||||
.top {
|
.top {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.resize_div {
|
|
||||||
background: gray;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
z-index: 999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.absolute_up {
|
|
||||||
position: absolute;
|
|
||||||
top: -16px;
|
|
||||||
left: calc(50% - 16px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.absolute_down {
|
|
||||||
position: absolute;
|
|
||||||
bottom: -16px;
|
|
||||||
left: calc(50% - 16px);
|
|
||||||
}
|
|
||||||
|
|
||||||
div.absolute_up,
|
|
||||||
div.absolute_down {
|
|
||||||
cursor: s-resize;
|
|
||||||
}
|
|
||||||
|
|
||||||
.absolute_left {
|
|
||||||
position: absolute;
|
|
||||||
top: calc(50% - 16px);
|
|
||||||
left: -16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.absolute_right {
|
|
||||||
position: absolute;
|
|
||||||
top: calc(50% - 16px);
|
|
||||||
right: -16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.absolute_left,
|
|
||||||
div.absolute_right {
|
|
||||||
cursor: w-resize;
|
|
||||||
}
|
|
||||||
|
|
||||||
.absolute_left_up {
|
|
||||||
position: absolute;
|
|
||||||
top: -16px;
|
|
||||||
left: -16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.absolute_left_down {
|
|
||||||
position: absolute;
|
|
||||||
bottom: -16px;
|
|
||||||
left: -16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.absolute_right_up {
|
|
||||||
position: absolute;
|
|
||||||
top: -16px;
|
|
||||||
right: -16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.absolute_right_down {
|
|
||||||
position: absolute;
|
|
||||||
bottom: -16px;
|
|
||||||
right: -16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.absolute_left_up,
|
|
||||||
div.absolute_right_down {
|
|
||||||
cursor: se-resize;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.absolute_right_up,
|
|
||||||
div.absolute_left_down {
|
|
||||||
cursor: ne-resize;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
@ -382,8 +226,6 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
emits: [
|
emits: [
|
||||||
"reset_geometry_offset",
|
|
||||||
"commit_geometry",
|
|
||||||
"close_this_window",
|
"close_this_window",
|
||||||
"close_other_windows",
|
"close_other_windows",
|
||||||
"close_all_windows",
|
"close_all_windows",
|
||||||
|
@ -423,56 +265,13 @@ export default defineComponent({
|
||||||
return signal_source.value.window_type == "EwindowType::Clock";
|
return signal_source.value.window_type == "EwindowType::Clock";
|
||||||
});
|
});
|
||||||
|
|
||||||
let selected = ref(false);
|
|
||||||
let can_move = ref(true);
|
|
||||||
let can_resize = ref(true);
|
|
||||||
let move_flag = false;
|
|
||||||
|
|
||||||
const onUnSelectAllWindows = () => {
|
|
||||||
selected.value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
EventBus.getInstance().on(
|
|
||||||
EventNamesDefine.UnSelectAllWindows,
|
|
||||||
onUnSelectAllWindows
|
|
||||||
);
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
EventBus.getInstance().removeListener(
|
|
||||||
EventNamesDefine.UnSelectAllWindows,
|
|
||||||
onUnSelectAllWindows
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
let mouse_down_flag = false;
|
|
||||||
let mouse_last_pos_x = 0;
|
|
||||||
let mouse_last_pos_y = 0;
|
|
||||||
|
|
||||||
const cleanMouseDownFlag = () => {
|
|
||||||
mouse_down_flag = false;
|
|
||||||
mouse_last_pos_x = 0;
|
|
||||||
mouse_last_pos_y = 0;
|
|
||||||
move_flag = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
reload_signal_source();
|
reload_signal_source();
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.window,
|
|
||||||
(a, b) => {
|
|
||||||
reload_signal_source();
|
|
||||||
selected.value = false;
|
|
||||||
cleanMouseDownFlag();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const flags = new _Flags();
|
const flags = new _Flags();
|
||||||
let ctrl_press_flag = false;
|
let ctrl_press_flag = false;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
signal_source,
|
signal_source,
|
||||||
selected,
|
|
||||||
can_move,
|
|
||||||
can_resize,
|
|
||||||
flags,
|
flags,
|
||||||
is_audo_player_window,
|
is_audo_player_window,
|
||||||
is_clock_window,
|
is_clock_window,
|
||||||
|
@ -485,112 +284,7 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
if (!props.mouse_area_flag) {
|
if (!props.mouse_area_flag) {
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
if (selected.value != true) {
|
$store.commit("setSelectedWindow", props.window.uuid);
|
||||||
EventBus.getInstance().emit(EventNamesDefine.UnSelectAllWindows);
|
|
||||||
selected.value = true;
|
|
||||||
$store.commit("setSelectedWindow", props.window.uuid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onMouseDown(evt: MouseEvent) {
|
|
||||||
ctrl_press_flag = evt.ctrlKey;
|
|
||||||
if (!evt.ctrlKey) {
|
|
||||||
evt.stopPropagation();
|
|
||||||
|
|
||||||
if (props.disable) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (selected.value) {
|
|
||||||
if (evt.button == 0) {
|
|
||||||
mouse_down_flag = true;
|
|
||||||
mouse_last_pos_x = evt.x;
|
|
||||||
mouse_last_pos_y = evt.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// console.log("down", ctrl_flag);
|
|
||||||
},
|
|
||||||
onMouseMove(evt: MouseEvent) {
|
|
||||||
if (!props.mouse_area_flag) {
|
|
||||||
evt.stopPropagation();
|
|
||||||
if (can_move.value && mouse_down_flag && selected.value) {
|
|
||||||
emit(
|
|
||||||
"reset_geometry_offset",
|
|
||||||
props.window,
|
|
||||||
evt.x - mouse_last_pos_x,
|
|
||||||
evt.y - mouse_last_pos_y,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
mouse_last_pos_x = evt.x;
|
|
||||||
mouse_last_pos_y = evt.y;
|
|
||||||
move_flag = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onResizeMouseDown(evt: MouseEvent) {},
|
|
||||||
|
|
||||||
onResizeMouseMove(evt: MouseEvent, dir: number) {
|
|
||||||
if (can_resize.value && mouse_down_flag && selected.value) {
|
|
||||||
const h = evt.x - mouse_last_pos_x;
|
|
||||||
const v = evt.y - mouse_last_pos_y;
|
|
||||||
let x_offset = 0;
|
|
||||||
let y_offset = 0;
|
|
||||||
let width_offset = 0;
|
|
||||||
let height_offset = 0;
|
|
||||||
if (dir & flags.up_flag) {
|
|
||||||
y_offset += v;
|
|
||||||
height_offset -= v;
|
|
||||||
}
|
|
||||||
if (dir & flags.down_flag) {
|
|
||||||
height_offset += v;
|
|
||||||
}
|
|
||||||
if (dir & flags.left_flag) {
|
|
||||||
x_offset += h;
|
|
||||||
width_offset -= h;
|
|
||||||
}
|
|
||||||
if (dir & flags.right_flag) {
|
|
||||||
width_offset += h;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit(
|
|
||||||
"reset_geometry_offset",
|
|
||||||
props.window,
|
|
||||||
x_offset,
|
|
||||||
y_offset,
|
|
||||||
width_offset,
|
|
||||||
height_offset
|
|
||||||
);
|
|
||||||
|
|
||||||
mouse_last_pos_x = evt.x;
|
|
||||||
mouse_last_pos_y = evt.y;
|
|
||||||
move_flag = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
cleanMouseDownFlag,
|
|
||||||
onMouseLeave(evt: MouseEvent) {
|
|
||||||
ctrl_press_flag = false;
|
|
||||||
if (!props.mouse_area_flag) {
|
|
||||||
if (selected.value && mouse_down_flag) {
|
|
||||||
if (move_flag) {
|
|
||||||
emit("commit_geometry", props.window);
|
|
||||||
}
|
|
||||||
cleanMouseDownFlag();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onMouseUp(evt: MouseEvent) {
|
|
||||||
// console.log("up", ctrl_flag);
|
|
||||||
|
|
||||||
if (selected.value && mouse_down_flag) {
|
|
||||||
if (move_flag) {
|
|
||||||
emit("commit_geometry", props.window);
|
|
||||||
}
|
|
||||||
cleanMouseDownFlag();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,9 @@ export namespace Protocol {
|
||||||
return Commands.PROTOCOL_PREFIX + "ResizeWindow";
|
return Commands.PROTOCOL_PREFIX + "ResizeWindow";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static get kSetWindowGeometry() {
|
||||||
|
return Commands.PROTOCOL_PREFIX + "SetWindowGeometry";
|
||||||
|
}
|
||||||
public static get kOpenWindow() {
|
public static get kOpenWindow() {
|
||||||
return Commands.PROTOCOL_PREFIX + "OpenWindow";
|
return Commands.PROTOCOL_PREFIX + "OpenWindow";
|
||||||
}
|
}
|
||||||
|
@ -289,6 +292,7 @@ export namespace Protocol {
|
||||||
Commands.kRpcGetApplicationConfig,
|
Commands.kRpcGetApplicationConfig,
|
||||||
Commands.kMoveWindow,
|
Commands.kMoveWindow,
|
||||||
Commands.kResizeWindow,
|
Commands.kResizeWindow,
|
||||||
|
Commands.kSetWindowGeometry,
|
||||||
Commands.kOpenWindow,
|
Commands.kOpenWindow,
|
||||||
Commands.kCloseWindow,
|
Commands.kCloseWindow,
|
||||||
Commands.kTopWindow,
|
Commands.kTopWindow,
|
||||||
|
@ -521,6 +525,29 @@ export namespace Protocol {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class SetWindowGeometryRequestEntity extends PacketEntity {
|
||||||
|
window_id: number = 0;
|
||||||
|
x: number = 0;
|
||||||
|
y: number = 0;
|
||||||
|
width: number = 0;
|
||||||
|
height: number = 0;
|
||||||
|
constructor(
|
||||||
|
window_id: number,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
this.command = Commands.kSetWindowGeometry;
|
||||||
|
this.window_id = window_id ?? 0;
|
||||||
|
this.x = x ?? 0;
|
||||||
|
this.y = y ?? 0;
|
||||||
|
this.width = width ?? 0;
|
||||||
|
this.height = height ?? 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class CloseWindowRequestEntity extends PacketEntity {
|
export class CloseWindowRequestEntity extends PacketEntity {
|
||||||
window_id: number = 0;
|
window_id: number = 0;
|
||||||
constructor(window_id: number) {
|
constructor(window_id: number) {
|
||||||
|
|
|
@ -9,51 +9,53 @@
|
||||||
style="background-color: #bce0f0"
|
style="background-color: #bce0f0"
|
||||||
>
|
>
|
||||||
<div id="windows" style="position: absolute">
|
<div id="windows" style="position: absolute">
|
||||||
<window
|
<vue3-resize-drag
|
||||||
@reset_geometry_offset="resetGeometryOffset"
|
:w="item.width * $refs.wall.clientWidth"
|
||||||
@commit_geometry="commitGeometry"
|
:h="item.height * $refs.wall.clientHeight"
|
||||||
@close_this_window="closeWindow"
|
:x="
|
||||||
@close_other_windows="closeOtherWindows"
|
($refs.wall.parentElement?.offsetLeft ?? 0) +
|
||||||
@close_all_windows="closeAllWindows"
|
$refs.wall.offsetLeft +
|
||||||
@top_window="topWindow"
|
item.x * $refs.wall.clientWidth
|
||||||
@lower_window="lowerWindow"
|
"
|
||||||
@dblclick="(evt) => windowDBClick(item.window_id)"
|
:y="
|
||||||
@edit_volume="edit_volume"
|
($refs.wall.parentElement?.offsetTop ?? 0) +
|
||||||
@mute_unmute="mute_unmute"
|
$refs.wall.offsetTop +
|
||||||
@start_polling="start_polling"
|
item.y * $refs.wall.clientHeight
|
||||||
@stop_polling="stop_polling"
|
"
|
||||||
@polling_setting="polling_setting"
|
:zIndex="
|
||||||
|
$store.state.windows_sort.findIndex((element) => element == item.uuid)
|
||||||
|
"
|
||||||
|
:isActive="item.uuid == $store.state.selected_window"
|
||||||
|
:isGuide="true"
|
||||||
v-for="(item, index) in windows"
|
v-for="(item, index) in windows"
|
||||||
:key="index"
|
:key="index"
|
||||||
:ref="'window_' + item.window_id"
|
style="background: red; position: fixed"
|
||||||
:id="'window_' + item.window_id"
|
@resizeEndHandler="resizeWindow(item.window_id, $event)"
|
||||||
:uuid="item.uuid"
|
@moveEndHandler="moveWindow(item.window_id, $event)"
|
||||||
:disable="plan_running"
|
|
||||||
class="window"
|
|
||||||
:mouse_area_flag="area_open_window_flag"
|
|
||||||
:signal_source_table_uuid="item.signal_source_table_uuid"
|
|
||||||
:window="item"
|
|
||||||
:style="{
|
|
||||||
top:
|
|
||||||
(item.y * $store.state.device_screen_height) / wall_height_scaler +
|
|
||||||
'px',
|
|
||||||
left:
|
|
||||||
(item.x * $store.state.device_screen_width) / wall_width_scaler +
|
|
||||||
'px',
|
|
||||||
width:
|
|
||||||
(item.width * $store.state.device_screen_width) /
|
|
||||||
wall_width_scaler +
|
|
||||||
'px',
|
|
||||||
height:
|
|
||||||
(item.height * $store.state.device_screen_height) /
|
|
||||||
wall_height_scaler +
|
|
||||||
'px',
|
|
||||||
'z-index': $store.state.windows_sort.findIndex(
|
|
||||||
(element) => element == item.uuid
|
|
||||||
),
|
|
||||||
}"
|
|
||||||
>
|
>
|
||||||
</window>
|
<window
|
||||||
|
@close_this_window="closeWindow"
|
||||||
|
@close_other_windows="closeOtherWindows"
|
||||||
|
@close_all_windows="closeAllWindows"
|
||||||
|
@top_window="topWindow"
|
||||||
|
@lower_window="lowerWindow"
|
||||||
|
@dblclick="(evt) => windowDBClick(item.window_id)"
|
||||||
|
@edit_volume="edit_volume"
|
||||||
|
@mute_unmute="mute_unmute"
|
||||||
|
@start_polling="start_polling"
|
||||||
|
@stop_polling="stop_polling"
|
||||||
|
@polling_setting="polling_setting"
|
||||||
|
:ref="'window_' + item.window_id"
|
||||||
|
:id="'window_' + item.window_id"
|
||||||
|
:uuid="item.uuid"
|
||||||
|
:disable="plan_running"
|
||||||
|
class="window fit"
|
||||||
|
:mouse_area_flag="area_open_window_flag"
|
||||||
|
:signal_source_table_uuid="item.signal_source_table_uuid"
|
||||||
|
:window="item"
|
||||||
|
>
|
||||||
|
</window>
|
||||||
|
</vue3-resize-drag>
|
||||||
</div>
|
</div>
|
||||||
<div ref="wall_grids" @click="onWallGridsClick">
|
<div ref="wall_grids" @click="onWallGridsClick">
|
||||||
<div
|
<div
|
||||||
|
@ -157,6 +159,8 @@ import { NotifyMessage } from "src/common/ClientConnection";
|
||||||
import EditVolumeDialog from "src/components/EditVolumeDialog.vue";
|
import EditVolumeDialog from "src/components/EditVolumeDialog.vue";
|
||||||
import PollingSettingDialog from "src/components/PollingSettingDialog.vue";
|
import PollingSettingDialog from "src/components/PollingSettingDialog.vue";
|
||||||
|
|
||||||
|
import vue3ResizeDrag from "../third_lib/vue3-resize-drag/components/vue3-resize-drag/index.vue";
|
||||||
|
|
||||||
class Rect {
|
class Rect {
|
||||||
start_x = 0;
|
start_x = 0;
|
||||||
start_y = 0;
|
start_y = 0;
|
||||||
|
@ -174,7 +178,12 @@ class Rect {
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "PageWall",
|
name: "PageWall",
|
||||||
|
|
||||||
components: { Window, EditVolumeDialog, PollingSettingDialog },
|
components: {
|
||||||
|
vue3ResizeDrag,
|
||||||
|
Window,
|
||||||
|
EditVolumeDialog,
|
||||||
|
PollingSettingDialog,
|
||||||
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
const $store = useStore();
|
const $store = useStore();
|
||||||
|
@ -208,17 +217,6 @@ export default defineComponent({
|
||||||
let item_witdh = ref(0);
|
let item_witdh = ref(0);
|
||||||
const item_height = ref(0);
|
const item_height = ref(0);
|
||||||
|
|
||||||
const wall_width_scaler = ref(0);
|
|
||||||
const wall_height_scaler = ref(0);
|
|
||||||
|
|
||||||
const calcWallVWScaler = (wall_width: number, wall_height: number) => {
|
|
||||||
if (wall.value && wall.value.parentElement) {
|
|
||||||
wall_height_scaler.value =
|
|
||||||
$store.state.device_screen_height / wall_height;
|
|
||||||
wall_width_scaler.value = $store.state.device_screen_width / wall_width;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const calcWallItemWH = () => {
|
const calcWallItemWH = () => {
|
||||||
item_witdh.value =
|
item_witdh.value =
|
||||||
wall?.value?.parentElement?.offsetWidth ?? 0 / wall_cols.value;
|
wall?.value?.parentElement?.offsetWidth ?? 0 / wall_cols.value;
|
||||||
|
@ -302,14 +300,10 @@ export default defineComponent({
|
||||||
?.openWindow(
|
?.openWindow(
|
||||||
new Protocol.OpenWindowRequestEntity(
|
new Protocol.OpenWindowRequestEntity(
|
||||||
$store.state.selected_signal_source,
|
$store.state.selected_signal_source,
|
||||||
(start_x * wall_width_scaler.value) /
|
start_x / wall.value.offsetWidth,
|
||||||
$store.state.device_screen_width,
|
start_y / wall.value.offsetHeight,
|
||||||
(start_y * wall_height_scaler.value) /
|
end_x / wall.value.offsetWidth,
|
||||||
$store.state.device_screen_height,
|
end_y / wall.value.offsetHeight
|
||||||
(end_x * wall_width_scaler.value) /
|
|
||||||
$store.state.device_screen_width,
|
|
||||||
(end_y * wall_height_scaler.value) /
|
|
||||||
$store.state.device_screen_height
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -367,12 +361,14 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!flag) {
|
if (!flag) {
|
||||||
EventBus.getInstance().emit(EventNamesDefine.UnSelectAllWindows);
|
$store.commit("setSelectedWindow", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const __temp__size_a__ = 0.00000001;
|
||||||
|
|
||||||
EventBus.getInstance().on(
|
EventBus.getInstance().on(
|
||||||
EventNamesDefine.NotifyMessage,
|
EventNamesDefine.NotifyMessage,
|
||||||
(notify: NotifyMessage) => {
|
(notify: NotifyMessage) => {
|
||||||
|
@ -396,18 +392,34 @@ export default defineComponent({
|
||||||
(item) => item.window_id == temp.window_id
|
(item) => item.window_id == temp.window_id
|
||||||
);
|
);
|
||||||
if (window) {
|
if (window) {
|
||||||
$store.commit("setWindowPropertys", [
|
// 先设置一个坐标让数据变动,然后再设置新数据,保证坐标正常刷新
|
||||||
{
|
// $store.commit("setWindowPropertys", [
|
||||||
window,
|
// {
|
||||||
property_name: "x",
|
// window,
|
||||||
value: temp.x ?? 0,
|
// property_name: "x",
|
||||||
},
|
// value: (temp.x ?? 0) + __temp__size_a__,
|
||||||
{
|
// },
|
||||||
window,
|
// {
|
||||||
property_name: "y",
|
// window,
|
||||||
value: temp.y ?? 0,
|
// property_name: "y",
|
||||||
},
|
// value: (temp.y ?? 0) + __temp__size_a__,
|
||||||
]);
|
// },
|
||||||
|
// ]);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
$store.commit("setWindowPropertys", [
|
||||||
|
{
|
||||||
|
window,
|
||||||
|
property_name: "x",
|
||||||
|
value: temp.x ?? 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
window,
|
||||||
|
property_name: "y",
|
||||||
|
value: temp.y ?? 0,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -420,18 +432,33 @@ export default defineComponent({
|
||||||
(item) => item.window_id == temp.window_id
|
(item) => item.window_id == temp.window_id
|
||||||
);
|
);
|
||||||
if (window) {
|
if (window) {
|
||||||
$store.commit("setWindowPropertys", [
|
// $store.commit("setWindowPropertys", [
|
||||||
{
|
// {
|
||||||
window,
|
// window,
|
||||||
property_name: "width",
|
// property_name: "width",
|
||||||
value: temp.width ?? 0,
|
// value: (temp.width ?? 0) + __temp__size_a__,
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
window,
|
// window,
|
||||||
property_name: "height",
|
// property_name: "height",
|
||||||
value: temp.height ?? 0,
|
// value: (temp.width ?? 0) + __temp__size_a__,
|
||||||
},
|
// },
|
||||||
]);
|
// ]);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
$store.commit("setWindowPropertys", [
|
||||||
|
{
|
||||||
|
window,
|
||||||
|
property_name: "width",
|
||||||
|
value: temp.width ?? 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
window,
|
||||||
|
property_name: "height",
|
||||||
|
value: temp.height ?? 0,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -554,13 +581,69 @@ export default defineComponent({
|
||||||
(element: HTMLElement) => {
|
(element: HTMLElement) => {
|
||||||
if (element) {
|
if (element) {
|
||||||
calcWallItemWH();
|
calcWallItemWH();
|
||||||
calcWallVWScaler(element.offsetWidth, element.offsetHeight);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const moveWindow = (window_id: number, evt: any) => {
|
||||||
|
evt.x = evt.x ?? 0;
|
||||||
|
evt.y = evt.y ?? 0;
|
||||||
|
if (wall.value) {
|
||||||
|
const x =
|
||||||
|
evt.left -
|
||||||
|
(wall.value.parentElement?.offsetLeft ?? 0) -
|
||||||
|
wall.value.offsetLeft;
|
||||||
|
const y =
|
||||||
|
evt.top -
|
||||||
|
(wall.value.parentElement?.offsetTop ?? 0) -
|
||||||
|
wall.value.offsetTop;
|
||||||
|
GlobalData.getInstance()
|
||||||
|
.getCurrentClient()
|
||||||
|
?.moveWindow(
|
||||||
|
window_id,
|
||||||
|
x / wall.value.clientWidth,
|
||||||
|
y / wall.value.clientHeight
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const resizeWindow = (window_id: number, evt: any) => {
|
||||||
|
console.log(evt);
|
||||||
|
evt.width = evt.width ?? 0;
|
||||||
|
evt.height = evt.height ?? 0;
|
||||||
|
evt.left = evt.left ?? 0;
|
||||||
|
evt.top = evt.top ?? 0;
|
||||||
|
// moveWindow(window_id, evt);
|
||||||
|
if (wall.value) {
|
||||||
|
// GlobalData.getInstance()
|
||||||
|
// .getCurrentClient()
|
||||||
|
// ?.resizeWindow(
|
||||||
|
// window_id,
|
||||||
|
// evt.width / wall.value.clientWidth,
|
||||||
|
// evt.height / wall.value.clientHeight
|
||||||
|
// );
|
||||||
|
const x =
|
||||||
|
evt.left -
|
||||||
|
(wall.value.parentElement?.offsetLeft ?? 0) -
|
||||||
|
wall.value.offsetLeft;
|
||||||
|
const y =
|
||||||
|
evt.top -
|
||||||
|
(wall.value.parentElement?.offsetTop ?? 0) -
|
||||||
|
wall.value.offsetTop;
|
||||||
|
GlobalData.getInstance()
|
||||||
|
.getCurrentClient()
|
||||||
|
?.setWindowGeometry(
|
||||||
|
window_id,
|
||||||
|
x / wall.value.clientWidth,
|
||||||
|
y / wall.value.clientHeight,
|
||||||
|
evt.width / wall.value.clientWidth,
|
||||||
|
evt.height / wall.value.clientHeight
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
windows,
|
windows,
|
||||||
wall,
|
wall,
|
||||||
|
@ -568,8 +651,6 @@ export default defineComponent({
|
||||||
wall_cols,
|
wall_cols,
|
||||||
item_witdh,
|
item_witdh,
|
||||||
item_height,
|
item_height,
|
||||||
wall_width_scaler,
|
|
||||||
wall_height_scaler,
|
|
||||||
plan_running,
|
plan_running,
|
||||||
edit_volume_dialog,
|
edit_volume_dialog,
|
||||||
polling_setting_dialog,
|
polling_setting_dialog,
|
||||||
|
@ -672,66 +753,10 @@ export default defineComponent({
|
||||||
|
|
||||||
onWallGridsClick(e: MouseEvent) {
|
onWallGridsClick(e: MouseEvent) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
EventBus.getInstance().emit(EventNamesDefine.UnSelectAllWindows);
|
|
||||||
$store.commit("setSelectedWindow", "");
|
$store.commit("setSelectedWindow", "");
|
||||||
},
|
},
|
||||||
resetGeometryOffset(
|
moveWindow,
|
||||||
window: any,
|
resizeWindow,
|
||||||
offset_x: number,
|
|
||||||
offset_y: number,
|
|
||||||
offset_width: number,
|
|
||||||
offset_height: number
|
|
||||||
) {
|
|
||||||
$store.commit("setWindowPropertys", [
|
|
||||||
{
|
|
||||||
window,
|
|
||||||
property_name: "x",
|
|
||||||
value:
|
|
||||||
window.x +
|
|
||||||
(offset_x * wall_width_scaler.value) /
|
|
||||||
$store.state.device_screen_width,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
window,
|
|
||||||
property_name: "y",
|
|
||||||
value:
|
|
||||||
window.y +
|
|
||||||
(offset_y * wall_height_scaler.value) /
|
|
||||||
$store.state.device_screen_height,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
window,
|
|
||||||
property_name: "width",
|
|
||||||
value: Math.max(
|
|
||||||
window.width +
|
|
||||||
(offset_width * wall_width_scaler.value) /
|
|
||||||
$store.state.device_screen_width,
|
|
||||||
32 / $store.state.device_screen_width
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
window,
|
|
||||||
property_name: "height",
|
|
||||||
value: Math.max(
|
|
||||||
window.height +
|
|
||||||
(offset_height * wall_height_scaler.value) /
|
|
||||||
$store.state.device_screen_height,
|
|
||||||
32 / $store.state.device_screen_height
|
|
||||||
),
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
commitGeometry(window: any) {
|
|
||||||
const win = window as WindowOpenNotifyEntity;
|
|
||||||
if (win) {
|
|
||||||
GlobalData.getInstance()
|
|
||||||
.getCurrentClient()
|
|
||||||
?.moveWindow(win.window_id, win.x, win.y);
|
|
||||||
GlobalData.getInstance()
|
|
||||||
.getCurrentClient()
|
|
||||||
?.resizeWindow(win.window_id, win.width, win.height);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
closeAllWindows() {
|
closeAllWindows() {
|
||||||
for (const window of $store.state.windows) {
|
for (const window of $store.state.windows) {
|
||||||
if (window) {
|
if (window) {
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
|
@ -0,0 +1,10 @@
|
||||||
|
<template>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
export default defineComponent({
|
||||||
|
name:'vue3ResizeDragCanvas'
|
||||||
|
})
|
||||||
|
</script>
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { watch } from 'vue';
|
||||||
|
function active(props: any, emit: Function) {
|
||||||
|
// 监听是否激活
|
||||||
|
watch(() => {
|
||||||
|
return props.isActive
|
||||||
|
},
|
||||||
|
(n) => {
|
||||||
|
if(n){
|
||||||
|
emit('activated',{
|
||||||
|
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
emit('deactivated',{
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export default active
|
|
@ -0,0 +1,66 @@
|
||||||
|
import { ref, reactive } from "vue";
|
||||||
|
import { styleIf } from "../../../types/style";
|
||||||
|
// 外层元素点击拖拽
|
||||||
|
const itemDrag = (
|
||||||
|
ev: any,
|
||||||
|
emit: Function,
|
||||||
|
props: any,
|
||||||
|
style: any,
|
||||||
|
moveing: any
|
||||||
|
): void => {
|
||||||
|
let press_x = ev.clientX;
|
||||||
|
let press_y = ev.clientY;
|
||||||
|
let target: any = ev.target || ev.srcElement;
|
||||||
|
ev.stopPropagation();
|
||||||
|
ev.preventDefault();
|
||||||
|
|
||||||
|
emit("downHandler", {
|
||||||
|
// 点击元素事件回调
|
||||||
|
el: target,
|
||||||
|
e: ev,
|
||||||
|
});
|
||||||
|
if (!props.isDraggable) return;
|
||||||
|
//鼠标按下并移动的事件
|
||||||
|
document.onmousemove = (e: any) => {
|
||||||
|
if (e.movementX || e.movementY) {
|
||||||
|
moveing.value = true;
|
||||||
|
|
||||||
|
let offset_left = press_x - e.clientX;
|
||||||
|
let offset_top = press_y - e.clientY;
|
||||||
|
press_x = e.clientX;
|
||||||
|
press_y = e.clientY;
|
||||||
|
|
||||||
|
//绑定元素位置到positionX和positionY上面
|
||||||
|
|
||||||
|
//移动当前元素
|
||||||
|
style.top -= offset_top;
|
||||||
|
style.left -= offset_left;
|
||||||
|
emit("moveHandler", {
|
||||||
|
// 移动事件回调
|
||||||
|
el: target,
|
||||||
|
e,
|
||||||
|
top: style.top,
|
||||||
|
left: style.left,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
document.onmouseup = (e: any) => {
|
||||||
|
moveing.value = false;
|
||||||
|
if (style.left == style.back_left && style.top == style.back_top) {
|
||||||
|
style.left = style.back_left;
|
||||||
|
style.top = style.back_top;
|
||||||
|
} else {
|
||||||
|
emit("moveEndHandler", {
|
||||||
|
// 抬起事件回调
|
||||||
|
el: target,
|
||||||
|
e,
|
||||||
|
top: style.top,
|
||||||
|
left: style.left,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
document.onmousemove = null;
|
||||||
|
document.onmouseup = null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export default itemDrag;
|
|
@ -0,0 +1,106 @@
|
||||||
|
const props = {
|
||||||
|
x: {
|
||||||
|
type: Number,
|
||||||
|
default: () => {
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
type: Number,
|
||||||
|
default: () => {
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
zIndex: {
|
||||||
|
type: Number,
|
||||||
|
default: () => {
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
w: {
|
||||||
|
type: Number,
|
||||||
|
default: () => {
|
||||||
|
return 100;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
h: {
|
||||||
|
type: Number,
|
||||||
|
default: () => {
|
||||||
|
return 100;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
isActive: {
|
||||||
|
type: Boolean,
|
||||||
|
default: () => {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
isDraggable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: () => {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
isResizable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: () => {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
isGuide: {
|
||||||
|
type: Boolean,
|
||||||
|
default: () => {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
guideStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
resizeIconSize: {
|
||||||
|
type: Number,
|
||||||
|
default: () => {
|
||||||
|
return 8;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
isRotate: {
|
||||||
|
type: Boolean,
|
||||||
|
default: () => {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rotate: {
|
||||||
|
type: Number,
|
||||||
|
default: () => {
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
limitTop: {
|
||||||
|
type: Number,
|
||||||
|
default: () => {
|
||||||
|
return -1;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
limitLeft: {
|
||||||
|
type: Number,
|
||||||
|
default: () => {
|
||||||
|
return -1;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
limitBottom: {
|
||||||
|
type: Number,
|
||||||
|
default: () => {
|
||||||
|
return -1;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
limitRight: {
|
||||||
|
type: Number,
|
||||||
|
default: () => {
|
||||||
|
return -1;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default props;
|
|
@ -0,0 +1,146 @@
|
||||||
|
import { computed, reactive, ref } from "vue";
|
||||||
|
import { styleIf } from "../../../types/style";
|
||||||
|
function render(props: any) {
|
||||||
|
// 外层元素定位style
|
||||||
|
const style = reactive<styleIf>({
|
||||||
|
top: props.y,
|
||||||
|
left: props.x,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
zIndex: props.zIndex,
|
||||||
|
width: props.w,
|
||||||
|
height: props.h,
|
||||||
|
rotate: props.rotate,
|
||||||
|
back_height: 0,
|
||||||
|
back_left: 0,
|
||||||
|
back_top: 0,
|
||||||
|
back_width: 0,
|
||||||
|
});
|
||||||
|
const moveing = ref(false);
|
||||||
|
// 计算属性 计算元素位置以及宽高
|
||||||
|
const styleHandler = computed(() => {
|
||||||
|
return {
|
||||||
|
top: style.top + "px",
|
||||||
|
left: style.left + "px",
|
||||||
|
right: style.right + "px",
|
||||||
|
bottom: style.bottom + "px",
|
||||||
|
zIndex: style.zIndex,
|
||||||
|
width: style.width + "px",
|
||||||
|
height: style.height + "px",
|
||||||
|
transform: `rotate(${style.rotate}deg)`,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const dragElResizeIcon = computed(() => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
class: "drag-lt",
|
||||||
|
style: {
|
||||||
|
top: -(props.resizeIconSize / 2) + "px",
|
||||||
|
left: -(props.resizeIconSize / 2) + "px",
|
||||||
|
width: props.resizeIconSize + "px",
|
||||||
|
height: props.resizeIconSize + "px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
class: "drag-ct",
|
||||||
|
style: {
|
||||||
|
top: -(props.resizeIconSize / 2) + "px",
|
||||||
|
left: <number>style.width / 2 - props.resizeIconSize / 2 + "px",
|
||||||
|
width: props.resizeIconSize + "px",
|
||||||
|
height: props.resizeIconSize + "px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
class: "drag-rt",
|
||||||
|
style: {
|
||||||
|
top: -(props.resizeIconSize / 2) + "px",
|
||||||
|
right: -(props.resizeIconSize / 2) + "px",
|
||||||
|
width: props.resizeIconSize + "px",
|
||||||
|
height: props.resizeIconSize + "px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
class: "drag-rc",
|
||||||
|
style: {
|
||||||
|
top: <number>style.height / 2 - props.resizeIconSize / 2 + "px",
|
||||||
|
right: -(props.resizeIconSize / 2) + "px",
|
||||||
|
width: props.resizeIconSize + "px",
|
||||||
|
height: props.resizeIconSize + "px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
class: "drag-rb",
|
||||||
|
style: {
|
||||||
|
bottom: -(props.resizeIconSize / 2) + "px",
|
||||||
|
right: -(props.resizeIconSize / 2) + "px",
|
||||||
|
width: props.resizeIconSize + "px",
|
||||||
|
height: props.resizeIconSize + "px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
class: "drag-bc",
|
||||||
|
style: {
|
||||||
|
bottom: -(props.resizeIconSize / 2) + "px",
|
||||||
|
left: <number>style.width / 2 - props.resizeIconSize / 2 + "px",
|
||||||
|
width: props.resizeIconSize + "px",
|
||||||
|
height: props.resizeIconSize + "px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
class: "drag-lb",
|
||||||
|
style: {
|
||||||
|
bottom: -(props.resizeIconSize / 2) + "px",
|
||||||
|
left: -(props.resizeIconSize / 2) + "px",
|
||||||
|
width: props.resizeIconSize + "px",
|
||||||
|
height: props.resizeIconSize + "px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
class: "drag-lc",
|
||||||
|
style: {
|
||||||
|
top: <number>style.height / 2 - props.resizeIconSize / 2 + "px",
|
||||||
|
left: -(props.resizeIconSize / 2) + "px",
|
||||||
|
width: props.resizeIconSize + "px",
|
||||||
|
height: props.resizeIconSize + "px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
|
const guideBaseStyle = computed(() => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
top: 0,
|
||||||
|
borderTop: "1px dashed #58B0E9",
|
||||||
|
width: "100vw",
|
||||||
|
left: `calc(-50vw + ${<number>style.width / 2}px)`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
left: 0,
|
||||||
|
borderLeft: "1px dashed #58B0E9",
|
||||||
|
height: "100vh",
|
||||||
|
top: `calc(-50vh + ${<number>style.height / 2}px)`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
right: 0,
|
||||||
|
borderRight: "1px dashed #58B0E9",
|
||||||
|
height: "100vh",
|
||||||
|
top: `calc(-50vh + ${<number>style.height / 2}px)`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
bottom: 0,
|
||||||
|
borderBottom: "1px dashed #58B0E9",
|
||||||
|
width: "100vw",
|
||||||
|
left: `calc(-50vw + ${<number>style.width / 2}px)`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
style,
|
||||||
|
moveing,
|
||||||
|
styleHandler,
|
||||||
|
dragElResizeIcon,
|
||||||
|
guideBaseStyle,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default render;
|
|
@ -0,0 +1,114 @@
|
||||||
|
// 元素缩放
|
||||||
|
const itemResize = (
|
||||||
|
ev: any,
|
||||||
|
cls: string,
|
||||||
|
index: number,
|
||||||
|
emit: Function,
|
||||||
|
style: any
|
||||||
|
) => {
|
||||||
|
let move_flag = false;
|
||||||
|
let target: any = ev.target.offsetParent || ev.srcElement.parentNode;
|
||||||
|
|
||||||
|
ev.stopPropagation();
|
||||||
|
ev.preventDefault();
|
||||||
|
let w: number = 0;
|
||||||
|
let h: number = 0;
|
||||||
|
let top: number = 0;
|
||||||
|
let left: number = 0;
|
||||||
|
// 鼠标拖拽改变元素大小
|
||||||
|
document.onmousemove = (e) => {
|
||||||
|
if (e.movementX || e.movementY) {
|
||||||
|
move_flag = true;
|
||||||
|
switch (cls) {
|
||||||
|
case "drag-ct": // top center
|
||||||
|
h = target.offsetHeight + target.offsetTop - e.clientY;
|
||||||
|
w = target.offsetWidth;
|
||||||
|
top = e.clientY;
|
||||||
|
left = target.offsetLeft;
|
||||||
|
break;
|
||||||
|
case "drag-lc": // left center
|
||||||
|
h = target.offsetHeight;
|
||||||
|
w = target.offsetWidth + target.offsetLeft - e.clientX;
|
||||||
|
top = target.offsetTop;
|
||||||
|
left = e.clientX;
|
||||||
|
break;
|
||||||
|
case "drag-bc": // bottom center
|
||||||
|
h = e.clientY - target.offsetTop;
|
||||||
|
w = target.offsetWidth;
|
||||||
|
top = target.offsetTop;
|
||||||
|
left = target.offsetLeft;
|
||||||
|
break;
|
||||||
|
case "drag-rc": // right center
|
||||||
|
h = target.offsetHeight;
|
||||||
|
w = e.clientX - target.offsetLeft;
|
||||||
|
top = target.offsetTop;
|
||||||
|
left = target.offsetLeft;
|
||||||
|
break;
|
||||||
|
case "drag-lt": // left top
|
||||||
|
h = target.offsetHeight + target.offsetTop - e.clientY;
|
||||||
|
w = target.offsetWidth + target.offsetLeft - e.clientX;
|
||||||
|
top = e.clientY;
|
||||||
|
left = e.clientX;
|
||||||
|
break;
|
||||||
|
case "drag-rt": // right top
|
||||||
|
h = target.offsetHeight + target.offsetTop - e.clientY;
|
||||||
|
w = e.clientX - target.offsetLeft;
|
||||||
|
top = e.clientY;
|
||||||
|
left = target.offsetLeft;
|
||||||
|
break;
|
||||||
|
case "drag-rb": // right bottom
|
||||||
|
h = e.clientY - target.offsetTop;
|
||||||
|
w = e.clientX - target.offsetLeft;
|
||||||
|
top = target.offsetTop;
|
||||||
|
left = target.offsetLeft;
|
||||||
|
break;
|
||||||
|
case "drag-lb": // left bottom
|
||||||
|
h = e.clientY - target.offsetTop;
|
||||||
|
w = target.offsetWidth + target.offsetLeft - e.clientX;
|
||||||
|
top = target.offsetTop;
|
||||||
|
left = e.clientX;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
w = target.offsetWidth;
|
||||||
|
h = target.offsetHeight;
|
||||||
|
top = target.offsetTop;
|
||||||
|
left = target.offsetLeft;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
emit("resizeHandler", {
|
||||||
|
el: target,
|
||||||
|
e,
|
||||||
|
w,
|
||||||
|
h,
|
||||||
|
top,
|
||||||
|
left,
|
||||||
|
});
|
||||||
|
style.width = w;
|
||||||
|
style.height = h;
|
||||||
|
style.top = top;
|
||||||
|
style.left = left;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.onmouseup = (e: any) => {
|
||||||
|
if (!move_flag) {
|
||||||
|
style.left = style.back_left;
|
||||||
|
style.top = style.back_top;
|
||||||
|
} else {
|
||||||
|
console.log(style);
|
||||||
|
emit("resizeEndHandler", {
|
||||||
|
// 抬起事件回调
|
||||||
|
el: target,
|
||||||
|
e: ev,
|
||||||
|
top: style.top,
|
||||||
|
left: style.left,
|
||||||
|
width: style.width,
|
||||||
|
height: style.height,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
document.onmousemove = null;
|
||||||
|
document.onmouseup = null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export default itemResize;
|
|
@ -0,0 +1,44 @@
|
||||||
|
|
||||||
|
// 元素旋转
|
||||||
|
const itemRotate = (ev: any,emit: Function,style:any) => {
|
||||||
|
let target:any = ev.target.offsetParent || ev.srcElement.parentNode
|
||||||
|
ev.stopPropagation()
|
||||||
|
ev.preventDefault()
|
||||||
|
let cx:number = target.offsetWidth / 2
|
||||||
|
let cy:number = target.offsetHeight / 2
|
||||||
|
let offsetX:number = target.offsetLeft
|
||||||
|
let offsetY:number = target.offsetTop
|
||||||
|
document.onmousemove = (e:any) => {
|
||||||
|
let mouseX:number = e.pageX - offsetX;//计算出鼠标相对于画布顶点的位置,无pageX时用clientY + body.scrollTop - body.clientTop代替,可视区域y+body滚动条所走的距离-body的border-top,不用offsetX等属性的原因在于,鼠标会移出画布
|
||||||
|
let mouseY:number = e.pageY - offsetY;
|
||||||
|
let ox:number = mouseX - cx;//cx,cy为圆心
|
||||||
|
let oy:number = mouseY - cy;
|
||||||
|
let to:number = Math.abs(ox / oy);
|
||||||
|
let angle:number = Math.atan(to) / (2 * Math.PI) * 360;//鼠标相对于旋转中心的角度
|
||||||
|
if (ox < 0 && oy < 0)//相对在左上角,第四象限,js中坐标系是从左上角开始的,这里的象限是正常坐标系
|
||||||
|
{
|
||||||
|
angle = -angle;
|
||||||
|
} else if (ox < 0 && oy > 0)//左下角,3象限
|
||||||
|
{
|
||||||
|
angle = -(180 - angle)
|
||||||
|
} else if (ox > 0 && oy < 0)//右上角,1象限
|
||||||
|
{
|
||||||
|
angle = angle;
|
||||||
|
} else if (ox > 0 && oy > 0)//右下角,2象限
|
||||||
|
{
|
||||||
|
angle = 180 - angle;
|
||||||
|
}
|
||||||
|
style.rotate = angle
|
||||||
|
emit('rotateHandler', {
|
||||||
|
el: target,
|
||||||
|
e,
|
||||||
|
rotate: angle
|
||||||
|
})
|
||||||
|
}
|
||||||
|
document.onmouseup = () => {
|
||||||
|
document.onmousemove = null
|
||||||
|
document.onmouseup = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default itemRotate
|
|
@ -0,0 +1,41 @@
|
||||||
|
import { watch } from 'vue'
|
||||||
|
// 外层元素点击拖拽
|
||||||
|
const watchProps = (props: any, style: any): void => {
|
||||||
|
watch(() => {
|
||||||
|
return props.x
|
||||||
|
},
|
||||||
|
(n) => {
|
||||||
|
style.left = n
|
||||||
|
})
|
||||||
|
watch(() => {
|
||||||
|
return props.y
|
||||||
|
},
|
||||||
|
(n) => {
|
||||||
|
style.top = n
|
||||||
|
})
|
||||||
|
watch(() => {
|
||||||
|
return props.zIndex
|
||||||
|
},
|
||||||
|
(n) => {
|
||||||
|
style.zIndex = n
|
||||||
|
})
|
||||||
|
watch(() => {
|
||||||
|
return props.w
|
||||||
|
},
|
||||||
|
(n) => {
|
||||||
|
style.width = n
|
||||||
|
})
|
||||||
|
watch(() => {
|
||||||
|
return props.h
|
||||||
|
},
|
||||||
|
(n) => {
|
||||||
|
style.height = n
|
||||||
|
})
|
||||||
|
watch(() => {
|
||||||
|
return props.rotate
|
||||||
|
},
|
||||||
|
(n) => {
|
||||||
|
style.rotate = n
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export default watchProps
|
|
@ -0,0 +1,145 @@
|
||||||
|
<template>
|
||||||
|
<div class="vue3-resize-drag" :style="styleHandler" @mousedown="itemDown">
|
||||||
|
<slot></slot>
|
||||||
|
<div v-if="isRotate" class="rotate-icon" @mousedown="itemRotate"></div>
|
||||||
|
<!-- 组件移动辅助线 -->
|
||||||
|
<div
|
||||||
|
v-if="isGuide"
|
||||||
|
v-for="i in [1, 2, 3, 4]"
|
||||||
|
:key="i"
|
||||||
|
:style="moveing ? { ...guideBaseStyle[i - 1], ...guideStyle } : {}"
|
||||||
|
class="guide"
|
||||||
|
></div>
|
||||||
|
<!-- 组件四周缩放按钮 -->
|
||||||
|
<div
|
||||||
|
v-if="isResizable && isActive"
|
||||||
|
v-for="(el, index) in dragElResizeIcon"
|
||||||
|
:key="el.class"
|
||||||
|
class="dragElResizeIcon"
|
||||||
|
:class="el.class"
|
||||||
|
@mousedown="itemResize($event, el.class, index)"
|
||||||
|
:style="el.style"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { computed, defineComponent, reactive, ref, watch } from "vue";
|
||||||
|
import { styleIf } from "../../types/style";
|
||||||
|
import renderFn from "./func/renderData";
|
||||||
|
import props from "./func/props";
|
||||||
|
import watchProps from "./func/watchProps";
|
||||||
|
|
||||||
|
import active from "./func/active";
|
||||||
|
import itemDrag from "./func/drag";
|
||||||
|
import itemRotateFn from "./func/rotate";
|
||||||
|
import itemResizeFn from "./func/resize";
|
||||||
|
export default defineComponent({
|
||||||
|
name: "vue3ResizeDrag",
|
||||||
|
props,
|
||||||
|
setup(props, { emit }) {
|
||||||
|
// 变量----------------------------------------------------------------------------------------------
|
||||||
|
let {
|
||||||
|
style, // 初始化组件位置级z-index
|
||||||
|
moveing, // 是否移动变量 用来判断辅助线是否显示
|
||||||
|
styleHandler, // 计算属性处理style变量
|
||||||
|
dragElResizeIcon, // 缩放图标初始位置 样式
|
||||||
|
guideBaseStyle, // 辅助线默认样式
|
||||||
|
} = renderFn(props); // 初始化data数据
|
||||||
|
|
||||||
|
// 事件-----------------------------------------------------------------------------------------------
|
||||||
|
watchProps(props, style);
|
||||||
|
const itemResize = (ev: any, cls: string, index: number) => {
|
||||||
|
// 缩放
|
||||||
|
style.back_top = style.top;
|
||||||
|
style.back_height = style.height;
|
||||||
|
style.back_left = style.left;
|
||||||
|
style.back_width = style.width;
|
||||||
|
itemResizeFn(ev, cls, index, emit, style);
|
||||||
|
};
|
||||||
|
const itemRotate = (ev: any) => {
|
||||||
|
// 旋转
|
||||||
|
itemRotateFn(ev, emit, style);
|
||||||
|
};
|
||||||
|
const itemDown = (ev: any) => {
|
||||||
|
if (!props.isActive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 拖拽
|
||||||
|
if (ev.ctrlKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
style.back_top = style.top;
|
||||||
|
style.back_height = style.height;
|
||||||
|
style.back_left = style.left;
|
||||||
|
style.back_width = style.width;
|
||||||
|
itemDrag(ev, emit, props, style, moveing);
|
||||||
|
};
|
||||||
|
active(props, emit); // 监听激活
|
||||||
|
return {
|
||||||
|
style,
|
||||||
|
guideBaseStyle,
|
||||||
|
dragElResizeIcon,
|
||||||
|
styleHandler,
|
||||||
|
itemDown,
|
||||||
|
itemResize,
|
||||||
|
itemRotate,
|
||||||
|
moveing,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.vue3-resize-drag {
|
||||||
|
position: absolute;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px dashed #ccc;
|
||||||
|
transition: width height 1s;
|
||||||
|
transform-origin: center center;
|
||||||
|
}
|
||||||
|
/* 辅助线 */
|
||||||
|
.guide {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
/* 旋转图标 */
|
||||||
|
.rotate-icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
position: absolute;
|
||||||
|
top: -20px;
|
||||||
|
left: calc(50% - 8px);
|
||||||
|
background: url("../../assets/rotate.png") no-repeat;
|
||||||
|
background-size: 100%;
|
||||||
|
}
|
||||||
|
/* 缩放角标 */
|
||||||
|
.dragElResizeIcon {
|
||||||
|
position: absolute;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
.drag-ct {
|
||||||
|
cursor: s-resize;
|
||||||
|
}
|
||||||
|
.drag-lt {
|
||||||
|
cursor: se-resize;
|
||||||
|
}
|
||||||
|
.drag-rt {
|
||||||
|
cursor: ne-resize;
|
||||||
|
}
|
||||||
|
.drag-rc {
|
||||||
|
cursor: w-resize;
|
||||||
|
}
|
||||||
|
.drag-rb {
|
||||||
|
cursor: se-resize;
|
||||||
|
}
|
||||||
|
.drag-bc {
|
||||||
|
cursor: s-resize;
|
||||||
|
}
|
||||||
|
.drag-lb {
|
||||||
|
cursor: ne-resize;
|
||||||
|
}
|
||||||
|
.drag-lc {
|
||||||
|
cursor: w-resize;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,14 @@
|
||||||
|
export interface styleIf {
|
||||||
|
left: number | string;
|
||||||
|
top: number | string;
|
||||||
|
bottom: number | string;
|
||||||
|
right: number | string;
|
||||||
|
zIndex: number;
|
||||||
|
width: number | string;
|
||||||
|
height: number | string;
|
||||||
|
rotate: number;
|
||||||
|
back_left: number | string;
|
||||||
|
back_top: number | string;
|
||||||
|
back_width: number | string;
|
||||||
|
back_height: number | string;
|
||||||
|
}
|
Loading…
Reference in New Issue