代码片段分享链接地址:https://developers.weixin.qq.com/s/1bnpmmm87Ayy
感谢小伙伴指出来的错误,已修正,分享链接已更新,感谢感谢 @weixin_44644888
看效果图:
直接上代码,注释写的非常详细:
<view class="cont">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Harum tempore voluptate dicta, amet nulla doloremque exercitationem vel magni ipsam unde voluptates, rerum illum consectetur ab saepe eos eius suscipit alias?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Iure, corporis debitis! Esse sapiente animi totam consectetur quo pariatur minus aut culpa nisi laborum! Odit impedit sequi saepe sit, recusandae beatae.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Minima libero fuga similique officiis voluptatibus consequatur doloribus atque mollitia. Possimus, natus illo. Nesciunt magni rem officiis. Iure voluptate deleniti nihil enim.
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Odit labore eveniet quis, nemo illo dolorem repudiandae accusamus impedit praesentium harum unde, rerum, optio similique. Temporibus fuga culpa repellendus obcaecati id!
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Laborum ducimus, deserunt amet aut reiciendis voluptates unde rerum libero cupiditate similique labore eos nihil! Incidunt illo eveniet, expedita quibusdam soluta iure!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Laborum modi necessitatibus, minus dicta doloribus molestias accusantium officia recusandae explicabo corrupti iste veritatis soluta voluptas facere alias accusamus iure nostrum at?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam dolor deserunt velit esse illum quas beatae quasi odio repellendus maiores sequi, nulla tempora eligendi eaque culpa voluptatem veritatis quo fugiat.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Corrupti error voluptatem nostrum quod temporibus consequuntur nobis natus autem modi voluptates. Explicabo, recusandae. Corporis quaerat nemo nobis debitis est error suscipit.
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Libero obcaecati vitae explicabo corrupti dicta earum expedita molestias delectus. Distinctio, reprehenderit? Nobis similique doloremque natus sequi nihil aspernatur harum, laborum suscipit!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Sint natus est, aut, eum voluptatibus reiciendis animi molestias assumenda ratione autem expedita eveniet tempora rem. Molestiae sapiente ab error odio ipsam?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Tenetur neque voluptatum perspiciatis fugit dolores, ad aperiam. Officiis esse excepturi dignissimos reprehenderit magnam neque illo ducimus aut, nulla explicabo aspernatur aliquid!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Expedita repellendus aliquid aut dolorem dolor soluta, accusantium odit fugit quisquam hic consectetur sed ab minus autem exercitationem tempore ad porro eius.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Recusandae est aliquam, id, autem exercitationem cupiditate repudiandae atque expedita explicabo vel enim neque totam. Vitae libero totam quas numquam laboriosam at.
Lorem ipsum dolor sit amet consectetur adipisicing elit. At excepturi quasi et repellat! Dicta quod voluptate explicabo! Ipsum, voluptatem deserunt quos recusandae perspiciatis nihil magni sapiente voluptas pariatur in nisi.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Itaque dolor molestias fugiat perspiciatis officiis natus inventore quaerat tenetur cum, praesentium magni, similique debitis vero sapiente ipsum aliquam modi voluptatem veniam!
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Officia animi voluptatum sint blanditiis officiis corporis ipsam accusamus harum enim doloremque a magni accusantium magnam sequi beatae, distinctio iure quam voluptatem.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Molestiae id voluptatem deserunt ipsum libero odio suscipit nobis, tenetur sed veritatis sapiente, magnam, quia dolores est repellat exercitationem voluptas architecto quasi.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Laboriosam repellendus, eligendi soluta, exercitationem temporibus quia totam, porro possimus repudiandae consequuntur iste dolor. Magni ipsam distinctio magnam accusantium nam itaque unde.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Possimus quos enim ut aliquam laboriosam quod, inventore officia numquam obcaecati odit nam, facere saepe impedit quis eligendi itaque amet consequatur. Nihil!
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quaerat illum perspiciatis minus iusto dolores tempora ipsam vitae vero perferendis architecto magnam, veniam expedita saepe nobis modi labore voluptatem! Ratione, quas?
view>
<movable-area class="movable-area" id="movableArea">
<movable-view class="movable-view" id="movableView" x="{{x}}px" y="{{y}}px" direction="all" animation="{{movableViewAnimation}}" bindtouchend="movableViewTouchEndHandler" bindchange="movableViewChangeHandler">
<view class="movable-view-main">view>
movable-view>
movable-area>
page{
width: 100%;
min-height: 100%;
background: rgba(0,0,0,0.75);
}
.cont{
width: 100%;
}
.movable-area{
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.movable-view{
width: 120rpx;
height: 120rpx;
}
.movable-view-main{
width: 120rpx;
height: 120rpx;
background: #f00;
}
const app = getApp()
// 这里随便初始化一个变量,记录滑块滑动的时候的 X,Y,之所以这样弄,是因为 setData 性能原因,写这里会好一些,不需要一直 setData 了
let movableTmpX = 0,
movableTmpY = 0,
movableChangeFlag = false // 是否移动
Page({
data: {
x: 0,
y: 0,
viewportInfo: null, // 视口样式信息
movableAreaInfo: null, // movableArea 样式信息
movableViewInfo: null, // movableView 样式信息
movableViewAnimation: false // movableView 动画是否开启
},
onLoad: function () {
},
onReady: function () {
// 之所以写在这里,是因为毕竟是初始化样式嘛,写在 onLoad 和 onShow 里边都不能确保样式已经渲染完毕,页面已经准备完毕了,所以写在 onReady 里边初始化
const query = wx.createSelectorQuery().in(this) // 这个 in(this) 在自定义组件内部使用相当有用,这里有没有都行
query.selectViewport().boundingClientRect()
query.selectAll('#movableArea,#movableView').boundingClientRect()
query.exec(res => { // 统一获取样式
let viewportInfo = res[0] // 这里可以获取当前屏幕视口的宽高,如果设置 movableArea 区域的话,这个相当有用,这里没用上
let movableAreaInfo = res[1][0] // 这是获取的 movableArea 样式
let movableViewInfo = res[1][1] // 这里获取的 movableView 样式
let x = movableAreaInfo.width - movableViewInfo.width - 48 // 这里之所以多减了 48 ,只是作为展示动态的初始化 x,y 怎样不让 movableView 过渡过去
let y = movableAreaInfo.height - movableViewInfo.height - 48 // 这里之所以多减了 48 ,只是作为展示动态的初始化 x,y 怎样不让 movableView 过渡过去
this.setData({
x,
y,
viewportInfo,
movableAreaInfo,
movableViewInfo
})
setTimeout(() => {
this.setData({
movableViewAnimation: true // 初始化 x y 之后把动画打开,注意:一定要和上边的设置 x y 初始值区分开,不然设置初始值的时候还是会过渡过去,这个就没意义了
})
})
})
},
// 滑动滑块 记录滑块当前的 X,Y
movableViewChangeHandler: function ({
detail
}) {
let {
x,
y,
source
} = detail
if (source === 'touch') { // 这里是只记录手指滑动的 X Y
movableChangeFlag = true // 代表移动过
movableTmpX = x // 记录滑块当前的 X
movableTmpY = y // 记录滑块当前的 Y
}
},
// 手指滑动结束事件
movableViewTouchEndHandler: function (e) {
if(movableChangeFlag){ // 移动过才触发,不移动单纯点击不触发
let {
width: movableAreaWidth,
height: movableAreaHeight
} = this.data.movableAreaInfo
let {
width: movableViewWidth,
height: movableViewHeight
} = this.data.movableViewInfo
let tmpX = 0,
tmpY = movableTmpY
// 计算当前 X 偏向于左还是右
if (movableTmpX + movableViewWidth / 2 > movableAreaWidth / 2) { // 如果偏向于右侧,则向右靠拢
tmpX = movableAreaWidth - movableViewWidth // 设置 X 为最右侧
} else { // 如果偏向于左侧,则向左靠拢
tmpX = 0 // 设置 X 为最左侧
}
// 第一次设置 X,Y
this.setData({
x: tmpX,
y: tmpY
})
// 第二次设置 X,Y ,实际上这里只需要设置 Y 就行了,因为有问题的是 Y,不过这里把 X 也设置了,防止 X 也有问题
setTimeout(() => {
this.setData({
x: tmpX,
y: tmpY
})
// 其实这里延迟不给就行,但是为了确保可行性,还是协商了 20ms 的延迟,基本上没啥感知
},20)
movableChangeFlag = false // 重置为未移动过
}
})
点击使用本地开发者工具查看:https://developers.weixin.qq.com/s/1bnpmmm87Ayy