vue 悬浮窗且带自动吸附功能实现demo
作者:Skywang
这篇文章主要为大家介绍了vue 悬浮窗且带自动吸附功能实现demo,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
封装的组件代码
之前写过悬浮窗的效果,这次做了个总结,网页端和移动端都可以用兼容,封装的组件代码,可以引到页面直接使用
代码
做了简单的注释 大家自行了解
HTML
<template> <div ref="floatDrag" class="float-position" :style="{ left: left + 'px', top: top + 'px', zIndex: zIndex }" @touchmove.prevent @mousemove.prevent @mousedown="mouseDown" @mouseup="mouseUp" > <div id="side-windows"> <div class="shrink"> <div class="problem-feedback" @click.stop="showDialog()"> <img :src="feedback" alt="" /> <p>问题<br />反馈</p> </div> </div> </div> </div> </template>
JS
<script> export default { name: "DragBall", props: { distanceRight: { // 初始化定位 type: Number, default: 0 }, distanceBottom: { // 初始化定位 type: Number, default: 100 }, isScrollHidden: { //滚动是否 隐藏 type: Boolean, default: false }, isCanDraggable: { //是否允许拖拽 type: Boolean, default: true }, zIndex: { // 初始化层级 type: Number, default: 50 }, value: { type: String, default: "悬浮!" } }, //data 域 data() { return { clientWidth: null, clientHeight: null, left: 0, top: 0, timer: null, currentTop: 0, mousedownX: 0, mousedownY: 0, feedback: require('') // 问题 }; }, created() { this.clientWidth = document.documentElement.clientWidth; this.clientHeight = document.documentElement.clientHeight; }, mounted() { this.isCanDraggable && this.$nextTick(() => { this.floatDrag = this.$refs.floatDrag; // 获取元素位置属性 this.floatDragDom = this.floatDrag.getBoundingClientRect(); // 设置初始位置 this.left = this.clientWidth - this.floatDragDom.width - this.distanceRight; this.top = this.clientHeight - this.floatDragDom.height - this.distanceBottom; this.initDraggable(); }); this.isScrollHidden && window.addEventListener("scroll", this.handleScroll); window.addEventListener("resize", this.handleResize); }, methods: { showDialog() { let url window.open(url, '_blank') }, /** * 设置滚动时隐藏悬浮按钮,停止时显示 */ handleScroll() { this.timer && clearTimeout(this.timer); this.timer = setTimeout(() => { this.handleScrollEnd(); }, 200); this.currentTop = document.documentElement.scrollTop || document.body.scrollTop; if (this.left > this.clientWidth / 2) { // 判断元素位置再左侧还是右侧 this.left = this.clientWidth + this.floatDragDom.width; } else { this.left = -this.floatDragDom.width; } }, /** * 滚动结束 */ handleScrollEnd() { let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; if (scrollTop === this.currentTop) { console.log(this.left); if (this.left > this.clientWidth / 2) { // 判断元素位置 this.left = this.clientWidth - this.floatDragDom.width; } else { this.left = 0; } clearTimeout(this.timer); } }, /** * 窗口监听 */ handleResize() { this.clientWidth = document.documentElement.clientWidth; this.clientHeight = document.documentElement.clientHeight; this.checkDraggablePosition(); }, /** * 初始化 */ initDraggable() { this.floatDrag.addEventListener("touchstart", this.toucheStart); this.floatDrag.addEventListener("touchmove", e => this.touchMove(e)); this.floatDrag.addEventListener("touchend", this.touchEnd); }, mouseDown(e) { const event = e || window.event; this.mousedownX = event.screenX; this.mousedownY = event.screenY; const that = this; let floatDragWidth = this.floatDragDom.width / 2; let floatDragHeight = this.floatDragDom.height / 2; if (event.preventDefault) { event.preventDefault(); } this.canClick = false; this.floatDrag.style.transition = "none"; setTimeout(() => { document.onmousemove = function(e) { var event = e || window.event; that.left = event.clientX - floatDragWidth; that.top = event.clientY - floatDragHeight; if (that.left < 0) that.left = 0; if (that.top < 0) that.top = 0; if (that.left >= that.clientWidth - floatDragWidth * 2) { that.left = that.clientWidth - floatDragWidth * 2; } if (that.top >= that.clientHeight - floatDragHeight * 2) { that.top = that.clientHeight - floatDragHeight * 2; } // 解决鼠标移出窗口 松开鼠标后 回到窗口内 悬浮继续跟随问题 if(event.clientX<=0 || event.clientY<=0 || event.clientY>= that.clientHeight || event.clientX>= that.clientWidth){ that.mouseUp(event) } }; }, 20); }, mouseUp(e) { const event = e || window.event; //判断只是单纯的点击,没有拖拽 if ( this.mousedownY == event.screenY && this.mousedownX == event.screenX ) { this.$emit("handlepaly"); } document.onmousemove = null; this.checkDraggablePosition(); this.floatDrag.style.transition = "all 0.3s"; }, toucheStart() { this.canClick = false; this.floatDrag.style.transition = "none"; }, touchMove(e) { this.canClick = true; if (e.targetTouches.length === 1) { let touch = event.targetTouches[0]; this.left = touch.clientX - this.floatDragDom.width / 2; this.top = touch.clientY - this.floatDragDom.height / 2; } }, touchEnd() { if (!this.canClick) return; // 解决点击事件和touch事件冲突的问题 this.floatDrag.style.transition = "all 0.3s"; this.checkDraggablePosition(); }, /** * 判断元素显示位置 * 在窗口改变和move end时调用 */ checkDraggablePosition() { let details = document.querySelector('.details') if (this.left + this.floatDragDom.width / 2 >= this.clientWidth / 2) { // 判断位置是往左往右滑动 this.left = this.clientWidth - this.floatDragDom.width; details.style.right = '56px' } else { this.left = 0; details.style.right = '-233px' } if (this.top < 0) { // 判断是否超出屏幕上沿 this.top = 0; } if (this.top + this.floatDragDom.height >= this.clientHeight) { // 判断是否超出屏幕下沿 this.top = this.clientHeight - this.floatDragDom.height; } } }, beforeDestroy() { window.removeEventListener("scroll", this.handleScroll); window.removeEventListener("resize", this.handleResize); } }; </script>
样式
<style lang="less" scoped> .float-position{ font-size: 12px; position: fixed; z-index: 500!important; right: 0; top: 50%; width: 48px; height: 168px; display: flex; align-items: center; justify-content: center; user-select: none; } </style>
以上就是vue 悬浮窗且带自动吸附功能实现demo的详细内容,更多关于vue 悬浮窗自动吸附的资料请关注脚本之家其它相关文章!