vue項目雙滑塊組件使用
更新時間:2024年07月27日 09:45:03 作者:漢武大帝·
這篇文章主要介紹了vue項目雙滑塊組件使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
vue項目雙滑塊組件
先看效果圖
說明
- 兩端值300,750 是可選范圍的最大值;
- 兩個按鈕上的值是已經(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, //是否直接點擊 isMove: false, //是否處于滑動狀態(tài) flag: false, // moveDistance: 0, initX: 0, //記錄鼠標點下時的坐標,用于移動中求差值 moveStart: 0, //進度條的開始位置 moveEnd: 0, //進度條的結(jié)束位置 moveDistanceOne: 0, //滑塊一的位置 moveDistanceTwo: 50, //滑塊二的位置 rate: 1, // 比率 outerWidth: 100, rate1: 1, // 比率 outerWidth1: 100, valueRange: [], leftIndex: 0, rightIndex: 0.5, }; }, computed: { // 使用對象展開運算符將 getter 混入 computed 對象中 ...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(); } }); }, //移動端 touchstart 點擊監(jiān)聽 ontouchmove 移動監(jiān)聽 ontouchend 松開監(jiān)聽,e.changedTouches[0] 元素偏移的一些數(shù)據(jù) //PC端 mousedown 點擊監(jiān)聽 onmousemove 移動監(jiān)聽 onmouseup 松開監(jiān)聽 /** * 初始坐標就是鼠標點下時的clientX坐標,這樣就可以做到將slider放在頁面任何位置,拖動原點偏移的量也是正確的, * 因為原點移動距離是用鼠標移動的位置和鼠標點下的位置做差值計算,所以不用擔心這里的clientX會因為slider放在 * 別的地方而導(dǎo)致距離計算錯誤 * @param e */ //鼠標點擊 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); }, /** * 當點擊進度條某一個位置時,快捷設(shè)置進度條的位置,這里就需要用offsetX而不是clientX了。這里需要設(shè)置的便宜距離是鼠標距離目標元素的距離而不是鼠標在整個頁面上的坐標 * @param e */ handleClickZong(e) { this.isClick = true; setTimeout(() => { this.isClick = false; }, 300); this.moveDistance = e.offsetX - 10; }, //滑動滑塊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 滑塊橫向移動的距離 */ 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; }; }, //滑動滑塊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; }; }, //滑動滑塊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é)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
element ui提交表單返回成功后自動清空表單的值的實現(xiàn)代碼
這篇文章主要介紹了elementui提交表單返回成功后自動清空表單的值,本文通過兩種方法結(jié)合實例代碼給大家介紹的非常詳細,對大家的學(xué)習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-08-08vue.js+Element實現(xiàn)表格里的增刪改查
本篇文章主要介紹了vue.js+Element實現(xiàn)增刪改查,具有一定的參考價值,有興趣的可以了解一下。2017-01-01vue3中使用vuedraggable實現(xiàn)拖拽el-tree數(shù)據(jù)分組功能
這篇文章主要介紹了vue3中使用vuedraggable實現(xiàn)拖拽el-tree數(shù)據(jù)分組功能,可以實現(xiàn)單個拖拽、雙擊添加、按住ctrl鍵實現(xiàn)多個添加,或者按住shift鍵實現(xiàn)范圍添加,添加到框中的數(shù)據(jù),還能拖拽排序,需要的朋友可以參考下2024-02-02Vue的實例、生命周期與Vue腳手架(vue-cli)實例詳解
本文通過實例代碼+圖片描述的形式給大家介紹了Vue的實例、生命周期與Vue腳手架(vue-cli)知識,需要的朋友可以參考下2017-12-12Vue實現(xiàn)電商網(wǎng)站商品放大鏡效果示例
這篇文章主要為大家介紹了Vue實現(xiàn)電商網(wǎng)站商品放大鏡效果示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10Vue如何實現(xiàn)文件預(yù)覽和下載功能的前端上傳組件
在Vue.js項目中,使用ElementUI的el-upload組件可以輕松實現(xiàn)文件上傳功能,通過配置組件參數(shù)和實現(xiàn)相應(yīng)的方法,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-09-09