Skip to content

Commit

Permalink
feat: 加上MeDialog
Browse files Browse the repository at this point in the history
  • Loading branch information
yuntian001 committed Jan 6, 2023
1 parent fda52b3 commit e3a5ebd
Show file tree
Hide file tree
Showing 6 changed files with 269 additions and 2 deletions.
178 changes: 178 additions & 0 deletions src/components/meDialog/hooks/minMax.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
//扩展 el-dailog 最大化最小化可移动
export default (el: HTMLDivElement & { fullscreen: boolean }) => {
console.log(222);
if (el.fullscreen !== undefined) {
console.log(111);
return;
}
//初始化不最大化
const resizeEvent = new CustomEvent('drag-resize', { detail: '尺寸变化', bubbles: false });
el.fullscreen = false;
//当前宽高
let nowWidth = el.clientWidth;
let nowHight = el.clientHeight;
//弹框可拉伸最小宽高
const minWidth = Math.min(nowWidth, 300);
const minHeight = Math.min(nowHight, 300);
//当前顶部高度
let nowMarginTop = '0';
//获取弹框头部(这部分可双击全屏)
const dialogHeaderEl = el.querySelector('.el-dialog__header') as HTMLDivElement;
let hasSetBodyHight = false;
//弹窗
const dragDom = el;
dragDom.className += ' el-drag-dialog';
//清除选择头部文字效果
dialogHeaderEl.onselectstart = () => false;
//头部加上可拖动cursor
dialogHeaderEl.style.cursor = 'move';

// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
const sty = window.getComputedStyle(dragDom, null);

//头部插入最大化最小化元素
const fullscreenSvg =
'<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" data-v-029747aa=""><path fill="currentColor" d="m160 96.064 192 .192a32 32 0 0 1 0 64l-192-.192V352a32 32 0 0 1-64 0V96h64v.064zm0 831.872V928H96V672a32 32 0 1 1 64 0v191.936l192-.192a32 32 0 1 1 0 64l-192 .192zM864 96.064V96h64v256a32 32 0 1 1-64 0V160.064l-192 .192a32 32 0 1 1 0-64l192-.192zm0 831.872-192-.192a32 32 0 0 1 0-64l192 .192V672a32 32 0 1 1 64 0v256h-64v-.064z"></path></svg>';
const cropSvg =
'<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" data-v-029747aa=""><path fill="currentColor" d="M256 768h672a32 32 0 1 1 0 64H224a32 32 0 0 1-32-32V96a32 32 0 0 1 64 0v672z"></path><path fill="currentColor" d="M832 224v704a32 32 0 1 1-64 0V256H96a32 32 0 0 1 0-64h704a32 32 0 0 1 32 32z"></path></svg>';
const maxMinButton = document.createElement('button');
maxMinButton.className = 'el-dialog__headerbtn';
maxMinButton.style.color = 'var(--el-color-info)';
maxMinButton.onmouseover = function () {
//设置其背景颜色为黄色
maxMinButton.style.color = 'var(--el-color-primary)';
};
maxMinButton.onmouseout = function (e) {
//设置其背景颜色为黄色
maxMinButton.style.color = 'var(--el-color-info)';
};
if (dialogHeaderEl.querySelector('.el-dialog__close')) {
maxMinButton.style.right = dialogHeaderEl.querySelector('.el-dialog__close')!.parentElement!.clientWidth + 'px';
}
const maxMin = document.createElement('i');
maxMinButton.appendChild(maxMin);
maxMin.style.fontSize = 'inherit';
maxMin.className = 'el-icon';
maxMin.innerHTML = el.fullscreen ? cropSvg : fullscreenSvg;
dialogHeaderEl.appendChild(maxMinButton);
const moveDown = (e: MouseEvent) => {
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX ?? 0 - dialogHeaderEl.offsetLeft;
const disY = e.clientY ?? 0 - dialogHeaderEl.offsetTop;

// 获取到的值带px 正则匹配替换
let styL: number, styT: number;

// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
if (sty.left.includes('%')) {
styL = +document.body.clientWidth * (+sty.left.replace(/%/g, '') / 100);
styT = +document.body.clientHeight * (+sty.top.replace(/%/g, '') / 100);
} else {
styL = +sty.left.replace(/\px/g, '');
styT = +sty.top.replace(/\px/g, '');
}
document.onmousemove = function (e) {
// 通过事件委托,计算移动的距离
const l = e.clientX - disX;
const t = e.clientY - disY;

// 移动当前元素
dragDom.style.left = `${l + styL}px`;
dragDom.style.top = `${t + styT}px`;

//将此时的位置传出去
//binding.value({x:e.pageX,y:e.pageY})
};

document.onmouseup = function (e) {
document.onmousemove = null;
document.onmouseup = null;
};
};
dialogHeaderEl.onmousedown = moveDown;
let bodyHeight = 'auto';
const setMaxMin = () => {
if (el.fullscreen) {
maxMin.innerHTML = fullscreenSvg;
dragDom.style.height = 'auto';
dragDom.style.width = nowWidth + 'px';
dragDom.style.marginTop = nowMarginTop;
dragDom.style.position = 'relative';
el.fullscreen = false;
dialogHeaderEl.style.cursor = 'move';
dialogHeaderEl.onmousedown = moveDown;
(dragDom.querySelector('.el-dialog__body') as HTMLDivElement).style.height = bodyHeight;
hasSetBodyHight = false;
} else {
maxMin.innerHTML = cropSvg;
bodyHeight = (dragDom.querySelector('.el-dialog__body') as HTMLDivElement).offsetHeight + 'px';
nowHight = dragDom.clientHeight;
nowWidth = dragDom.clientWidth;
nowMarginTop = dragDom.style.marginTop;
dragDom.style.left = '0';
dragDom.style.top = '0';
dragDom.style.height = '100vh';
dragDom.style.width = '100vw';
dragDom.style.marginTop = '0';
dragDom.style.position = 'fixed';
el.fullscreen = true;
dialogHeaderEl.style.cursor = 'initial';
dialogHeaderEl.onmousedown = null;
if (!hasSetBodyHight) {
const footerHeight =
dragDom.querySelector('.el-dialog__footer') &&
(dragDom.querySelector('.el-dialog__footer') as HTMLDivElement).offsetHeight;
(dragDom.querySelector('.el-dialog__body') as HTMLDivElement).style.height =
'calc(100% - ' + (dialogHeaderEl.offsetHeight + footerHeight!) + 'px)';
hasSetBodyHight = true;
}
}
el.dispatchEvent(resizeEvent);
};

//点击放大缩小效果
maxMinButton.onclick = setMaxMin;
//双击头部效果
dialogHeaderEl.ondblclick = setMaxMin;
//拉伸
const resizeEl = document.createElement('div');
dragDom.appendChild(resizeEl);
//在弹窗右下角加上一个10-10px的控制块
resizeEl.style.cursor = 'se-resize';
resizeEl.style.position = 'absolute';
resizeEl.style.height = '10px';
resizeEl.style.width = '10px';
resizeEl.style.right = '0px';
resizeEl.style.bottom = '0px';
//鼠标拉伸弹窗
resizeEl.onmousedown = (e) => {
// 记录初始x位置
const clientX = e.clientX;
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - resizeEl.offsetLeft;
const disY = e.clientY - resizeEl.offsetTop;
document.onmousemove = function (e) {
e.preventDefault(); // 移动时禁用默认事件
// 通过事件委托,计算移动的距离
const x = e.clientX - disX + (e.clientX - clientX); //这里 由于elementUI的dialog控制居中的,所以水平拉伸效果是双倍
const y = e.clientY - disY;
//比较是否小于最小宽高
dragDom.style.width = x > minWidth ? `${x}px` : minWidth + 'px';
dragDom.style.height = y > minHeight ? `${y}px` : minHeight + 'px';
if (!hasSetBodyHight) {
const footerHeight =
dragDom.querySelector('.el-dialog__footer') &&
(dragDom.querySelector('.el-dialog__footer') as HTMLDivElement).offsetHeight;
(dragDom.querySelector('.el-dialog__body') as HTMLDivElement).style.height =
'calc(100% - ' + (dialogHeaderEl.offsetHeight + footerHeight!) + 'px)';
hasSetBodyHight = true;
}
};
//拉伸结束
document.onmouseup = function (e) {
document.onmousemove = null;
document.onmouseup = null;
el.dispatchEvent(resizeEvent);
};
};
};
57 changes: 57 additions & 0 deletions src/components/meDialog/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<template>
<el-dialog ref="elDialogRef" class="me-dialog">
<template v-for="(item, key) in $slots" :key="key" #[key]>
<component :is="item"></component>
</template>
</el-dialog>
</template>
<script lang="ts">
import { ElDialog } from 'element-plus';
import { ComponentOptionsMixin, ExtractPropTypes, Ref } from 'vue';
import minMax from './hooks/minMax';
const props = {
full: {
type: Boolean,
default: true,
},
};
export default defineComponent<
ComponentProps<typeof ElDialog> & Partial<ExtractPropTypes<typeof props>>,
Record<string, any>,
Record<string, any>,
Record<string, any>,
Record<string, any>,
ComponentOptionsMixin,
ComponentOptionsMixin,
Record<string, never>
>({
name: 'MeDialog',
props: props as any,
setup(props) {
const elDialogRef = ref<InstanceType<typeof ElDialog>>();
watch(
[() => elDialogRef.value?.dialogContentRef, () => props.full],
async () => {
if (elDialogRef.value?.dialogContentRef && props.full) {
await nextTick();
minMax(elDialogRef.value!.dialogContentRef.$el);
}
},
{ immediate: true },
);
return {
elDialogRef,
};
},
created() {
console.log(this);
},
});
</script>
<style lang="scss">
.me-dialog {
.el-dialog__headerbtn {
width: 40px;
}
}
</style>
2 changes: 1 addition & 1 deletion src/layout/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<el-main class="right-main">
<el-scrollbar view-class="me-right-main-view">
<layout-header v-if="!themeConfig.fixedHeader"></layout-header>
<div class="me-main" id="me-main">
<div id="me-main" class="me-main">
<layout-page :transition="{ name: 'fade-transform', mode: 'out-in' }"></layout-page>
</div>
</el-scrollbar>
Expand Down
8 changes: 8 additions & 0 deletions src/router/routes/components/5-dialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { RouteRecordRaw } from 'vue-router';
export const routes: RouteRecordRaw[] = [
{
path: 'dialog',
component: () => import('@/views/components/dialog.vue'),
meta: { title: '弹窗' },
},
];
24 changes: 24 additions & 0 deletions src/views/components/dialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<template>
<div class="dailog">
<el-button @click="show = true"> 弹窗 </el-button>
<me-dialog ref="dailog" v-model="show" title="Title">
<div>content</div>
<template #footer>
<el-button @click="show = false"> 关闭 </el-button>
</template>
</me-dialog>
</div>
</template>

<script setup lang="ts" name="Dailog">
const show = ref(false);
const dailog = ref();
onMounted(() => {
console.log('dailog', dailog.value);
});
</script>

<style lang="scss" scoped>
.dailog {
}
</style>
2 changes: 1 addition & 1 deletion src/views/components/number.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div class="number">
<el-card header="数字动画">
<h1><me-number v-bind="props" v-if="has"></me-number></h1>
<h1><me-number v-if="has" v-bind="props"></me-number></h1>
<el-form label-width="150px" inline>
<el-form-item label="起始值">
<el-input-number v-model="props.start"></el-input-number>
Expand Down

0 comments on commit e3a5ebd

Please sign in to comment.