vue項(xiàng)目雙滑塊組件使用
vue項(xiàng)目雙滑塊組件
先看效果圖
說明
- 兩端值300,750 是可選范圍的最大值;
- 兩個(gè)按鈕上的值是已經(jīng)選擇的范圍 ;
目前灰色背景條的寬度單位是px,
上面代碼中,背景條寬度是寫死的;
下面是優(yōu)化后的代碼
<template> <div :style="{ display: 'flex', 'justify-content': 'center', width: '100%', }" > <div class="slider-box" id="slider-box" :style="{ width: '100%', background: outBg, }" @mousedown="handleClickZong" > <div :class="['slider-nei', isClick ? 'transtion' : '']" :style="{ width: Math.abs(moveDistanceOne - moveDistanceTwo) + 20 + 'px', transform: moveDistanceTwo > moveDistanceOne ? `translateX(${moveDistanceOne}px)` : `translateX(${moveDistanceTwo}px)`, background: neiBg, }" ></div> <div :style="{ transform: `translateX(${moveDistance}px)`, }" :class="{ 'point-box': true, zhua: isMove, transtion: isClick, }" v-if="!range" @mousedown.stop.prevent="handleMousedown" ></div> <div :style="{ transform: `translateX(${moveDistanceOne}px)`, background: btnBg,position:'absolute','z-index': leftIndex }" :class="{ 'point-box': true, zhua: isMove, transtion: isClick, }" v-if="range" @mousedown.stop.prevent="handleMousedownOne" @touchstart="handleMousedownOne1" @mouseup="handleUp" @touchend="handleUp" > {{ Math.trunc(moveDistanceOne * rate) + min }} </div> <div :style="{ transform: `translateX(${moveDistanceTwo}px)`, background: btnBg,position:'absolute','z-index': rightIndex }" :class="{ 'point-box': true, point: true, zhua: isMove, transtion: isClick, }" @mousedown.stop.prevent="handleMousedownTwo" @touchstart="handleMousedownTwo1" @mouseup="handleUp" @touchend="handleUp" > {{ Math.trunc(moveDistanceTwo * rate + min) }} </div> </div> </div> </template>
<script> import { mapGetters } from "vuex"; export default { data() { return { range: true, //是否開啟雙滑塊 isClick: false, //是否直接點(diǎn)擊 isMove: false, //是否處于滑動(dòng)狀態(tài) flag: false, // moveDistance: 0, initX: 0, //記錄鼠標(biāo)點(diǎn)下時(shí)的坐標(biāo),用于移動(dòng)中求差值 moveStart: 0, //進(jìn)度條的開始位置 moveEnd: 0, //進(jìn)度條的結(jié)束位置 moveDistanceOne: 0, //滑塊一的位置 moveDistanceTwo: 50, //滑塊二的位置 rate: 1, // 比率 outerWidth: 100, rate1: 1, // 比率 outerWidth1: 100, valueRange: [], leftIndex: 0, rightIndex: 0.5, }; }, computed: { // 使用對(duì)象展開運(yùn)算符將 getter 混入 computed 對(duì)象中 ...mapGetters("common", [ "userType" ]), }, props: { // 可選擇范圍的較大值 max: { type: Number, default: 750, }, // 外層背景色 outBg: { type: String, default: "#F0F0F0", }, // 滑塊背景色 btnBg: { type: String, default: "#497cfe", }, // 內(nèi)層背景色 neiBg: { type: String, default: "#E5EDFF", }, // 可選擇范圍的較小值 min: { type: Number, default: 150, }, // 已經(jīng)選擇的范圍 valuesRange: { type: Array, default: [350, 550], }, }, watch: { valuesRange: { handler(val1) { this.valueRange = val1; this.init(); }, deep: true, immediate: true, }, }, mounted() { window.addEventListener("resize", this.init); window.addEventListener("mouseup", () => { if(this.flag) { this.handleUp2(); this.flag = false; } }); // this.init(); }, methods: { init() { this.$nextTick(() => { /* this.valueRange [1, 750] */ if (this.valueRange && this.valueRange.length > 0) { let max_min = this.max - this.min; var slide_width = document.querySelector("#slider-box").clientWidth; var point_width = document.querySelector(".point").clientWidth; this.outerWidth = slide_width - point_width; this.outerWidth1 = slide_width - point_width - point_width; this.rate = max_min / this.outerWidth; this.rate1 = max_min / this.outerWidth1; let vr = JSON.parse(JSON.stringify(this.valueRange)); if(vr[0] > vr[1]) { this.valueRange = [vr[1],vr[0]]; } this.moveDistanceOne = (this.valueRange[0] - this.min) / this.rate; this.moveDistanceTwo = (this.valueRange[1] - this.min) / this.rate; this.$forceUpdate(); } }); }, //移動(dòng)端 touchstart 點(diǎn)擊監(jiān)聽 ontouchmove 移動(dòng)監(jiān)聽 ontouchend 松開監(jiān)聽,e.changedTouches[0] 元素偏移的一些數(shù)據(jù) //PC端 mousedown 點(diǎn)擊監(jiān)聽 onmousemove 移動(dòng)監(jiān)聽 onmouseup 松開監(jiān)聽 /** * 初始坐標(biāo)就是鼠標(biāo)點(diǎn)下時(shí)的clientX坐標(biāo),這樣就可以做到將slider放在頁面任何位置,拖動(dòng)原點(diǎn)偏移的量也是正確的, * 因?yàn)樵c(diǎn)移動(dòng)距離是用鼠標(biāo)移動(dòng)的位置和鼠標(biāo)點(diǎn)下的位置做差值計(jì)算,所以不用擔(dān)心這里的clientX會(huì)因?yàn)閟lider放在 * 別的地方而導(dǎo)致距離計(jì)算錯(cuò)誤 * @param e */ //鼠標(biāo)點(diǎn)擊 handleMousedown(e) { this.isMove = true; this.initX = e.clientX; const sliderDomWidth = this.outerWidth; // const sliderDomWidth = document.getElementsByClassName("slider-box")[0].clientWidth; document.onmousemove = (e) => { if (this.isMove) { this.moveDistance += e.clientX - this.initX; this.initX = e.clientX; if ((this.moveDistance / sliderDomWidth) * 100 > 100) { this.moveDistance = sliderDomWidth; return; } if ((this.moveDistance / sliderDomWidth) * 100 < 0) { this.moveDistance = 0; return; } } }; document.onmouseup = (e) => { this.isMove = false; document.onmousemove = null; }; }, handleUp(){ // console.log('this.valueRange', this.valueRange); // this.$emit("recommendRange", this.valueRange); }, handleUp2(){ this.$emit("recommendRange", this.valueRange); }, handleUp3(){ this.$emit("recommendRange", this.valueRange); }, handleUp4(){ this.$emit("recommendRange", this.valueRange); }, /** * 當(dāng)點(diǎn)擊進(jìn)度條某一個(gè)位置時(shí),快捷設(shè)置進(jìn)度條的位置,這里就需要用offsetX而不是clientX了。這里需要設(shè)置的便宜距離是鼠標(biāo)距離目標(biāo)元素的距離而不是鼠標(biāo)在整個(gè)頁面上的坐標(biāo) * @param e */ handleClickZong(e) { this.isClick = true; setTimeout(() => { this.isClick = false; }, 300); this.moveDistance = e.offsetX - 10; }, //滑動(dòng)滑塊1 handleMousedownOne1(e) { if (this.userType != 'VIP') { this.$store.commit('common/SET_SHOWEXCHANGEVIP', true); return; } this.flag = true; this.isMove = true; this.leftIndex = 0.5; this.rightIndex = 0; let currentDistance = e.changedTouches[0].clientX; document.ontouchmove = (e) => { let item = e.changedTouches[0]; if (this.isMove) { const moveX = item.clientX - currentDistance; currentDistance = item.clientX; this.moveDistanceOne += moveX; if (this.moveDistanceOne < 0) { this.moveDistanceOne = 0; return; } if (this.moveDistanceOne > this.moveDistanceTwo) { this.moveDistanceOne = this.moveDistanceTwo; return; } this.valueRange = [this.moveDistanceOne, this.moveDistanceTwo]; } }; document.ontouchend = (e) => { this.isMove = false; // this.flag = false; document.onmousemove = null; }; }, handleMousedownOne(e) { console.log(e); if (this.userType != 'VIP') { this.$store.commit('common/SET_SHOWEXCHANGEVIP', true); return; } this.flag = true; this.isMove = true; this.leftIndex = 0.5; this.rightIndex = 0; let currentDistance = e.clientX; document.onmousemove = (e) => { if (this.isMove) { /* moveX 滑塊橫向移動(dòng)的距離 */ const moveX = e.clientX - currentDistance; currentDistance = e.clientX; this.moveDistanceOne += moveX; if (this.moveDistanceOne < 0) { this.moveDistanceOne = 0; return; } if (this.moveDistanceOne > this.moveDistanceTwo) { this.moveDistanceOne = this.moveDistanceTwo; return; } let arr_one = Math.trunc(this.moveDistanceOne * this.rate) + this.min; let arr_two = Math.trunc(this.moveDistanceTwo * this.rate) + this.min; this.valueRange = [arr_one, arr_two]; } }; document.onmouseup = (e) => { this.isMove = false; // this.flag = false; document.onmousemove = null; }; }, //滑動(dòng)滑塊2 handleMousedownTwo1(e) { if (this.userType != 'VIP') { this.$store.commit('common/SET_SHOWEXCHANGEVIP', true); return; } this.isMove = true; this.flag = true; this.leftIndex = 0; this.rightIndex = 0.5; let currentDistance = e.changedTouches[0].clientX; document.ontouchmove = (e) => { if (this.isMove) { let item = e.changedTouches[0]; const moveX = item.clientX - currentDistance; currentDistance = item.clientX; this.moveDistanceTwo += moveX; if (this.moveDistanceTwo > this.outerWidth) { this.moveDistanceTwo = this.outerWidth; return; } if (this.moveDistanceTwo < this.moveDistanceOne) { this.moveDistanceTwo = this.moveDistanceOne; return; } if (this.moveDistanceTwo < 0) { this.moveDistanceTwo = 0; return; } this.valueRange = [this.moveDistanceOne, this.moveDistanceTwo]; } }; document.ontouchend = (e) => { this.isMove = false; // this.flag = false; document.onmousemove = null; }; }, //滑動(dòng)滑塊2 handleMousedownTwo(e) { if (this.userType != 'VIP') { this.$store.commit('common/SET_SHOWEXCHANGEVIP', true); return; } this.flag = true; this.isMove = true; this.leftIndex = 0; this.rightIndex = 0.5; let currentDistance = e.clientX; document.onmousemove = (e) => { if (this.isMove) { const moveX = e.clientX - currentDistance; currentDistance = e.clientX; this.moveDistanceTwo += moveX; if (this.moveDistanceTwo > this.outerWidth) { this.moveDistanceTwo = this.outerWidth; return; } if (this.moveDistanceTwo < this.moveDistanceOne) { this.moveDistanceTwo = this.moveDistanceOne; return; } if (this.moveDistanceTwo < 0) { this.moveDistanceTwo = 0; return; } let arr_one = Math.trunc(this.moveDistanceOne * this.rate) + this.min; let arr_two = Math.trunc(this.moveDistanceTwo * this.rate) + this.min; this.valueRange = [arr_one, arr_two]; } }; document.onmouseup = (e) => { this.isMove = false; // this.flag = false; document.onmousemove = null; }; }, }, }; </script>
<style lang="scss" scoped> @function autoPx($num) { @return (($num / 1200) * 24rem); } .slider-box { height: autoPx(10); border-radius: autoPx(20); position: relative; } .slider-nei { position: absolute; left: 0; top: 0; width: 0; height: autoPx(10); border-radius: autoPx(20); } .point-box { width: autoPx(43); height: autoPx(20); border-radius: autoPx(20); position: absolute; top: -(autoPx(5)); color: #fff; font-size: autoPx(12); line-height: autoPx(20); text-align: center; user-select: none; cursor: pointer; } .point-box:hover { cursor: grab; } .zhua:active { cursor: grabbing; } .transtion { transition: all 0.3s; } </style>
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vuex分模塊后,實(shí)現(xiàn)獲取state的值
這篇文章主要介紹了vuex分模塊后,實(shí)現(xiàn)獲取state的值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-07-07element ui提交表單返回成功后自動(dòng)清空表單的值的實(shí)現(xiàn)代碼
這篇文章主要介紹了elementui提交表單返回成功后自動(dòng)清空表單的值,本文通過兩種方法結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08vue.js+Element實(shí)現(xiàn)表格里的增刪改查
本篇文章主要介紹了vue.js+Element實(shí)現(xiàn)增刪改查,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-01-01vue3中使用vuedraggable實(shí)現(xiàn)拖拽el-tree數(shù)據(jù)分組功能
這篇文章主要介紹了vue3中使用vuedraggable實(shí)現(xiàn)拖拽el-tree數(shù)據(jù)分組功能,可以實(shí)現(xiàn)單個(gè)拖拽、雙擊添加、按住ctrl鍵實(shí)現(xiàn)多個(gè)添加,或者按住shift鍵實(shí)現(xiàn)范圍添加,添加到框中的數(shù)據(jù),還能拖拽排序,需要的朋友可以參考下2024-02-02Vue的實(shí)例、生命周期與Vue腳手架(vue-cli)實(shí)例詳解
本文通過實(shí)例代碼+圖片描述的形式給大家介紹了Vue的實(shí)例、生命周期與Vue腳手架(vue-cli)知識(shí),需要的朋友可以參考下2017-12-12Vue實(shí)現(xiàn)電商網(wǎng)站商品放大鏡效果示例
這篇文章主要為大家介紹了Vue實(shí)現(xiàn)電商網(wǎng)站商品放大鏡效果示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10Vue如何實(shí)現(xiàn)文件預(yù)覽和下載功能的前端上傳組件
在Vue.js項(xiàng)目中,使用ElementUI的el-upload組件可以輕松實(shí)現(xiàn)文件上傳功能,通過配置組件參數(shù)和實(shí)現(xiàn)相應(yīng)的方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-09-09