微信小程序实现翻书效果

文章介绍了如何在微信小程序中创建类似翻书的效果,通过监听touch事件,结合CSS3D变换和clip-path属性来实现页面的动态翻转。作者对比了使用Turn.js库的不便,提出了一种利用绝对定位和计算拖动角度的自定义解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近要在微信小程序里实现一个类似翻页的场景,网上翻看了多个案例无非就两种实现,第一种通过css 3d变换+动画实现,第二使用Turn.js现成库。前者实现效果一般,后者js库是基于古老的JQuery来实现的并没办法移植到小程序了里。

下面就自己调研了一下turnjs来实现小程序的简单版本

turnjs效果截图

我的实现思路:

  1. 排版布局,通过绝对定位方式实现书页堆叠到一起就行(随意发挥)
  2. 监听touchmove事件,来确定拖拽时的动态坐标
  3. 根据拖拽页角的位置来计算翻页的角度和大小
  4. 通过css transfrom来创建一个背面露出来的部分
  5. 通过css clip-path来切出来下页露出来的部分(这里我的实现方案和turnjs不太一致,因为我在开发过程中发现clip-path这个属性实现起来更方便)
  6. 最后实现自动翻页

上代码:

WXML:

<!-- 书页 -->
<view
      wx:for="{{paper}}" 
      hidden="{{pagenum > paper.length - index - 1}}"
      wx:key="index"
      class="list-pape" 
      style="{{index == paper.length - pagenum - 1 ? clipPath1 : ''}}"
      catchtouchstart="touchstart"
      catchtouchmove="touchmove"
      catchtouchend="touchend">
      <image src="{{item}}"></image>
    </view>
<!-- 背面部分 -->
<view class="page-back" style="{{transformCss}};{{clipPath2}};{{transformOrigin}}">
      <image src="{{pageBackImage1}}"></image>
    </view>

JS(核心代码):

touchmove(e){
    let clientX = e.touches[0].clientX;
    let clientY = e.touches[0].clientY;
    this.flippingPage(clientX,clientY);
  },
//计算翻书效果
flippingPage(clientX,clientY){
    // 本人比较懒,这里写死了书的宽度和高度
    let width = 287; 
    let height = 450;

    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.paper[this.data.paper.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%)',
    })
  },

解释下这里的计算逻辑:

示例图1
示例图1
  1. 这里的clipPath1是示例图1的露出部分的裁剪区域,实现这里效果,其实就是对上一页的(p1-p2-p3-p4-p5)坐标的裁剪
  2. 那剩下的关键就是算出O-P3和O-P4的距离(三角函数自行推导)
  3. 最后得出P1-P5的所有坐标,所得样式为: 'clip-path: polygon(p1,p2,p3,p4,p5)'
321
示例图2
  1.  这里的clipPath2是示例图2的背面部分的裁剪区域 
  2. 这里做红色背面部分其实也是对上一页进行 (镜像 - 旋转 - 裁剪) 所得
  3. 旋转角度为:2倍的∠ap4p3
  4. 裁剪区域为红色区 a-p4-p3
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值