zdg #92
|
@ -0,0 +1,81 @@
|
||||||
|
/**
|
||||||
|
* @description: v-drag
|
||||||
|
* @author zdg
|
||||||
|
* @date 2023-06-07
|
||||||
|
*/
|
||||||
|
// 工具包
|
||||||
|
const utils = {
|
||||||
|
// Creates an event handler that can be used in Vue code
|
||||||
|
// setup start moving end
|
||||||
|
vueDragEvent: (el, action) => {
|
||||||
|
el.dispatchEvent(new Event(`drag-${action}`))
|
||||||
|
},
|
||||||
|
dragStart: (el, target, axis, snap, e) => {
|
||||||
|
// el.style.cursor = 'move'
|
||||||
|
// el.onmousedown = function (e) {
|
||||||
|
// const disX = e.clientX - el.offsetLeft
|
||||||
|
// const disY = e.clientY - el.offsetTop
|
||||||
|
// document.onmousemove = function (e) {
|
||||||
|
// const left = e.clientX - disX
|
||||||
|
// const top= e.clientY - disY
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// 首次向元素添加可拖动配置 | Add draggable configuration to element for the first time
|
||||||
|
const mountedHook = (el, binding) => {
|
||||||
|
console.log(el, binding)
|
||||||
|
const value = binding.value || {}
|
||||||
|
const handleSelector = value instanceof Object ? value.el : value // 获取元素
|
||||||
|
const isOpen = value instanceof Object ? value.open || true : true // 是否开启拖拽 默认:开启
|
||||||
|
const handleArray = [] // 拖拽元素
|
||||||
|
if (!isOpen) return false // 没有开启不加载后面的代码
|
||||||
|
let axis
|
||||||
|
// Store all the DOM elements that will be used as handles.
|
||||||
|
// They can be declared using a string with a CSS tag, class or id, or using Vue refs.
|
||||||
|
if (!!handleSelector) {
|
||||||
|
if (handleSelector instanceof HTMLElement) {
|
||||||
|
handleArray.push(handleSelector);
|
||||||
|
} else {
|
||||||
|
// handleArray.push(document.querySelectorAll(handleSelector));
|
||||||
|
document.querySelectorAll(handleSelector).forEach((child) => {
|
||||||
|
handleArray.push(child);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (handleArray.length !== 0) {
|
||||||
|
// Define move element and apply CSS class
|
||||||
|
// el.classList.add(window.data.class.usesHandle);
|
||||||
|
|
||||||
|
handleArray.forEach((grabElement) => {
|
||||||
|
// Apply CSS class to each grab element
|
||||||
|
// grabElement.classList.add(window.data.class.handle);
|
||||||
|
|
||||||
|
// Add events to start drag with handle
|
||||||
|
grabElement.onmousedown = (e) => utils.dragStart(grabElement, el, axis, e);
|
||||||
|
grabElement.ontouchstart = (e) => utils.dragStart(grabElement, el, axis, e);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Add events to start drag without handle
|
||||||
|
el.onmousedown = (e) => utils.dragStart(el, el, axis, e);
|
||||||
|
el.ontouchstart = (e) => utils.dragStart(el, el, axis, e);
|
||||||
|
}
|
||||||
|
// Vue event on setup
|
||||||
|
utils.vueDragEvent(el, 'setup')
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
// Hooks for Vue3
|
||||||
|
mounted(el, binding) {
|
||||||
|
mountedHook(el, binding)
|
||||||
|
},
|
||||||
|
// Hooks for Vue2
|
||||||
|
inserted(el, binding) {
|
||||||
|
mountedHook(el, binding)
|
||||||
|
},
|
||||||
|
|
||||||
|
update(el, binding){
|
||||||
|
},
|
||||||
|
updated(el, binding){
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
|
@ -175,9 +175,9 @@ const eventHandles = (type, win) => {
|
||||||
const setIgnore = (_, ignore) => {win.setIgnoreMouseEvents(ignore, {forward: true})}
|
const setIgnore = (_, ignore) => {win.setIgnoreMouseEvents(ignore, {forward: true})}
|
||||||
Remote.ipcMain.on('tool-sphere:set:ignore', setIgnore)
|
Remote.ipcMain.on('tool-sphere:set:ignore', setIgnore)
|
||||||
// 关闭窗口
|
// 关闭窗口
|
||||||
Remote.ipcMain.once('tool-sphere:close', () => { win.destroy() })
|
Remote.ipcMain.once('tool-sphere:close', () => { win&&win.destroy() })
|
||||||
// 放大监听-测试
|
// 放大监听-测试
|
||||||
Remote.ipcMain.once('maximize-window', () => {win.destroy()})
|
Remote.ipcMain.once('maximize-window', () => {win&&win.destroy()})
|
||||||
const on = {
|
const on = {
|
||||||
onClosed: () => {Remote.ipcMain.off('tool-sphere:set:ignore', setIgnore)}
|
onClosed: () => {Remote.ipcMain.off('tool-sphere:set:ignore', setIgnore)}
|
||||||
}
|
}
|
||||||
|
@ -185,8 +185,7 @@ const eventHandles = (type, win) => {
|
||||||
break}
|
break}
|
||||||
case 'open-PDF': {
|
case 'open-PDF': {
|
||||||
// 最小化窗口 minimize()
|
// 最小化窗口 minimize()
|
||||||
Remote.ipcMain.once('open-PDF:minimize', () => {win.destroy()})
|
Remote.ipcMain.once('open-PDF:minimize', () => {win&&win.destroy()})
|
||||||
win.webContents.openDevTools()
|
|
||||||
publicMethods() // 加载公共方法
|
publicMethods() // 加载公共方法
|
||||||
break}
|
break}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -2,11 +2,16 @@
|
||||||
<div class="warp-all">
|
<div class="warp-all">
|
||||||
<board-vue v-model="tabActive"></board-vue>
|
<board-vue v-model="tabActive"></board-vue>
|
||||||
<!-- 底部工具栏 -->
|
<!-- 底部工具栏 -->
|
||||||
<el-row id="test" class="tool-bottom-all" @mouseenter="mouseChange(0)" @mouseleave="mouseChange(1)">
|
<div ref="tool" class="tool-bottom-all" :style="dataPos.style"
|
||||||
<el-col :span="3" class="flex justify-center items-center">
|
@mouseenter="mouseChange(0)" @mouseleave="mouseChange(1)">
|
||||||
<div class="c-logo"><el-image :src="logo" @click="tabChange('close')" /></div>
|
<div @mousedown="e => dargHandle(e,'down')"
|
||||||
</el-col>
|
@mousemove="e => dargHandle(e,'move')"
|
||||||
<el-col :span="20">
|
@mouseup="e => dargHandle(e,'up')">
|
||||||
|
<div class="c-logo" @click="logoHandle" title="拖动 | 折叠 | 展开">
|
||||||
|
<el-image :src="logo" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tool-btns" v-show="!isFold">
|
||||||
<el-segmented class="c-btns" v-model="tabActive" :options="btnList" size="large" block
|
<el-segmented class="c-btns" v-model="tabActive" :options="btnList" size="large" block
|
||||||
@change="tabChange">
|
@change="tabChange">
|
||||||
<template #default="{item}">
|
<template #default="{item}">
|
||||||
|
@ -16,22 +21,27 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-segmented>
|
</el-segmented>
|
||||||
</el-col>
|
</div>
|
||||||
</el-row>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
// 功能说明:electron 悬浮球
|
// 功能说明:electron 悬浮球
|
||||||
import { onMounted, ref } from 'vue'
|
import { onMounted, ref, reactive } from 'vue'
|
||||||
import logo from '@root/resources/icon.png' // logo
|
import logo from '@root/resources/icon.png' // logo
|
||||||
import boardVue from './components/board.vue'
|
import boardVue from './components/board.vue' // 画板
|
||||||
|
import vDrag from '@/directive/drag'
|
||||||
|
import { tryOnUnmounted } from '@vueuse/core'
|
||||||
// const Remote = require('@electron/remote') // remote对象
|
// const Remote = require('@electron/remote') // remote对象
|
||||||
const { ipcRenderer } = require('electron')
|
const { ipcRenderer } = require('electron')
|
||||||
|
|
||||||
|
const tool = ref()
|
||||||
const tabActive = ref('select')
|
const tabActive = ref('select') // 工具栏当前选中项
|
||||||
const btnList = [
|
const isFold = ref(false) // 折叠工具栏
|
||||||
|
const isDrag = ref(false) // 开始拖拽
|
||||||
|
const dataPos = reactive({style:{}}) // 对象属性
|
||||||
|
const btnList = [ // 工具栏按钮列表
|
||||||
{ label: '选择', value: 'select', icon: 'icon-mouse' },
|
{ label: '选择', value: 'select', icon: 'icon-mouse' },
|
||||||
{ label: '画笔', value: 'brush', icon: 'icon-huabi' },
|
{ label: '画笔', value: 'brush', icon: 'icon-huabi' },
|
||||||
{ label: '板擦', value: 'eraser', icon: 'icon-xiangpica' },
|
{ label: '板擦', value: 'eraser', icon: 'icon-xiangpica' },
|
||||||
|
@ -39,7 +49,7 @@ const btnList = [
|
||||||
{ label: '聚焦', value: 'focus', icon: 'icon-jujiao' },
|
{ label: '聚焦', value: 'focus', icon: 'icon-jujiao' },
|
||||||
{ label: '更多', value: 'more', icon: 'icon-xiazai9' },
|
{ label: '更多', value: 'more', icon: 'icon-xiazai9' },
|
||||||
]
|
]
|
||||||
|
let offsetX = 0, offsetY = 0, dragtime = 0
|
||||||
// ==== 方法 ===
|
// ==== 方法 ===
|
||||||
const tabChange = (val) => { // 切换tab-change
|
const tabChange = (val) => { // 切换tab-change
|
||||||
switch (val) {
|
switch (val) {
|
||||||
|
@ -60,6 +70,48 @@ const tabChange = (val) => { // 切换tab-change
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const logoHandle = (e,t) => { // logo 点击-事件 折叠|展开
|
||||||
|
if (Date.now() - dragtime < 200) {
|
||||||
|
isFold.value = !isFold.value
|
||||||
|
}
|
||||||
|
console.log('click', isDrag.value)
|
||||||
|
}
|
||||||
|
const dargHandle = (e, type) => { // 拖拽处理
|
||||||
|
e.preventDefault(); // 阻止默认的拖拽行为
|
||||||
|
if (type == 'down') {
|
||||||
|
dragtime = Date.now()
|
||||||
|
return isDrag.value = true
|
||||||
|
} else if (type == 'up') {
|
||||||
|
return isDrag.value = false
|
||||||
|
} else {
|
||||||
|
if (!isDrag.value) return false
|
||||||
|
if (!e.clientX&&!e.clientY){ // 最后一次松开坐标为0
|
||||||
|
offsetX = 0
|
||||||
|
offsetY = 0
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!offsetX&&!offsetY) { // 第一次, 获取元素坐标
|
||||||
|
setStyle()
|
||||||
|
} else {
|
||||||
|
const x = e.clientX - offsetX
|
||||||
|
const y = e.clientY - offsetY
|
||||||
|
setStyle(x, y)
|
||||||
|
}
|
||||||
|
offsetX = e.clientX
|
||||||
|
offsetY = e.clientY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const setStyle = (x, y) => { // 拖拽-设置值
|
||||||
|
if (offsetX && offsetY) { // 有值
|
||||||
|
const {left, top} = dataPos.style
|
||||||
|
const ox = parseInt(left.replace('px',''))
|
||||||
|
const oy = parseInt(top.replace('px',''))
|
||||||
|
dataPos.style = {...dataPos.style, left: ox + x + 'px', top: oy + y + 'px'}
|
||||||
|
} else { // 初始值
|
||||||
|
const {left, top} = tool.value.getBoundingClientRect() // 获取元素位置
|
||||||
|
dataPos.style = {bottom: 'unset', transform:'unset', left: left+'px', top: top+'px'}
|
||||||
|
}
|
||||||
|
}
|
||||||
const mouseChange = (bool) => { // 鼠标移入工具栏 是否穿透
|
const mouseChange = (bool) => { // 鼠标移入工具栏 是否穿透
|
||||||
let resBool = false
|
let resBool = false
|
||||||
if (tabActive.value == 'select') resBool = !!bool
|
if (tabActive.value == 'select') resBool = !!bool
|
||||||
|
@ -73,7 +125,8 @@ const mouseChange = (bool) => { // 鼠标移入工具栏 是否穿透
|
||||||
}
|
}
|
||||||
// 底部工具栏
|
// 底部工具栏
|
||||||
.tool-bottom-all{
|
.tool-bottom-all{
|
||||||
width: 45vw;
|
// width: 45vw;
|
||||||
|
display: flex;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 3em;
|
bottom: 3em;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
|
@ -88,9 +141,11 @@ const mouseChange = (bool) => { // 鼠标移入工具栏 是否穿透
|
||||||
height: 5rem;
|
height: 5rem;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
box-shadow: 0px 0px 8px rgb(0 0 0 / 40%);
|
box-shadow: 0px 0px 8px rgb(0 0 0 / 40%);
|
||||||
position: absolute;
|
// &:hover{
|
||||||
left: 0;
|
// .el-image{transform: scale(1.1);}
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
.tool-btns{margin: 0 35px 0 7px;}
|
||||||
.c-btn{
|
.c-btn{
|
||||||
i{font-size: 2rem;}
|
i{font-size: 2rem;}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue