新遇到一个需求,希望在选择重量的时候,通过滑块的方式来获取。结合小程序通用组件slider和大佬们的经验,通过css简单实现了一个,做个记录。
- ruler.wxml
<view class='wrapper horizontal-box' id='scale-wrapper'>
<view>{{weight}}kg</view>
<view class='weight-wrapper' id='scale-wrapper'>
<!-- 标尺容器 -->
<view class='scale-container'>
<view class='scale-wrapper' id='scaleWrapper'>
<view class="slider-active" id="sliderActive" style="width: {{sliderActive}}rpx;"></view>
<view class='scale-grip-item scale-grip-item-first' style="width:{{single}}rpx;height:14rpx;border-color:{{styles.line}};"> </view>
<view class='scale-grip'
wx:for="{{grid}}"
wx:key="{{index}}"
style='height:{{h}}rpx;border-color:{{styles.line}};'>
<view class='scale-grip-item'
wx:for-item="it"
wx:for-index="itx"
wx:for="{{5}}"
wx:key="itx"
style="width:{{single}}rpx;height:{{itx==4?'33':'14'}}%;border-color:{{styles.line}};"
></view>
<view class='scale-grip-vaule'>{{min+5*(index)}}</view>
</view>
<view class='scale-grip scale-grip-last' style='height:{{h}}rpx;border-color:{{styles.line}};'>
<view class='scale-grip-vaule'>{{max}}</view>
</view>
</view>
</view>
<view class='weight-slider-bar' style="margin-left: {{sliderActive}}rpx;"></view>
<slider class='weight-slider' style="margin-left: {{circleWidth}}rpx;" min='4' max='20' value='{{weight}}'
activeColor="#FF6A00" backgroundColor='#F8F8F8' color="#F8F8F8"
bindchange="chooseWeight" bindchanging="changeingWeight" block-size="28" ></slider>
</view>
</view>
- ruler.wxss
view,text{
box-sizing: border-box;
}
.wrapper{
position: relative;
}
.weight-wrapper{
position: relative;
}
.horizontal-box .scale-container {
display: flex;
flex-direction: column;
align-items: center;
}
.horizontal-box .scroll-wrapper {
position: relative;
display: flex;
}
.horizontal-box .zz{
position: absolute;
left: 50%;
top: 0;
transform: translate(-50%);
height: 40%;
width: 2px;
background-color: #5b73f2;
z-index: 10;
}
.horizontal-box .scale-wrapper{
display: flex;
width: 100%;
height: 90rpx;
background: #F8F8F8;
align-items: flex-end;
border-radius: 90rpx;
justify-content: center;
}
.horizontal-box .scale-grip{
position: relative;
height: 100rpx;
display: flex;
align-items: flex-end;
}
.horizontal-box .scale-grip::before{
content: "";
position: absolute;
bottom: 0;
border-width: 2rpx;
border-color: inherit;
border-style: solid;
height: 100%;
transform: translateX(-50%);
left: 0rpx;
}
.horizontal-box .scale-grip-vaule{
position: absolute;
bottom: -20px;
width: 80rpx;
height: 30rpx;
text-align: center;
transform: translateX(-50%);
}
.horizontal-box .scale-grip-item{
height: 60%;
padding-top: 10rpx;
}
.horizontal-box .scale-grip-item:not(:last-child){
border-right: 2rpx solid #000000;
}
.horizontal-box .scale-grip-item-first{
height: 60%;
padding-top: 10rpx;
border-left: 2rpx solid #000000;
border-right: none;
}
.horizontal-box .scale-vaule-wrapper{
position: relative;
display: flex;
text-align: center;
}
.horizontal-box .scale-vaule{
text-align: left;
width: 180rpx;
}
.horizontal-box .scale-vaule:last-child{
text-align: right;
}
.horizontal-box .first-scale-value{
position: absolute;
left: 0;
bottom: 0;
transform: translateX(-50%);
}
.weight-slider {
width: 576rpx;
margin: 0rpx;
position: absolute;
top: 32rpx;
opacity: 0.01;
}
.weight-slider-bar {
position: absolute;
top: -10rpx;
width: 18rpx;
height: 110rpx;
border: 2rpx solid #D0D0D0;
background: #FFFFFF;
box-shadow: 0 8px 20px 0 rgba(0,0,0,0.14);
border-radius: 10px;
transform: translateX(-50%);
}
.slider-active {
position: absolute;
top: 0;
left: 0;
border-top-left-radius: 90rpx;
border-bottom-left-radius: 90rpx;
height: 90rpx;
background: #FF6A00;
}
- ruler.ts
const defaultStyles = {
line: '#D9D9D9', // 刻度颜色
fontSize: 16, //字体大小
};
Component({
attached() {
// 获取两端宽度
const query = wx.createSelectorQuery().in(this);
const that = this;
query
.select('.scale-wrapper')
.boundingClientRect(function(rects) {
const { width } = rects;
// 获取两端半圆的宽度
const circleWidth = width - 16 * 18;
that.setData({
circleWidth,
sliderActive: circleWidth,
});
})
.exec();
},
/**
* 组件的属性列表
*/
properties: {
// 最小值
min: {
type: Number,
value: 0,
},
//最大值
max: {
type: Number,
value: 100,
},
// 每个格子的实际行度 (单位rpx ,相对默认值)
single: {
type: Number,
value: 36,
},
styles: {
type: Object,
value: defaultStyles,
},
},
data: {
circleWidth: 0,
weight: 1,
},
ready() {
this.init();
},
methods: {
init() {
// 设置默认值
const min = this.data.min || 0;
const max = this.data.max || 0;
const grid = (max - min) / 5;
const styles = Object.assign(defaultStyles, this.data.styles);
this.setData({ grid, styles });
},
// 选择重量
chooseWeight(e) {
const weight = e.detail.value === 4 ? 1 : e.detail.value;
const { circleWidth } = this.data;
const sliderActive = weight < 5 ? circleWidth : circleWidth + (weight - 4) * 36;
this.setData({
weight,
sliderActive,
});
this.triggerEvent('set-weight', weight);
},
// 滑动选择重量
changeingWeight(e) {
const { circleWidth } = this.data;
const weight = e.detail.value === 4 ? 1 : e.detail.value;
const sliderActive = weight < 5 ? circleWidth : circleWidth + (weight - 4) * 36;
this.setData({
weight,
sliderActive,
});
this.triggerEvent('set-weight', weight);
},
},
});
- 使用
<weight-ruler min="5" max="20" single="36" bind:set-weight="setWeight"></weight-ruler>