vue项目实现自定义滑块过渡效果
更新时间:2024年07月27日 09:38:48 作者:小影_8978
这篇文章主要介绍了vue项目实现自定义滑块过渡效果,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
vue自定义滑块过渡效果
- html部分:
<div class="slider-main"> <div class="slider"> <span v-show="value !== ''" class="pointer" :style="`background-color: ${pointerColor}; left: ${pointerLeft}%`" /> </div> <div class="data-text"> <span class="min-max">{{ max }}%</span> <span class="min-max">{{ min }}%</span> </div> </div>
- css代码:
.slider-main { width: 100%; .slider { flex: 1; height: 14px; border-radius: 20px; background: linear-gradient(to right, #F59292, #95D8A4); position: relative; rotate: 180deg; .pointer { position: absolute; width: 24px; height: 35px; top: 50%; transform: translate(-50%, -50%); border-radius: 24px; border: 3px solid #fff; left: 50%; } } .data-text { display: flex; justify-content: space-between; align-items: center; .min-max { font-size: 12px; color: #666; margin: 0 5px; } } }
- js部分:
export default { props: { value: { type: [Number, String], default: '' }, min: { type: Number, default: -100 }, max: { type: Number, default: 100 }, }, computed: { pointerColor () { // 获取当前值对应的颜色 // return this.colorToHex(currentColor); return tools.valueToColor(this.min, this.max, this.value); }, pointerLeft () { return this.calculateLeftPosition(this.value, this.min, this.max) } }, methods: { // 计算当前的left的位置 calculateLeftPosition(actualValue, minValue, maxValue) { // 确保实际值不小于最小值,不大于最大值 actualValue = Math.max(minValue, Math.min(maxValue, actualValue)); // 计算left值 var left = (actualValue - minValue) / (maxValue - minValue) * 100; // 返回left值 return left; }, } }
vue写滑块组件
<template> <div @touchend="down = false" @touchmove="gotouchstart" class="pledge"> <!-- <div class="mask" @touchend="down = false" @touchmove="gotouchstart"></div> --> <div class="h2">調整質押率</div> <!-- 已借數量和質押金額 --> <div class="info"> <div>已借數量</div> <div>1,001.48292837 USDT</div> </div> <div class="info"> <div>質押金額</div> <div>1.48292837 BTC</div> </div> <!-- 滑块背景 --> <div class="box"> <div style="border-right: 1px solid #0f9d58"> <div class="text">65%</div> <div class="text">初始質押率</div> <div class="low col">低風險</div> <div class="round"> <div></div> </div> <div class="round" style="bottom: -4px; left: -4px"> <div></div> </div> <div class="round" style="top: -4px; right: -4px"> <div style="background: #0f9d58"></div> </div> </div> <div style="border-right: 1px solid #d23f31"> <div class="text">83%</div> <div class="text">平倉質押率</div> <div class="danger col">高風險</div> <div class="round"> <div></div> </div> <div class="round" style="top: -4px; right: -4px"> <div style="background: #d23f31"></div> </div> </div> </div> <!-- 滑块 --> <div class="slider" ref="sliderRef"> <div class="slider_box" :style="{ left: sliderLeft + 'px' }" @touchstart="down = true" > | | | </div> <div class="percent" :style="{ left: percentLeft + 'px' }"> <div>LTV</div> <div style="color: #0f9d58; font-weight: bold">{{ percent }}%</div> </div> </div> <!-- 还款总额弹窗 --> <div class="title">質押金額</div> <div class="input"> <div class="type">增加</div> <input type="text" v-model="money" @keyup="formatInput" /> <div class="unit"> <span style="margin-right: 5px">MAX</span> <span style="color: rgba(0, 0, 0, 0.87)">USDT</span> </div> </div> <div class="btn">增加质押金</div> </div> </template>
<script> export default { data() { return { sliderLeft: -16, // 滑块左侧距离 percentLeft: -21, // 百分比的侧距离 percent: 1, // 百分比 down: false, // 控制滑块 money: 0, } }, mounted() {}, methods: { // 滑块拖动 gotouchstart(e) { if (this.down) { let width = this.$refs.sliderRef.getBoundingClientRect().width // 计算距离 let left = Math.round(e.targetTouches[0].clientX) - Math.round(this.$refs.sliderRef.getBoundingClientRect().left) if (left < 0) { this.sliderLeft = -17 this.percentLeft = -27 } else if (left > width) { this.sliderLeft = width - 17 this.percentLeft = width - 27 } else { this.sliderLeft = left - 17 this.percentLeft = left - 27 } // 计算百分比 if (left > 0 && left < width / 2) { this.percent = Math.round((left / width) * 2 * 65) this.percent = this.percent ? this.percent : 1 } else if (left > width / 2 && left < width) { this.percent = Math.round(((left - width / 2) / width) * 2 * 18 + 65) } else if (left < 0) { this.percent = 1 } else if (left > width) { this.percent = 83 } } }, // 数字处理 formatInput() { if (typeof this.money !== 'string') { this.money = this.money.toString() } // 先把非数字的都替换掉,除了数字和. this.money = this.money.replace(/[^\d.]/g, '') // 必须保证第一个为数字而不是. this.money = this.money.replace(/^\./g, '') // 保证只有出现一个.而没有多个. this.money = this.money.replace(/\.{2,}/g, '') // 保证.只出现一次,而不能出现两次以上 this.money = this.money .replace('.', '$#$') .replace(/\./g, '') .replace('$#$', '.') // 只能输入小数点后8位 const reg = '^(-)*(\\d+)\\.(\\d{' + 8 + '}).*$' this.money = this.money.replace(new RegExp(reg), '$1$2.$3') }, }, } </script>
<style lang="less" scoped> .pledge { padding: 16px; position: relative; overflow: hidden; .h2 { font-family: DIN Pro; font-style: normal; font-weight: bold; font-size: 16px; line-height: 20px; display: flex; justify-content: center; align-items: center; width: 100%; height: 36px; } .mask { width: 100wh; height: 100vh; position: fixed; top: 0; bottom: 0; left: 0; right: 0; z-index: -1; } } .info { font-family: DIN Pro; font-size: 14px; font-style: normal; line-height: 18px; letter-spacing: 0em; text-align: left; display: flex; margin: 20px 0 30px 0; } .info :first-child { color: #86868b; min-width: 80px; } .info :last-child { color: #1d1d1f; font-weight: bold; } .title { font-family: DIN Pro; font-style: normal; font-weight: bold; font-size: 14px; line-height: 18px; color: #1d1d1f; margin: 8px 0; } .input { display: flex; height: 50px; justify-content: space-between; align-items: center; background: #f5f5f7; border-radius: 4px; padding: 0 15px; .type { width: 80px; height: 40px; margin-right: 5px; border-right: 1px solid #e6e6e9; font-family: DIN Pro; font-style: normal; font-weight: normal; font-size: 14px; line-height: 40px; color: rgba(0, 0, 0, 0.87); } input { width: 120px; background: none; outline: none; border: none; font-family: DIN Pro; font-style: normal; font-weight: normal; font-size: 16px; line-height: 26px; color: rgba(0, 0, 0, 0.87); } .unit { font-family: DIN Pro; font-size: 14px; font-style: normal; font-weight: 400; line-height: 18px; letter-spacing: 0em; color: #14c393; } } .btn { height: 40px; background: #14c393; border-radius: 10px; color: #ffffff; font-family: DIN Pro; font-style: normal; font-weight: bold; font-size: 14px; line-height: 18px; display: flex; justify-content: center; align-items: center; margin-bottom: 25px; margin-top: 16px; } .slider { width: 100%; height: 100px; position: relative; .slider_box { display: flex; justify-content: center; align-items: center; color: #a1a1a6; width: 34px; height: 32px; background: #ffffff; border: 1px solid #e6e6e9; box-sizing: border-box; box-shadow: 0px 0px 3px rgba(101, 119, 134, 0.15), 0px 0px 15px rgba(101, 119, 134, 0.2); border-radius: 8px; position: absolute; top: 0%; transform: translateY(-50%); z-index: 10; } .percent { position: absolute; top: 30px; width: 55px; height: 42px; background-color: #fff; box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.08), 0px 4px 8px rgba(50, 50, 71, 0.006); border-radius: 4px; display: flex; justify-content: center; align-items: center; flex-direction: column; font-size: 12px; line-height: 16px; font-family: DIN Pro; font-style: normal; font-weight: normal; color: #515154; } } .box { display: flex; flex: 2; margin-top: 16px; > div { flex: 1; text-align: right; position: relative; } .text { font-family: DIN Pro; font-style: normal; font-weight: normal; font-size: 12px; line-height: 16px; color: #515154; margin-right: 4px; } .col { height: 50px; margin-top: 18px; font-family: DIN Pro; font-style: normal; font-weight: bold; font-size: 12px; line-height: 16px; padding-right: 4px; padding-top: 4px; } .round { width: 8px; height: 8px; background: #ffffff; border: 1px solid #e6e6e9; display: flex; justify-content: center; align-items: center; border-radius: 50%; position: absolute; bottom: -4px; right: -4px; z-index: 5; > div { width: 4px; height: 4px; background: #1d1d1f; border-radius: 50%; } } .low { background: rgba(15, 157, 88, 0.2); color: #0f9d58; border-bottom: 2px solid #0f9d58; } .danger { background: rgba(210, 63, 49, 0.2); color: #d23f31; border-bottom: 2px solid #d23f31; } } </style>
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
vue.js自定义组件实现v-model双向数据绑定的示例代码
这篇文章主要介绍了vue.js自定义组件实现v-model双向数据绑定的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-01-01
最新评论