想要做一个基于uni-app的血糖血压刻度滑动控件,hbuilder市场没有好的,参照别人的写了一个。如图:
源码,自己放入components里面。
<!-- 刻度滑动选择 -->
<template><view><view class="slide-title"><view class="slide-title-left">{{subTitle}}</view><view class="slide-title-num">{{selvalue}}</view><view class="slide-title-right">{{subUnit}}</view></view><view class="slide-scroll-border"><scroll-view scroll-x class="slide-scroll" :enable-flex="true" show-scrollbar="false":style="{width: setUnit(screenW)}" @scroll="slideScroll":scroll-left="scrollLeft" @touchend="slideMoveEnd" :scroll-with-animation="true"><view class="slide-scroll slide-border"><view class="empty-none" :style="{width: screenW /2 + 'px'}"></view><view v-for="(s_item, s_index) in list" :key="s_index" class="" :class="{'slide-list':true,'selected': s_index === selInd,'selected1': (s_index === selInd + 1 || s_index === selInd - 1),'selected2': (s_index === selInd + 2 || s_index === selInd - 2),'selected3': (s_index === selInd + 3 || s_index === selInd - 3) }"><view class="list-num" v-if="s_index%10==0">{{s_item}}</view><view class="slide-list-ba"></view></view><view class="empty-none" :style="{width: screenW / 2 + 'px'}"></view></view></scroll-view></view><view class="slide-message" v-if="message">{{message}}</view></view>
</template><script>export default {name:'zlSlider',data() {return {scrollLeft: 0, // 仅用于核准中间位置d_len:20,list: [],selvalue:0,selInd: 0,cellWidth:12,// 每小格宽度screenW:uni.getSystemInfoSync().screenWidth};},props: {subTitle: { type: String, default: '' },subUnit: { type: String, default: '' },message: { type: String, default: '' },startNum: { type: Number, default: 0 }, // 开始数值endNum: { type: Number, default: 20 }, // 结束数值step: { type: Number, default: 1 }, // 结束数值value: { type: Number, default: 0 }, // 用v-model双向绑定},mounted() {// 获取滑动显示内容的宽度。uni.createSelectorQuery().in(this).select('.slide-scroll-border').boundingClientRect(data => {if (data) this.screenW = data.width-60;}).exec();this.initSlide();},methods: {setUnit(unit) {if (typeof unit === 'number') {return (unit + 'px')} else {return unit;}},// 滚动触发slideScroll(e) {const { cellWidth} = this;const scrollL = e.detail.scrollLeft; // 当前滚动距离左边的距离let ind = parseInt(scrollL / cellWidth); // 当前选中是第几个if (ind > this.d_len) {ind = this.d_len;}if (ind !== this.selInd) {this.selInd = ind;this.selvalue = this.getIntNum(this.selInd*this.step+this.startNum)}},// 触摸结束slideMoveEnd(e) {// const end_t = setTimeout(() => {// const { selInd } = this;// this.slideTo(selInd);// this.setEmitFunc();// clearTimeout(end_t);// }, 400);const { selInd } = this;this.slideTo(selInd);this.setEmitFunc();},// 初始化initSlide() {const { startNum, endNum, step } = this;this.d_len = (endNum - startNum)*(1/step);// let list = [...Array(this.d_len).keys()].map(index=>this.getIntNum(startNum + index*this.step))// for (let i = 0; i <= this.d_len; i++) {// const l_num = this.getIntNum(startNum + i*this.step);// list.push(l_num);// }this.list = [...Array(this.d_len).keys()].map(index=>this.getIntNum(startNum + index*step));this.getSelInd();},// 滚动到正确的刻度slideTo(ind) {const { screenW, cellWidth, scrollLeft } = this;const newLeft = ind * cellWidth + (cellWidth / 2);this.$nextTick(()=>{this.scrollLeft = (scrollLeft === newLeft) ? (scrollLeft + 0.001) : newLeft;})},// 四舍五入getIntNum(n) {return parseInt(n * 100) / 100},// value改变后,计算选中的selIndgetSelInd() {const { endNum, startNum } = this;let value = this.value,isChange = false,noHave = false;// 不能超过最小最大值if (value > endNum) {value = endNum;isChange = true;} else if (value < startNum) {value = startNum;isChange = true;}let defaultInd = -1;const itemValue = this.list.map((item,index)=>{return (item===value)? index :0}).filter(item=>item>0);// for (let d = 0; d <= this.d_len; d++) {// const item = this.getIntNum(startNum + d*this.step);// if (item === value) {// defaultInd = d;// break;// }// }if(itemValue && itemValue.length>0){defaultInd = itemValue[0]}else {defaultInd = 0;noHave = true;}// 没有匹配到的情况 以及 超过了最大最小值 需要通知父组件修改value(isChange || noHave) && this.setEmitFunc();if (defaultInd === this.selInd) return;this.selInd = defaultInd;this.selvalue = this.getIntNum(this.selInd*this.step+this.startNum)this.slideTo(defaultInd);},// 父组件通知事件setEmitFunc() {const { selvalue } = this;this.$emit('input', selvalue);this.$listeners.change && this.$emit('change', selvalue);},},watch: {value: function(newVal, oldVal) {this.getSelInd();}},}
</script><style lang="scss">.slide-title{display: flex;flex-direction: row;align-items: flex-end;justify-content: center;margin-top: 10px;margin-bottom: 5px;&-left,&-right{color:$uni-text-color-grey;font-size: 14px;}&-num{color:$uni-text-color;text-align: center;font-size: 30px;margin: 0 10px;line-height: 100%;/* #ifdef H5 */margin-bottom: 5px !important;/* #endif */}}.slide-message{color:$uni-text-color-grey;font-size: $uni-font-size-sm;margin: 0 20px;}.slide-scroll {display: flex;flex-wrap: nowrap;flex-direction: row;height: 50px;::-webkit-scrollbar {width: 0 !important;height: 0 !important;-webkit-appearance: none;background: transparent;color: transparent;}}.slide-scroll-border{padding: 5px 30px;border: 1px solid #808080;border-radius: 40px;overflow: hidden;}.slide-list {flex-shrink: 0;position: relative;border-radius: 4px;transition: background-color .1s;width:4px;margin: 0 4px;height: 50px;}.slide-list.selected .slide-list-ba{background-color: red !important;height: 27px;}.slide-list.selected1 .slide-list-ba{background-color: red !important;height: 24px;}.slide-list.selected2 .slide-list-ba{background-color: red !important;height: 21px;}.slide-list.selected3 .slide-list-ba{background-color: red !important;height: 18px;}.slide-list-ba{position: absolute;bottom: 0;left: 0;right: 0;height: 15px;background-color: #D3D3D3;}.list-num {top: 0;position: absolute;transform: translateX(-50%);}.empty-none {flex-shrink: 0;height: 5px;}
</style>
使用示例
<template><view>
......
<zl-slider v-model="bloodSugar.value" :step="0.1" :startNum="0" :endNum="50" subTitle="血糖" subUnit="mmol/L" message="范围通常>3.9,空腹<7.0, 饭后两小时内<11.1 mmol/L"></zl-slider>
......</view>
</template>
<script>import zlSlider from '@/components/zl-slider/zl-slider.vue';export default {components:{zlSlider},data() {return {bloodSugar:{value:0}}}}
</script>