效果
实现环境
- abcdefg相对于屏幕是居中的,并且不会换行(换行的话要考虑Y坐标)
- 每个item都是相同宽高间距
思路
1、屏幕左边框对应内容第一项的距离a 的距离可以计算出来(我下面命名为leftX)
2、用户移动时我们能获取到手指相对于页面的坐标(获取的是pageX,pageY)
3、用户手指X坐标减去 leftX再除以item的宽 + item的一个左边距再向上取整= 当前用户手指所在的项的序号 ( Math.ceil((fingerPosition.x - leftX) / (letterItem.width+letterItem.margin)) - 1 )
代码
wxml
<view class="word-box">
<view class="word-item {{item.checked?'checked':''}}" style="{{wordItemStyle}}" wx:for="{{letterList}}" wx:key="index" bindtouchstart="onItemStart" bindtouchmove="onItemMove" bindtouchend="onItemEnd" data-idx="{{index}}">
{{item.text}}
</view>
</view>
wxss
.word-box{
display: flex;
display: -webkit-flex;
justify-content: center;
align-items: center;
width: 750rpx;
margin: 20rpx auto;
}
.word-item{
display: flex;
display: -webkit-flex;
justify-content: center;
align-items: center;
border: 1rpx solid red;
box-sizing: border-box;
}
.checked{
background: #000;
color: #fff;
}
js
const app = getApp()
Page({
data: {
letterList:[
{
text:'a',
checked:false,
},
{
text:'b',
checked:false,
},
{
text:'c',
checked:false,
},
{
text:'d',
checked:false,
},
{
text:'e',
checked:false,
},
{
text:'f',
checked:false,
},
// {
// text:'g',
// checked:false,
// },
],
letterItem:{
width:80,
margin:5,
},
canMove:true,
},
onLoad: function (options) {
const SystemInfo = wx.getSystemInfoSync()
app.globalData.pxToRpx = 750/SystemInfo.windowWidth
let letterItem= this.data.letterItem
let wordItemStyle = `width:${letterItem.width}rpx;height:${letterItem.width}rpx;margin:${letterItem.margin}rpx;`
this.setData({
wordItemStyle
})
},
onItemStart(e){
console.log('onItemStart',e)
let idx = e.currentTarget.dataset.idx
let letterList = this.data.letterList
for(let i=idx;i<letterList.length;i++){
if(letterList[i].checked){
this.data.canMove = false
wx.showToast({
title: '选了后面的不能再选前面!',
icon:'none'
})
return false
}
}
this.setData({
[`letterList[${idx}].checked`]:!this.data.letterList[idx].checked
})
},
preCheckIdx:0, // 上一次触发onItemMove所在的idx
onItemMove(e){
// console.log(e)
if(!this.data.canMove) return
const pxToRpx = app.globalData.pxToRpx
let idx = e.currentTarget.dataset.idx
let letterList = this.data.letterList
let fingerPosition = {
x:e.touches[0].pageX * pxToRpx,
y:e.touches[0].pageY * pxToRpx,
}
console.log('onItemMove fingerPosition',fingerPosition)
let letterItem = this.data.letterItem
let leftX = (750 - (letterList.length*letterItem.width + (letterList.length-1)*letterItem.margin ))/2
let checkedNum = Math.ceil((fingerPosition.x - leftX) / (letterItem.width+letterItem.margin)) - 1 // 当前滑动到的下标
console.log( idx,'-',checkedNum )
// console.log(leftX)
if(checkedNum<idx || this.preCheckIdx == checkedNum || checkedNum>letterList.length-1){
// 往左划 或者 上一次位置和这次位置一致 则不奏效
return false
}
if(this.preCheckIdx > checkedNum){
this.setData({
[`letterList[${this.preCheckIdx}].checked`]:false
})
}
if(this.preCheckIdx < checkedNum){
this.setData({
[`letterList[${checkedNum}].checked`]:true
})
}
this.preCheckIdx = checkedNum
},
onItemEnd(e){
// console.log('onItemEnd',e)
this.data.canMove = true
},
})