手写一个 SVG 翻书轮播:模拟“翻页”动效的三种关键动画(无 JS)

在做网页、公众号、H5 时,只要涉及到“多图内容”,基本都会用到轮播。

但普通轮播效果就那几种:

  • 左右滑

  • 渐隐渐现

  • 上下切换

  • 自动跑马灯

效果单调、气质也普通。
如果要做成那种“翻书翻页”的质感,尤其像杂志翻页、相册翻页这种强拟物感动画,一般前端会:

  • 写一堆 CSS 3D

  • 加 perspective

  • 写 transform-origin

  • 再配 JS 控时序

光是翻一次页,都能写出几十行代码。


这篇文章要分享的是:
用纯 SVG + SMIL,就能做出一个完整循环的“翻页轮播”效果,而且不需要写 JS,也能自动循环播放。

这个翻页动效的底层链路来自 E2 编辑器里一个叫《循环翻页》的免费 SVG 组件,我把它拆解了一遍,自己重新做了一个可复用的版本,结构非常干净。

先上代码(为便于阅读我做了格式整理)👇


一、完整 SVG 翻页轮播代码(可直接预览效果)

代码如下:

<section name="preview-6" style="overflow:hidden;text-align:center;">
  <section powered-by="e2.cool" style="overflow:hidden;line-height:0;">
    <svg
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 1080 1080"
      width="100%"
    >
      <!-- 第1张图(底层) -->
      <g>
        <foreignObject x="0" y="0" width="1080" height="1080">
          <svg
            style='display:block;background-image:url("你的图片地址");background-size:100% auto;'
            viewBox="0 0 1080 1080"
          ></svg>
        </foreignObject>
      </g>

      <!-- 第2张图 -->
      <g>
        <!-- 翻页的倾斜 -->
        <animateTransform
          attributeName="transform"
          type="skewY"
          values="0;0;0;30"
          begin="0s"
          dur="6s"
          additive="sum"
          repeatCount="indefinite"
        ></animateTransform>

        <!-- 翻页过程透明度变化 -->
        <animate
          attributeName="opacity"
          values="1;1;1;0;0"
          keyTimes="0;0.333;0.666;0.888;1"
          begin="0s"
          dur="6s"
          repeatCount="indefinite"
        ></animate>

        <!-- 横向合页的缩放 -->
        <animateTransform
          attributeName="transform"
          type="scale"
          values="1 1;1 1;1 1;0 1"
          begin="0s"
          dur="6s"
          additive="sum"
          repeatCount="indefinite"
        ></animateTransform>

        <foreignObject x="0" y="0" width="1080" height="1080">
          <svg
            style='display:block;background-size:100%;background-image:url("你的图片地址");'
            viewBox="0 0 1080 1080"
          ></svg>
        </foreignObject>
      </g>

      <!-- 第3张图 -->
      <g>
        <animateTransform
          attributeName="transform"
          type="skewY"
          values="0;0;30;0"
          begin="0s"
          dur="6s"
          additive="sum"
          repeatCount="indefinite"
        ></animateTransform>

        <animate
          attributeName="opacity"
          values="1;1;0;0"
          keyTimes="0;0.333;0.555;1"
          begin="0s"
          dur="6s"
          repeatCount="indefinite"
        ></animate>

        <animateTransform
          attributeName="transform"
          type="scale"
          values="1 1;1 1;0 1;0 1"
          begin="0s"
          dur="6s"
          additive="sum"
          repeatCount="indefinite"
        ></animateTransform>

        <foreignObject x="0" y="0" width="1080" height="1080">
          <svg
            style='display:block;background-size:100%;background-image:url("你的图片地址");'
            viewBox="0 0 1080 1080"
          ></svg>
        </foreignObject>
      </g>

      <!-- 第4张图循环回到第 1 张 -->
      <g>
        <animateTransform
          attributeName="transform"
          type="skewY"
          values="0;30;0;0"
          begin="0s"
          dur="6s"
          additive="sum"
          repeatCount="indefinite"
        ></animateTransform>

        <animate
          attributeName="opacity"
          values="1;0;0;0"
          keyTimes="0;0.222;0.666;1"
          begin="0s"
          dur="6s"
          repeatCount="indefinite"
        ></animate>

        <animateTransform
          attributeName="transform"
          type="scale"
          values="1 1;0 1;0 1;0 1"
          begin="0s"
          dur="6s"
          additive="sum"
          repeatCount="indefinite"
        ></animateTransform>

        <foreignObject x="0" y="0" width="1080" height="1080">
          <svg
            style='display:block;background-size:100%;background-image:url("你的图片地址");'
            viewBox="0 0 1080 1080"
          ></svg>
        </foreignObject>
      </g>
    </svg>
  </section>
