微信小程序翻书效果
微信小程序翻书效果
wxml
<viewwx:for="{{imgList}}" hidden="{{pagenum > imgList.length - index - 1}}"wx:key="index"class="list-pape" style="{{index == imgList.length - pagenum - 1 ? clipPath1 : ''}}"bindtouchstart="touchstart"bindtouchmove="touchmove"bindtouchend="touchend"><image src="{{item}}" mode="aspectFit" data-src="{{item}}" bindtap="previewImage"></image></view><!-- 背面部分 --><view wx:if="{{transformCss}}" class="page-back" style="{{transformCss}};{{clipPath2}};{{transformOrigin}}"><image src="{{pageBackImage}}" mode="aspectFit"></image></view>
js
data:{imgList:[ ],pageBackImage: '',transformCss: '', transformOrigin: '',clipPath2: '',clipPath1: '',pagenum: 0,startPoint: 0, //记录滑动的初始位置slipFlag: false, //定义 滑动事件 节流阀, 防止一次滑动触发多次滑动事件imgboxh: 0,imgboxw: 0,
}
touchstart:function(e) {this.setData({startPoint: e.touches[0],slipFlag: true})},touchmove:function(e) {let clientX = e.touches[0].clientX;let clientY = e.touches[0].clientY;if (((this.data.startPoint.clientX - clientX) > 80) && this.data.slipFlag) {console.log("左滑事件");this.setData({slipFlag: false})this.next()} else if (((this.data.startPoint.clientX - clientX) < -80) && this.data.slipFlag) {console.log("右滑事件");this.setData({slipFlag: false})this.prev()}},touchend:function() {this.setData({pageBackImage: this.data.imgList[this.data.imgList.length - this.data.pagenum - 1],transformCss: '', transformOrigin: '',clipPath2: 'clip-path: polygon(100% 100%, 100% 100%, 100% 100%)',clipPath1: '',})},//计算翻书效果flippingPage:function(clientX,clientY){// 本人比较懒,这里写死了书的宽度和高度let width = this.data.imgboxw; let height = this.data.imgboxh;let x = width - clientX;let y = height - clientY;let a = ((x/2 * x/2) + (y/2 * y/2)) / (x/2);let b = ((x/2 * x/2) + (y/2 * y/2)) / (y/2);a = a > width ? width : a;let angle = (Math.atan(a / b) * (180 / Math.PI));angle = 180 - angle * 2;this.setData({pageBackImage: this.data.imgList[this.data.imgList.length - this.data.pagenum - 1],transformCss: 'transform: rotateX(180deg) rotateZ('+ angle +'deg)', transformOrigin: 'transform-origin: right '+ (height - b) +'px',clipPath2: 'clip-path: polygon(100% 100%, ' + (width-a) +'px 100%, 100% ' + (height - b) + 'px)',clipPath1: 'clip-path: polygon(0% 0%, 0% 100%, ' + (width-a) +'px 100%, 100% ' + (height - b) + 'px, 100% 0%)',})},animate1(callback) {let clientX = this.data.imgboxw;let clientY = this.data.imgboxh;let timer = setInterval(() => {clientX -= 30;clientY -= 1;if (clientX < -this.data.imgboxw) {clientX = -this.data.imgboxw;clientY = this.data.imgboxh-1;this.flippingPage(clientX, clientY)clearInterval(timer);this.setData({transformCss: '', transformOrigin: '',clipPath2: 'clip-path: polygon(100% 100%, 100% 100%, 100% 100%)',clipPath1: '',})callback && callback();}this.flippingPage(clientX, clientY)}, 20);},animate2(callback) {let clientX = -this.data.imgboxw;let clientY = this.data.imgboxh;let timer = setInterval(() => {clientX += 30;clientY -= 1;if (clientX > this.data.imgboxw) {clientX = this.data.imgboxw;clientY = this.data.imgboxh-1;this.flippingPage(clientX, clientY)clearInterval(timer);this.setData({transformCss: '', transformOrigin: '',clipPath2: 'clip-path: polygon(100% 100%, 100% 100%, 100% 100%)',clipPath1: '',})callback && callback();}this.flippingPage(clientX, clientY)}, 20);},toHomePage() {this.setData({pagenum: 0})},toLastPage() {this.setData({pagenum: this.data.imgList.length - 1})},next() {let pagenum = this.data.pagenumif (pagenum > this.data.imgList.length - 2) return;this.animate1(() => {this.data._timer = setTimeout(()=>{clearTimeout(this.data._timer)pagenum++;this.setData({pagenum,clipPath1: ''})},0)})},prev() {let pagenum = this.data.pagenumif (pagenum <= 0) return;pagenum--;this.setData({pagenum,})this.animate2(() => {})},
css
.imgbox {width: 100%;position: relative;transform-style: preserve-3d;overflow: hidden;height: calc(100% - 170px);padding: 40rpx 0;background-color: #000000;
}
.list-pape,
.page-back {overflow: hidden;width: 100%;height: calc(100% - 80rpx);position: absolute;left: 0;top: 40rpx;/* box-shadow: 3px 0px 8px 0px #0000004d; */
}
.list-pape image,
.page-back image {width: 100%;height: 100%;
}.page-back {transform-origin: right bottom;pointer-events: none;filter: contrast(0.4);
}