vue2中实现一个悬浮球点击可以展开/收取,可拖拽到页面的任何位置。 您所在的位置:网站首页 ios14的视频悬浮窗哪些可以用的 vue2中实现一个悬浮球点击可以展开/收取,可拖拽到页面的任何位置。

vue2中实现一个悬浮球点击可以展开/收取,可拖拽到页面的任何位置。

2024-07-15 06:24| 来源: 网络整理| 查看: 265

效果如图: 在这里插入图片描述 在这里插入图片描述 整体的悬浮球组件代码如下:感兴趣的朋友可以试试。

展开 收起 {{ item.label }} export default { name: 'DragBall', props: { distanceRight: { type: Number, default: 36, }, distanceBottom: { type: Number, default: 700, }, isScrollHidden: { type: Boolean, default: false, }, isCanDraggable: { type: Boolean, default: true, }, zIndex: { type: Number, default: 50, }, value: { type: String, default: '悬浮球!', }, }, data() { return { clientWidth: null, clientHeight: null, left: null, top: null, right: null, timer: null, currentTop: 0, mousedownX: 0, mousedownY: 0, flag: true, // 控制悬浮框是否展开 box: '', // 悬浮球的dom activeIndex: 0, //高亮显示 powerList: [ { path: require('../../../../assets/image/lianjie.png'), label: '连接CTI' }, { path: require('../../../../assets/image/checkIn.png'), label: '签入' }, { path: require('../../../../assets/image/checkOut.png'), label: '签出' }, { path: require('../../../../assets/image/kongxian.png'), label: '置闲' }, { path: require('../../../../assets/image/manglu.png'), label: '置忙' }, { path: require('../../../../assets/image/bohao.png'), label: '拨号' }, { path: require('../../../../assets/image/zixun.png'), label: '咨询' }, { path: require('../../../../assets/image/baochi.png'), label: '保持' }, { path: require('../../../../assets/image/huifu.png'), label: '恢复' }, ] }; }, 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.right = 0; this.top = this.clientHeight - this.floatDragDom.height - this.distanceBottom; this.initDraggable(); }); // this.isScrollHidden && window.addEventListener('scroll', this.handleScroll); window.addEventListener('resize', this.handleResize); this.box = document.getElementById("float-box") }, beforeUnmount() { window.removeEventListener('scroll', this.handleScroll); window.removeEventListener('resize', this.handleResize); }, methods: { // 伸缩悬浮球 handelFlex() { if (this.flag) { this.buffer(this.box, "height", 700); } else { this.buffer(this.box, "height", 70); } this.flag = !this.flag console.log('是否展开', this.flag) }, // 点击哪个power activeHandle(index) { //把我们自定义的下标赋值 this.activeIndex = index console.log('HHHH', index) }, // 获取要改变得样式属性 getStyleAttr(obj, attr) { if (obj.currentStyle) { // IE 和 opera return obj.currentStyle[attr]; } else { return window.getComputedStyle(obj, null)[attr]; } }, // 动画函数 buffer(eleObj, attr, target) { // setInterval方式开启动画 //先清后设 // clearInterval(eleObj.timer); // let speed = 0 // let begin = 0 // //设置定时器 // eleObj.timer = setInterval(() => { // //获取动画属性的初始值 // begin = parseInt(this.getStyleAttr(eleObj, attr)); // speed = (target - begin) * 0.2; // speed = target > begin ? Math.ceil(speed) : Math.floor(speed); // eleObj.style[attr] = begin + speed + "px"; // if (begin === target) { // clearInterval(eleObj.timer); // } // }, 20); // cancelAnimationFrame开启动画 // 先清后设 cancelAnimationFrame(eleObj.timer) let speed = 0 let begin = 0 let _this = this eleObj.timer = requestAnimationFrame(function fn() { begin = parseInt(_this.getStyleAttr(eleObj, attr)) // 动画速度 speed = (target - begin) * 0.9 speed = target > begin ? Math.ceil(speed) : Math.floor(speed) eleObj.style[attr] = begin + speed + "px" eleObj.timer = requestAnimationFrame(fn) if (begin === target) { cancelAnimationFrame(eleObj.timer); } }) }, /** * 窗口resize监听 */ handleResize() { // this.clientWidth = document.documentElement.clientWidth; // this.clientHeight = document.documentElement.clientHeight; // console.log(window.innerWidth); // console.log(document.documentElement.clientWidth); this.checkDraggablePosition(); }, /** * 初始化draggable */ 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'; document.onmousemove = function (e) { var event = e || window.event; that.left = event.clientX - floatDragWidth; that.top = event.clientY - floatDragHeight; if (that.left that.left = document.documentElement.clientWidth - floatDragWidth * 2; } if (that.top >= that.clientHeight - floatDragHeight * 2) { that.top = that.clientHeight - floatDragHeight * 2; } }; }, 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() { this.clientWidth = document.documentElement.clientWidth; this.clientHeight = document.documentElement.clientHeight; if (this.left + this.floatDragDom.width / 2 >= this.clientWidth / 2) { // 判断位置是往左往右滑动 this.left = this.clientWidth - this.floatDragDom.width; } else { this.left = 0; } if (this.top // 判断是否超出屏幕下沿 this.top = this.clientHeight - this.floatDragDom.height; } }, }, }; html, body { overflow: hidden; } .float-position { position: fixed; z-index: 10003 !important; left: 0; top: 20%; width: 70px; height: 70px; border-radius: 32px; // background: rgba(167, 160, 161, .5); cursor: pointer; overflow: hidden; user-select: none; display: block; background: black; // border-radius: 50%; margin: 0; background: -webkit-radial-gradient(100px 100px, circle, #35a1a1, #000); background: -moz-radial-gradient(100px 100px, circle, #35a1a1, #000); background: radial-gradient(100px 100px, circle, #35a1a1, #000); .drag { width: 70px; height: 35px; // background: #f2e96a; text-align: center; line-height: 35px; border-bottom: 1px solid #fff; } .content { width: 70px; height: 35px; // background: #716af2; .label { width: 70px; height: 35px; text-align: center; line-height: 35px; color: white; } .label:hover { color: rgb(243, 82, 19); transition: all 0.5; } .item-container { margin-top: 10px; width: 70px; height: 600px; display: flex; justify-content: space-between; align-items: center; flex-direction: column; .power-item { width: 40px; height: 40px; border-radius: 50%; background-color: #69707a; display: flex; justify-content: center; align-items: center; flex-direction: column; } .des { width: 40px; text-align: center; margin-bottom: 5px; font-size: 10px; color: #fff; } } } .close { width: 20px; height: 20px; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #fff; background: rgba(0, 0, 0, 0.6); position: absolute; right: -10px; top: -12px; cursor: pointer; } } .cart { border-radius: 50%; width: 5em; height: 5em; display: flex; align-items: center; justify-content: center; } .header-notice { display: inline-block; transition: all 0.3s; span { vertical-align: initial; } .notice-badge { color: inherit; .header-notice-icon { font-size: 16px; padding: 4px; } } } .drag-ball .drag-content { overflow-wrap: break-word; font-size: 14px; color: #fff; letter-spacing: 2px; } .active { background-color: #1a1818 !important; } .active-des { color: #1a1818 !important; font-weight: bold !important; }

用的话直接引入就行了比如这样:

export default { components: { floatButton: () => import("../components/floatButton"), //异步组件加载方式 },

接下来介绍一下实现的几个核心要点吧: 1. 样式,让小球看起来有立体感 主要就是设置盒子阴影,主要代码如下

.float-position{ position: fixed; z-index: 10003 !important; left: 0; top: 20%; width: 70px; height: 70px; border-radius: 32px; cursor: pointer; overflow: hidden; user-select: none; // 设置盒子阴影 让小球有立体感 display: block; background: black; margin: 0; background: -webkit-radial-gradient(100px 100px, circle, #35a1a1, #000); background: -moz-radial-gradient(100px 100px, circle, #35a1a1, #000); background: radial-gradient(100px 100px, circle, #35a1a1, #000); }

2. 小球的拖拽功能,可以拖拽到屏幕的任意位置 这个主要是参考这位大佬的,写的非常好,我是直接拿来就用了。地址在下方 悬浮球拖拽功能 3. 小球的展开与收起动画效果 我开始想的是用vue中给我们提供的过度组件实现,由于自己是菜鸡不熟悉这块东西,懒得看文档了,就自己写了个动画函数,用dom操作实现了动画,具体代码如下。

展开 收起 暂时站位哈哈哈哈哈哈或 data(){ return { box: '', //悬浮球盒子 flag: true, // 控制小球展开和收起的阀门 } }, mounted() { this.box = document.getElementById("float-box") // 获取小球的实例 }, methods: { // 伸缩悬浮球 handelFlex() { if (this.flag) { this.buffer(this.box, "height", 700); // 改变盒子的高度为700 } else { this.buffer(this.box, "height", 70); // 改变盒子的高度70 } this.flag = !this.flag console.log('是否展开', this.flag) }, // 获取要改变得样式属性 getStyleAttr(obj, attr) { if (obj.currentStyle) { // IE 和 opera return obj.currentStyle[attr]; } else { return window.getComputedStyle(obj, null)[attr]; } }, // 动画函数 buffer(eleObj, attr, target) { // setInterval方式开启动画 //先清后设 // clearInterval(eleObj.timer); // let speed = 0 // let begin = 0 // //设置定时器 // eleObj.timer = setInterval(() => { // //获取动画属性的初始值 // begin = parseInt(this.getStyleAttr(eleObj, attr)); // speed = (target - begin) * 0.2; // speed = target > begin ? Math.ceil(speed) : Math.floor(speed); // eleObj.style[attr] = begin + speed + "px"; // if (begin === target) { // clearInterval(eleObj.timer); // } // }, 20); // cancelAnimationFrame开启动画 // 先清后设 cancelAnimationFrame(eleObj.timer) let speed = 0 let begin = 0 let _this = this eleObj.timer = requestAnimationFrame(function fn() { begin = parseInt(_this.getStyleAttr(eleObj, attr)) // 动画速度 speed = (target - begin) * 0.9 speed = target > begin ? Math.ceil(speed) : Math.floor(speed) eleObj.style[attr] = begin + speed + "px" eleObj.timer = requestAnimationFrame(fn) if (begin === target) { cancelAnimationFrame(eleObj.timer); } }) }, }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有