</section>

二、翻页轮播的三个关键动效原理

这个翻页动画不是随机堆 transform,它其实很有章法。

1)skewY —— 模拟书页“翻折角”的倾斜

核心一条就是:

type="skewY"

skewY 会让元素沿 Y 轴方向倾斜。想象一下:

  • 翻页时,书页右侧被抬起来

  • 左边还贴在书脊上

这时候视觉上就会出现类似“斜切”的错位感。

SVG 用 <animateTransform type="skewY"> 可以完美模拟这种 2D 倾斜。

不同页的 skew 曲线不同,就能形成:

  • 一张页刚翻起

  • 一张页开始落下

  • 另一张页已经翻到背面

这种层次分明的翻页节奏。


2)scale —— 横向收拢模拟“合页收紧效应”

翻页的过程中,书页会从外向内收:

  • 刚翻起时宽度几乎正常

  • 快要合上时会被视觉压缩

用 scale 做:

type="scale"
values="1 1; 0 1"

就代表:

  • X 缩放从 1 → 0

  • Y 保持 1(不变)

这就是 “书页合拢” 的视觉来源。


3)opacity —— 控制书页之间的遮盖关系

翻页过程有“前页遮住后页”“下一页渐显”的需求。

每一页都是:

<g>…</g>

每个 <g> 里设置透明度轨迹:

values="1;1;1;0;0"

就是:

  • 前半段完全可见

  • 后半段逐渐淡出

  • 到尾声完全隐藏

这样 3~4 页叠在一起,就能制造一个“真实翻书”必备的层次关系。


三、为什么不写 JS / CSS,而用 SVG?

原因很简单:

1)公众号、H5、编辑器环境对 JS 支持不稳定

SVG 动画(SMIL)是写在标签内部的,不依赖外部 JS,也不容易被过滤器吃掉。

2)SVG 可以无限缩放、适配所有屏幕尺寸

不用写 media query,不用算宽高比。

3)动画时间轴天然同步

多个 <animateTransform> 最怕“跑不同步”。
SVG 的动画天然使用统一 timeline,更容易做出整体节奏。

4)翻页效果本身就是图形学,用 transform 更自然

翻书不是左右滑动,而是倾斜 + 收拢 + 透明度变化。
SVG transform 的组合能比 CSS 更干净地表达“图像变形”。


四、想要改成自己的翻页轮播?你只要改三处

1. 换图

每个 <foreignObject> 的:

background-image:url("你的图.png")

替换掉即可。


2. 改翻页速度

6 秒一轮:

dur="6s"

改成 3s / 10s 都可以。


3. 调整翻页节奏

比如 skew 是否更明显,只要改:

values="0;0;0;30"

书页更立体,也可以调到:

values="0;0;0;50"

scale 阶段也可以手动改:

values="1 1; 0.6 1; 0 1"

更像图片从右边折回来。


五、如果你不想手写,E2 编辑器里有现成的免费组件

最后带一句实用信息:
如果你只是想把这个翻页效果快速用在公众号图文、活动轮播、节日海报里,其实可以直接去:

E2 编辑器 → 搜索「循环翻页」

这是一个 免费组件,特点是:

  • 只需要上传 3 张图 就能自动生成翻页轮播

  • 支持「自动循环」与「手动触发」

  • 导出的 SVG 可以再做二次开发

  • 所有动画参数都是开放的(可以继续在代码里微调)

相比很多 JS 插件或重型 H5 框架,这种纯 SVG 的“轻量轮播”在公众号环境里非常稳定,特别适合视觉要求高、动画节奏细腻的内容,比如:

  • 杂志风推文

  • 产品展示(翻页目录)

  • 影集 / 回忆录

  • 运营活动的节日页面

  • 书籍/专刊介绍页

如果你只是想“快速上效果”,直接用组件会更轻松。


结语

翻页轮播乍一看是一个“复杂动画”,但本质上拆开就是:

  • skew:模拟书页翻角

  • scale:模拟书页合拢

  • opacity:模拟遮挡关系

  • timeline 同步:SMIL 非常适合做节奏动画

最终形成一种“书页呼吸式切换”的质感,比普通轮播优雅太多。

如果你也想做一个“书本一样的轮播”,这份代码可以直接当模板;
如果更希望快速出活,可以直接用 E2 的《循环翻页》组件。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值