微信小程序共享元素+ page-container假页实现弹出效果

1.实现效果

微信小程序共享元素+ page-container假页实现弹出效果_第1张图片

2.实现原理

page-container

page-container
小程序如果在页面内进行复杂的界面设计(如在页面内弹出半屏的弹窗、在页面内加载一个全屏的子页面等),用户进行返回操作会直接离开当前页面,不符合用户预期,预期应为关闭当前弹出的组件。 为此提供“假页”容器组件,效果类似于 popup 弹出层,页面内存在该容器时,当用户进行返回操作,关闭该容器不关闭页面。返回操作包括三种情形,右滑手势、安卓物理返回键和调用 navigateBack 接口。

微信小程序共享元素+ page-container假页实现弹出效果_第2张图片

  • tip: 当前页面最多只有 1 个容器,若已存在容器的情况下,无法增加新的容器。
  • tip: wx.navigateBack 无法在页面栈顶调用,此时没有上一级页面 示例代码。
    eg:
<page-container show="{{show}}" round="{{round}}" overlay="{{overlay}}" duration="{{duration}}" position="{{position}}" close-on-slide-down="{{false}}" bindbeforeenter="onBeforeEnter" bindenter="onEnter" bindafterenter="onAfterEnter" bindbeforeleave="onBeforeLeave" bindleave="onLeave" bindafterleave="onAfterLeave" bindclickoverlay="onClickOverlay" custom-style="{{customStyle}}" overlay-style="{{overlayStyle}}">
</page-container>

share-element
共享元素是一种动画形式,类似于 flutter Hero动画,表现为元素像是在页面间穿越一样。该组件需与 page-container 组件结合使用。
使用时需在当前页放置 share-element 组件,同时在 page-container 容器中放置对应的 share-element 组件,对应关系通过属性值 key 映射。当设置 page-container 显示时,transform 属性为 true 的共享元素会产生动画。当前页面容器退出时,会产生返回动画。

微信小程序共享元素+ page-container假页实现弹出效果_第3张图片

 <share-element class="avatar" duration="{{duration}}" key="avatar" transform>
  <image style="width: 40px;border-radius: 50%;" mode="widthFix" src="{{contact.img}}" />
 </share-element>
 <share-element class="name" key="name" duration="{{duration}}" transform>
   {{contact.name}}
 </share-element>

key值映射:

page-container中的share-element相绑定。

3.缩放效果

实现一个缩放效果,将元素大小放到share-element标签上。
微信小程序共享元素+ page-container假页实现弹出效果_第4张图片

4.实现代码

<view>
  <view class="screen screen1">
    <block wx:for="{{contacts}}" wx:key="id" wx:for-item="contact">
      <view class="contact" bindtap="showNext" data-idx="{{index}}">
        <share-element class="avatar" key="avatar" duration="{{duration}}" transform="{{transformIdx === index}}">
          <image mode="widthFix" src="{{contact.img}}"></image>
        </share-element>
        <share-element duration="{{duration}}" class="name" key="name" transform="{{transformIdx === index}}">
          {{contact.name}}
        </share-element>
        <view class="list">
          <view>手机号: {{contact.phone}}</view>
          <view>邮箱: {{contact.email}}</view>
        </view>
      </view>
    </block>
  </view>
</view>
<page-container show="{{show}}" overlay="{{overlay}}" close-on-slide-down duration="{{duration}}" position="{{position}}" bindbeforeenter="onBeforeEnter" bindenter="onEnter" bindafterenter="onAfterEnter" bindbeforeleave="onBeforeLeave" bindleave="onLeave" bindafterleave="onAfterLeave" bindclickoverlay="onClickOverlay">
  <view class="screen screen2">
    <view class="contact">
      <share-element class="avatar ava_pa" duration="{{duration}}" key="avatar" transform>
        <image mode="widthFix" src="{{contact.img}}" />
      </share-element>
      <share-element class="name" key="name" duration="{{duration}}" transform>
        {{contact.name}}
      </share-element>
      <view class="paragraph {{show ? 'enter' : ''}}">
        共享元素是一种动画形式,类似于 flutter Hero动画,表现为元素像是在页面间穿越一样。该组件需与 page-container 组件结合使用。
        使用时需在当前页放置 share-element 组件,同时在 page-container 容器中放置对应的 share-element 组件,对应关系通过属性值 key 映射。
        当设置 page-container 显示时,transform 属性为 true 的共享元素会产生动画。当前页面容器退出时,会产生返回动画。
        <view></view>
        小程序如果在页面内进行复杂的界面设计(如在页面内弹出半屏的弹窗、在页面内加载一个全屏的子页面等),用户进行返回操作会直接离开当前页面,不符合用户预期,预期应为关闭当前弹出的组件。 为此提供“假页”容器组件,效果类似于 popup 弹出层,页面内存在该容器时,当用户进行返回操作,关闭该容器不关闭页面。返回操作包括三种情形,右滑手势、安卓物理返回键和调用 navigateBack 接口。
      </view>
      <button class="screen2-button" bindtap="showPrev" hidden="{{!show}}" hover-class="none">Click Me</button>
    </view>
  </view>
