重构虚拟窗口移动,调整大小逻辑
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",
|
||||
"autoprefixer": "^10.4.2",
|
||||
"axios": "^0.21.1",
|
||||
"core-js": "^3.6.5",
|
||||
"element-resize-detector": "^1.2.3",
|
||||
"quasar": "^2.5.4",
|
||||
"core-js": "^3.21.0",
|
||||
"element-resize-detector": "^1.2.4",
|
||||
"quasar": "^2.5.5",
|
||||
"reconnecting-websocket": "^4.4.0",
|
||||
"v-viewer": "^3.0.9",
|
||||
"vue": "^3.0.0",
|
||||
"vue-i18n": "^9.0.0-beta.0",
|
||||
"vue-i18n": "^9.1.9",
|
||||
"vue-router": "^4.0.0",
|
||||
"vuex": "^4.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@quasar/app": "^3.3.2",
|
||||
"@quasar/app": "^3.3.3",
|
||||
"@types/node": "^10.17.15",
|
||||
"workbox-webpack-plugin": "^6.0.0"
|
||||
"workbox-webpack-plugin": "^6.4.2"
|
||||
},
|
||||
"browserslist": [
|
||||
"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) {
|
||||
this.ws?.send(
|
||||
JSON.stringify(new Protocol.CloseWindowRequestEntity(window_id))
|
||||
|
|
|
@ -18,7 +18,6 @@ export default class EventBus extends EventEmitter {
|
|||
|
||||
export namespace EventNamesDefine {
|
||||
export const UnKnow = "onUnKnow";
|
||||
export const UnSelectAllWindows = "onUnSelectAllWindows";
|
||||
export const WindowResize = "onWindowResize";
|
||||
export const WindowMouseDown = "onWindowMouseDown";
|
||||
export const WindowMouseMove = "onWindowMouseMove";
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<template>
|
||||
<div
|
||||
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"
|
||||
@mousedown="onMouseDown"
|
||||
@mousemove="onMouseMove"
|
||||
@mouseleave="onMouseLeave"
|
||||
@mouseup="onMouseUp"
|
||||
:style="{
|
||||
background: $props.window.client_color,
|
||||
}"
|
||||
|
@ -154,87 +154,6 @@
|
|||
}}</q-tooltip>
|
||||
</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>
|
||||
</template>
|
||||
|
||||
|
@ -261,81 +180,6 @@
|
|||
.top {
|
||||
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>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -382,8 +226,6 @@ export default defineComponent({
|
|||
},
|
||||
},
|
||||
emits: [
|
||||
"reset_geometry_offset",
|
||||
"commit_geometry",
|
||||
"close_this_window",
|
||||
"close_other_windows",
|
||||
"close_all_windows",
|
||||
|
@ -423,56 +265,13 @@ export default defineComponent({
|
|||
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();
|
||||
|
||||
watch(
|
||||
() => props.window,
|
||||
(a, b) => {
|
||||
reload_signal_source();
|
||||
selected.value = false;
|
||||
cleanMouseDownFlag();
|
||||
}
|
||||
);
|
||||
const flags = new _Flags();
|
||||
let ctrl_press_flag = false;
|
||||
|
||||
return {
|
||||
signal_source,
|
||||
selected,
|
||||
can_move,
|
||||
can_resize,
|
||||
flags,
|
||||
is_audo_player_window,
|
||||
is_clock_window,
|
||||
|
@ -485,112 +284,7 @@ export default defineComponent({
|
|||
}
|
||||
if (!props.mouse_area_flag) {
|
||||
evt.stopPropagation();
|
||||
if (selected.value != true) {
|
||||
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();
|
||||
$store.commit("setSelectedWindow", props.window.uuid);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -60,6 +60,9 @@ export namespace Protocol {
|
|||
return Commands.PROTOCOL_PREFIX + "ResizeWindow";
|
||||
}
|
||||
|
||||
public static get kSetWindowGeometry() {
|
||||
return Commands.PROTOCOL_PREFIX + "SetWindowGeometry";
|
||||
}
|
||||
public static get kOpenWindow() {
|
||||
return Commands.PROTOCOL_PREFIX + "OpenWindow";
|
||||
}
|
||||
|
@ -289,6 +292,7 @@ export namespace Protocol {
|
|||
Commands.kRpcGetApplicationConfig,
|
||||
Commands.kMoveWindow,
|
||||
Commands.kResizeWindow,
|
||||
Commands.kSetWindowGeometry,
|
||||
Commands.kOpenWindow,
|
||||
Commands.kCloseWindow,
|
||||
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 {
|
||||
window_id: number = 0;
|
||||
constructor(window_id: number) {
|
||||
|
|
|
@ -9,51 +9,53 @@
|
|||
style="background-color: #bce0f0"
|
||||
>
|
||||
<div id="windows" style="position: absolute">
|
||||
<window
|
||||
@reset_geometry_offset="resetGeometryOffset"
|
||||
@commit_geometry="commitGeometry"
|
||||
@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"
|
||||
<vue3-resize-drag
|
||||
:w="item.width * $refs.wall.clientWidth"
|
||||
:h="item.height * $refs.wall.clientHeight"
|
||||
:x="
|
||||
($refs.wall.parentElement?.offsetLeft ?? 0) +
|
||||
$refs.wall.offsetLeft +
|
||||
item.x * $refs.wall.clientWidth
|
||||
"
|
||||
:y="
|
||||
($refs.wall.parentElement?.offsetTop ?? 0) +
|
||||
$refs.wall.offsetTop +
|
||||
item.y * $refs.wall.clientHeight
|
||||
"
|
||||
: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"
|
||||
:key="index"
|
||||
:ref="'window_' + item.window_id"
|
||||
:id="'window_' + item.window_id"
|
||||
:uuid="item.uuid"
|
||||
: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
|
||||
),
|
||||
}"
|
||||
style="background: red; position: fixed"
|
||||
@resizeEndHandler="resizeWindow(item.window_id, $event)"
|
||||
@moveEndHandler="moveWindow(item.window_id, $event)"
|
||||
>
|
||||
</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 ref="wall_grids" @click="onWallGridsClick">
|
||||
<div
|
||||
|
@ -157,6 +159,8 @@ import { NotifyMessage } from "src/common/ClientConnection";
|
|||
import EditVolumeDialog from "src/components/EditVolumeDialog.vue";
|
||||
import PollingSettingDialog from "src/components/PollingSettingDialog.vue";
|
||||
|
||||
import vue3ResizeDrag from "../third_lib/vue3-resize-drag/components/vue3-resize-drag/index.vue";
|
||||
|
||||
class Rect {
|
||||
start_x = 0;
|
||||
start_y = 0;
|
||||
|
@ -174,7 +178,12 @@ class Rect {
|
|||
export default defineComponent({
|
||||
name: "PageWall",
|
||||
|
||||
components: { Window, EditVolumeDialog, PollingSettingDialog },
|
||||
components: {
|
||||
vue3ResizeDrag,
|
||||
Window,
|
||||
EditVolumeDialog,
|
||||
PollingSettingDialog,
|
||||
},
|
||||
setup() {
|
||||
const $q = useQuasar();
|
||||
const $store = useStore();
|
||||
|
@ -208,17 +217,6 @@ export default defineComponent({
|
|||
let item_witdh = 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 = () => {
|
||||
item_witdh.value =
|
||||
wall?.value?.parentElement?.offsetWidth ?? 0 / wall_cols.value;
|
||||
|
@ -302,14 +300,10 @@ export default defineComponent({
|
|||
?.openWindow(
|
||||
new Protocol.OpenWindowRequestEntity(
|
||||
$store.state.selected_signal_source,
|
||||
(start_x * wall_width_scaler.value) /
|
||||
$store.state.device_screen_width,
|
||||
(start_y * wall_height_scaler.value) /
|
||||
$store.state.device_screen_height,
|
||||
(end_x * wall_width_scaler.value) /
|
||||
$store.state.device_screen_width,
|
||||
(end_y * wall_height_scaler.value) /
|
||||
$store.state.device_screen_height
|
||||
start_x / wall.value.offsetWidth,
|
||||
start_y / wall.value.offsetHeight,
|
||||
end_x / wall.value.offsetWidth,
|
||||
end_y / wall.value.offsetHeight
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -367,12 +361,14 @@ export default defineComponent({
|
|||
}
|
||||
}
|
||||
if (!flag) {
|
||||
EventBus.getInstance().emit(EventNamesDefine.UnSelectAllWindows);
|
||||
$store.commit("setSelectedWindow", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const __temp__size_a__ = 0.00000001;
|
||||
|
||||
EventBus.getInstance().on(
|
||||
EventNamesDefine.NotifyMessage,
|
||||
(notify: NotifyMessage) => {
|
||||
|
@ -396,18 +392,34 @@ export default defineComponent({
|
|||
(item) => item.window_id == temp.window_id
|
||||
);
|
||||
if (window) {
|
||||
$store.commit("setWindowPropertys", [
|
||||
{
|
||||
window,
|
||||
property_name: "x",
|
||||
value: temp.x ?? 0,
|
||||
},
|
||||
{
|
||||
window,
|
||||
property_name: "y",
|
||||
value: temp.y ?? 0,
|
||||
},
|
||||
]);
|
||||
// 先设置一个坐标让数据变动,然后再设置新数据,保证坐标正常刷新
|
||||
// $store.commit("setWindowPropertys", [
|
||||
// {
|
||||
// window,
|
||||
// property_name: "x",
|
||||
// value: (temp.x ?? 0) + __temp__size_a__,
|
||||
// },
|
||||
// {
|
||||
// window,
|
||||
// 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
|
||||
);
|
||||
if (window) {
|
||||
$store.commit("setWindowPropertys", [
|
||||
{
|
||||
window,
|
||||
property_name: "width",
|
||||
value: temp.width ?? 0,
|
||||
},
|
||||
{
|
||||
window,
|
||||
property_name: "height",
|
||||
value: temp.height ?? 0,
|
||||
},
|
||||
]);
|
||||
// $store.commit("setWindowPropertys", [
|
||||
// {
|
||||
// window,
|
||||
// property_name: "width",
|
||||
// value: (temp.width ?? 0) + __temp__size_a__,
|
||||
// },
|
||||
// {
|
||||
// window,
|
||||
// property_name: "height",
|
||||
// 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) => {
|
||||
if (element) {
|
||||
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 {
|
||||
windows,
|
||||
wall,
|
||||
|
@ -568,8 +651,6 @@ export default defineComponent({
|
|||
wall_cols,
|
||||
item_witdh,
|
||||
item_height,
|
||||
wall_width_scaler,
|
||||
wall_height_scaler,
|
||||
plan_running,
|
||||
edit_volume_dialog,
|
||||
polling_setting_dialog,
|
||||
|
@ -672,66 +753,10 @@ export default defineComponent({
|
|||
|
||||
onWallGridsClick(e: MouseEvent) {
|
||||
e.stopPropagation();
|
||||
EventBus.getInstance().emit(EventNamesDefine.UnSelectAllWindows);
|
||||
$store.commit("setSelectedWindow", "");
|
||||
},
|
||||
resetGeometryOffset(
|
||||
window: any,
|
||||
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);
|
||||
}
|
||||
},
|
||||
moveWindow,
|
||||
resizeWindow,
|
||||
closeAllWindows() {
|
||||
for (const window of $store.state.windows) {
|
||||
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