一直都想实现类似于五百丁中简历填写中模块跟随鼠标移动的组件,最近闲来无事,自己琢磨实现了一个差不多的组件。
其中每个模块都是组件调入(项目经验、教育经验、工作经验等),所以这里也用到了动态加载组件方式。
思路:鼠标移入模块,显示相应模块的点击移动按钮,点击A模块移动按钮,此时原先A模块所在的位置上变为拖动到这里绿框模块,同时鼠标下悬浮着A模块,鼠标移动,悬浮的A模块跟随移动,绿框也跟随上下移动。
父组件
1、父组件template中的代码
<div class="component-box" ref="compBox"> <component v-for="(item, index) in comRoute" :is="item" :key="index" @getData="getData"> </component> <div :class="['translate-box', {'move-icon':transType}]" ref="translateBox" v-if="transType"> <component :is="transCom"></component> </div> </div>
2、data中定义的属性
comList: ['educationExp', 'workExp', 'projectExp'], // 模块列表 comLen: 0, // 模块的长度 comType: '', // 当前移动的模块 transType: '', // 当前移动的模块 coordinate: { // 鼠标坐标 mouseX: 0, mouseY: 0, }, downFlag: false, // 当前是否点击模块移动 mouseYBefore: 0, // 记录鼠标点击时Y坐标以及鼠标每移动30后重新记录鼠标Y坐标 mouseYLast: 0, // 实时记录鼠标移动时的Y坐标 nowCom: '', // 移动模块时,上一个模块或者下一个模块的名称 forFlage: false, // forEach遍历结束的标识 comRoute: [], // 动态加载组件列表 transCom: null, // 点击后悬浮的组件 compBox: null, // 获取当前组件在页面中的位置信息
3、scrollTop为页面滚动的距顶部的距离,从父组件传过来
props: { scrollTop: Number,}
4、watch一些属性
watch: { comList: { handler(val) { this.getCom(val); // 模块列表改变时,实时加载组件 }, deep: true, immediate: true, // 声明了之后会立马执行handler里面的函数 }, transType(val) { // 悬浮模块加载组件 if (val) { this.transCom = () => import(`./default/${val}`); } }, scrollTop: { // 监听页面滚动 handler() {}, immediate: true, }, comType(newVal) { if (newVal) { this.comList.forEach((item, index) => { if (item === newVal) { this.comList[index] = 'moveBox'; // 将组建列表中为comType的元素改为moveBox组件 } }); this.getCom(this.comList); } }, downFlag(newVal) { // 鼠标已经点击 const nowThis = this; document.onmousemove = function (e) { if (newVal) { // 鼠标移动赋值 nowThis.coordinate.mouseX = e.clientX; nowThis.coordinate.mouseY = e.clientY; } }; document.onmouseup = function () { // 鼠标松开 document.onmousemove = null; if (newVal) { nowThis.transType = ''; // 悬浮组件置空 nowThis.comList.forEach((item, index) => { if (item === 'moveBox') { // 寻找moveBox所在位置 nowThis.comList[index] = nowThis.comType; // 还原成点击组件 } }); nowThis.downFlag = false; nowThis.comType = ''; nowThis.getCom(nowThis.comList); } }; }, coordinate: { handler(newVal) { // 悬浮组件位置 this.$refs.translateBox.style.top = `${newVal.mouseY + this.scrollTop - 40 - this.compBox.y}px`; this.$refs.translateBox.style.left = `${newVal.mouseX - this.compBox.x - 200}px`; this.mouseYLast = newVal.mouseY; }, deep: true, }, mouseYLast(newVal) { // 鼠标移动Y坐标 this.forFlage = false; if (newVal - this.mouseYBefore > 30) { // 移动30鼠标向下移,每移动30,moveBox移动一次 this.comList.forEach((item, index) => { if (item === 'moveBox' && index < this.comLen - 1 && !this.forFlage) { this.nowCom = this.comList[index + 1]; this.$set(this.comList, index + 1, 'moveBox'); this.$set(this.comList, index, this.nowCom); this.mouseYBefore = newVal; this.forFlage = true; } }); } else if (newVal - this.mouseYBefore < -30) { // 鼠标向上移 this.comList.forEach((item, index) => { if (item === 'moveBox' && index > 0 && !this.forFlage) { this.nowCom = this.comList[index - 1]; // this.comList[index - 1] = 'moveBox'; // this.comList[index] = this.nowCom; // this.comList[index]数组中采用这种方式赋值,vue是不能检测到数组的变动的 this.$set(this.comList, index - 1, 'moveBox'); this.$set(this.comList, index, this.nowCom); this.mouseYBefore = newVal; this.forFlage = true; } }); } }, },
其中 forFlage的作用是,在forEach中不能使用break这样来结束循环,所以用forFlage来表示,当遍历到moveBox后, 就结束遍历
5、methods
methods: { getCom(val) { this.comRoute = []; val.forEach((item) => { this.comRoute.push(() => import(`./default/${item}`)); }); }, getData(data, dataY, dataX) { // 模块组件点击后,父组件中调用此方法,并传值过来 this.comType = data; this.transType = data; // 目前考虑点击后立即移动,点击不移动的情况后期再考虑 this.downFlag = true; this.mouseYBefore = dataY; this.$nextTick(() => { this.$refs.translateBox.style.top = `${dataY + this.scrollTop - 40 - this.compBox.y}px`; this.$refs.translateBox.style.left = `${dataX - this.compBox.x - 200}px`; }); }, },
6、mounted
mounted() { this.comLen = this.comList.length; this.compBox = this.$refs.compBox.getBoundingClientRect(); const that = this; window.onresize = () => (() => { that.compBox = this.$refs.compBox.getBoundingClientRect(); })(); },
子组件
1、子组件template代码
<div class="pad-box hover-box name-box"> <p class="absolute-box"> <i class="el-icon-rank operation-icon move-icon" @mousedown="mouseDown"></i> <i class="el-icon-circle-plus operation-icon"></i> <i class="el-icon-s-tools operation-icon"></i> </p> 教育经验 </div>
2、script
export default { name: 'educationExp', data() { return { comType: 'educationExp', mouseYBefore: 0, mouseXBefore: 0, }; }, methods: { mouseDown(e) { this.mouseYBefore = e.clientY; this.mouseXBefore = e.clientX; this.$emit('getData', this.comType, this.mouseYBefore, this.mouseXBefore); }, }, };
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]