微信小程序 - 3D 相册

思路

h5 通过 svg 和 CSS mask 属性,可以实现一些特殊形状的排版。

“ورحل مايكل هارت.. قدّيس الكتاب الرقمي! ماجد الحيدر في صمت وهدوء.. بعيداً عن أضواء الإعلام التي تتلقف أخبار هذا وذاك من نجوم الرياضة والسياسة والسينما.. وفي الوقت الذي واصل الناس التعبير عن حزنهم على رحيل مخترع كبير آخر هو ستيف جوبز عن طريق شراء المزيد من أجهزة الآي فون التي تصب المليارات في خزائن الشركة المنتجة.. رحل عن عالمنا، في بيت متواضع مزدحم بالكتب، رجل ”

摘录来自: Majid AlHydar. “Tribute to Michael Hart。” Apple Books.

《爱因斯坦全集》的负责人兼总编戴安娜·科默斯·布克沃尔德

(Diana Kormos Buchwald)认真阅读了本书,并就初稿做了大量评论,提出了许多改进意见。此外,她使我有机会能够查阅2006年才披露的所有新的爱因斯坦文献资料,并给予我具体指导。在我造访加州理工学院“爱因斯坦文稿计划”(Einstein Papers Project)期间,她热情地接待了我,并提供了许多方便。她工作相当投入,满怀奉献精神,为人风趣幽默,所有这些都使与她交住的人备感余切和愉悦。

经过实测,微信小程序也支持基本的 CSS mask,再结合 CSS transform 属性,就可以根据相册背景图绘制所需 svg 形状,实现 3D 透视效果。

  1. svg 生成,根据相册背景图,利用矢量软件或在线绘制工具生成 mask 所需矢量形状,然后转 base64 格式。
  2. transform 透视和定位,如果微信小程序使用 rpx,注意 rpx 和 px 转换。小技巧是 svg 和相册背景先 1:1 调整,然后再整体缩放。

代码和效果

<view class="album">
  <view class="cover_c">
    <!--- 第1页 2图 --->
    <view class="cover_1_c">
      <view class="transform-2p">
        <image class="img" src="{{ ... }}" mode="aspectFill" />
        <image class="img" src="{{ ... }}" mode="aspectFill" />
      </view>
    </view>
    
    ...

  </view>

  <image class="bg" src="bg_album.jpg" />
</view>
.album {
  width: 730rpx;
  height: 494rpx;
  margin: 0 auto 24rpx;
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: 20rpx;

  .bg {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1;
  }

  .cover_c {
    width: 100%;
    height: 100%;
    position: absolute;
    z-index: 2;
  }

  .cover_1_c {
    width: 310rpx;
    height: 310rpx;
    position: absolute;
    top: 139rpx;
    left: 100rpx;
    z-index: 1;

    -webkit-mask: url('data:image/svg+xml;charset=utf-8;base64,PHN2ZyB3aWR0aD0iOTgwIiBoZWlnaHQ9IjY2NCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICAgICAgICAgIDxwYXRoCiAgICAgICAgICAgICAgZD0ibTIwOC4wOTQ1MSwyMzguNDUxOTVsLTUyLjA5NDUxLDI1MC41NDgwNWMxOTEuODc1LC01NC4xNDExMyAyNjguODY1ODUsLTcyLjY1NDA5IDMzMS4zMjAxMiwtMzguMTUwNTZjLTIyLjA2NDAyLC01NC42NDcwMyAtMTc1Ljc4MDk5LC05OC4wMzA0MiAtMTgwLjMyMDEyLC0xMDYuNzE5ODNsMjYuNjIwMDUsLTEzOC4xNDI5M2MxLjczNDEyLC02LjI1OTQxIC04MS4yMjI2OSwxOS40MTU4NyAtMTI1LjUyNTU0LDMyLjQ2NTI3eiIKICAgICAgICAgICAgICBmaWxsPSJncmF5IgogICAgICAgICAgICAvPgogICAgICA8L3N2Zz4=')
      no-repeat;
    -webkit-mask-size: 730rpx 494rpx;
    -webkit-mask-position: -102rpx -138rpx;

    .transform-2p {
      width: 100%;
      height: 100%;
      margin-top: 2rpx;
      transform: perspective(300px) skewX(-10deg) skewY(-7deg) rotateY(-27deg) rotateZ(-2deg) rotateX(6deg);

      .img {
        width: 100%;
        height: 110rpx;
        margin-top: -2rpx;
        margin-left: -36rpx;
        background-color: @bg-img;

        &:first-child {
          margin-top: -17rpx;
        }
      }
    }

    ...
  }

  ...