</page-container>
/* pages/jsCase/pageCon/index.wxss */
page {
  color           : #333;
  background-color: #fff;
  overflow        : hidden;
}

button {
  border-radius     : 60rpx;
  border            : 0 solid orange;
  background-color  : orange;
  color             : #fff;
  font-size         : 120%;
  padding           : 8px 16px;
  outline-width     : 0;
  -webkit-appearance: none;
  box-shadow        : 0 8px 17px rgba(0, 0, 0, 0.2);
}

.screen {
  position                  : absolute;
  top                       : 0;
  bottom                    : 0;
  left                      : 0;
  right                     : 0;
  padding                   : 16px;
  -webkit-overflow-scrolling: touch;
}

.contact {
  position        : relative;
  padding         : 16px;
  background-color: #fff;
  width           : 100%;
  height          : 100%;
  box-sizing      : border-box;
}

.avatar {
  position     : absolute;
  top          : 16px;
  left         : 16px;
  font-size    : 0;
  border-radius: 50%;
  width        : 160rpx;
  height       : 160rpx;
  overflow     : hidden;
}

.avatar image {
  width : 100%;
  height: 100%;
}

.ava_pa {
  width : 80rpx;
  height: 80rpx;
}

.ava_pa image {
  width : 100%;
  height: 100%;
}

.name {
  height     : 65px;
  font-size  : 2em;
  font-weight: bold;
  text-align : center;
  margin     : 10px 0;
}

.list {
  padding-top : 8px;
  padding-left: 32px;
}

.screen1 {
  overflow-y: scroll;
  padding   : 0;
}

.screen1 .contact {
  margin       : 16px;
  height       : auto;
  width        : auto;
  box-shadow   : 0 2px 5px 0 rgba(0, 0, 0, 0.2);
  border-radius: 20rpx;
  overflow     : hidden;
}

.screen2-button {
  display: block;
  margin : 24px auto;
}

.paragraph {
  -webkit-transition: transform ease-in-out 300ms;
  transition        : transform ease-in-out 300ms;
  -webkit-transform : scale(0.6);
  transform         : scale(0.6);
  color             : #999;
  font-size         : 27rpx;
}

.enter.paragraph {
  transform: none;
}
Page({

  /**
   * 页面的初始数据
   */
  data: {
    contacts: [{
      id: 1,
      name: 'susu1',
      img: 'https://i.postimg.cc/mgsKJGLw/susu1.jpg',
      phone: '0101 123456',
      mobile: '0770 123456',
      email: '[email protected]'
    },
    {
      id: 2,
      name: 'susu2',
      img: 'https://i.postimg.cc/mgsKJGLw/susu1.jpg',
      phone: '0101 123456',
      mobile: '0770 123456',
      email: '[email protected]'
    },
    {
      id: 3,
      name: 'susu3',
      img: 'https://i.postimg.cc/mgsKJGLw/susu1.jpg',
      phone: '0101 123456',
      mobile: '0770 123456',
      email: '[email protected]'
    },
    {
      id: 4,
      name: 'susu4',
      img: 'https://i.postimg.cc/mgsKJGLw/susu1.jpg',
      phone: '0101 123456',
      mobile: '0770 123456',
      email: '[email protected]'
    },
    {
      id: 5,
      name: 'susu5',
      img: 'https://i.postimg.cc/mgsKJGLw/susu1.jpg',
      phone: '0101 123456',
      mobile: '0770 123456',
      email: '[email protected]'
    },
    {
      id: 6,
      name: 'susu6',
      img: 'https://i.postimg.cc/mgsKJGLw/susu1.jpg',
      phone: '0101 123456',
      mobile: '0770 123456',
      email: '[email protected]'
    },
    {
      id: 7,
      name: 'susu7',
      img: 'https://i.postimg.cc/mgsKJGLw/susu1.jpg',
      phone: '0101 123456',
      mobile: '0770 123456',
      email: '[email protected]'
    },
    {
      id: 8,
      name: 'susu8',
      img: 'https://i.postimg.cc/mgsKJGLw/susu1.jpg',
      phone: '0101 123456',
      mobile: '0770 123456',
      email: '[email protected]'
    }
    ],
    contact: {},
    transformIdx: 0,
    position: 'center',
    duration: 300,
    show: false,
    overlay: false
  },
  onLoad: function (options) {
    this.setData({
      contact: this.data.contacts[0]
    })
  },

  showNext(e) {
    const idx = e.currentTarget.dataset.idx;
    this.setData({
      show: true,
      contact: this.data.contacts[idx],
      transformIdx: idx
    })
  },

  showPrev() {
    this.setData({
      show: false
    })
  },

  onBeforeEnter(res) {
    console.log(res)
  },
  onEnter(res) {
    console.log(res)
  },
  onAfterEnter(res) {
    console.log(res)
  },
  onBeforeLeave(res) {
    console.log(res)
  },
  onLeave(res) {
    console.log(res)
  },
  onAfterLeave(res) {
    console.log(res)
  },
})

5更多小程序demo,尽在苏苏的码云如果对你有帮助,欢迎你的star+订阅!

你可能感兴趣的:(微信小程序,微信小程序,动画,flutter)