微信小程序 Skyline Worklet ios Andorid 项目实战-02

微信小程序 最新推出的Skyline渲染以及打包ios、andorid查看各个技术平台很少有详细介绍与项目案例,下面是一个简单的壁纸项目开发实战案例,涵盖了从项目创建到功能实现的整个过程。

项目概述

我们开发的是一个小程序手机、平板、pc端壁纸项目。用户可以点赞、收藏、下载壁纸。虽然项目很简单,但项目中我们会涉及多语言、主题外观、适配ios andorid、手势系统、自定义tabbar、自定义appbar、复杂组件开发测试、自定义路由、 元素共享动画、以及一些算法如:发布订阅、线性插值、矩形插值等高阶内容。

微信小程序 Skyline Worklet ios Andorid 项目实战-01的视频

自定义tabbat

自定义appbar

因为小程序的appbar比较特殊,所以建议在appbar上使用px而不是rpx,应为rpx是逻辑像素,它不管设备的真实的像素,一刀切的把屏幕宽度分成750份,一份就是1rpx,这样的后果是在手机上看上去一切正常,如果使用平板打开 样式会乱掉。当然我们也可以 写一个rpx和px互换的工具方法,把px转成rpx后再使用也是可以的。util.js 工具类加入一下方法

/**
 * rpx或px相互转换
 * @param { String } unit 带单位的尺寸 rpx、px
 * @param { Number } screenWidth 屏幕宽度不是设备可用的宽度
 * @return { Number } 转换后的rpxn或px
 */
export const switchPxRx = (unit, screenWidth) => {
  if (!unit || typeof (unit) !== 'string') return new Error('带单位的尺寸叁数错误')
  if (!screenWidth || typeof (screenWidth) !== 'number') return new Error('设备宽度错误')
  const value = parseInt(unit, 10)
  const and = 0 - Number(unit.length - (value.toString().length))
  const type = unit.slice(and)
  if (type === 'px') return value / (screenWidth / 750)
  if (type === 'rpx') return value * screenWidth / 750
}

rpx和px互换的工具方法

容器组件iAppbar

项目根目录创建一个components文件夹 用来存放我们的所有组件。创建出一个appbar头部容器组件名字叫iAppbar

const app = getApp()
const wininfo = app.globalData.windowInfo
/**
 * 这是一个头部容器组件 主要以微信小程序胶囊作为计算基点, 分左中有三部分。
 */
Component({
  options: {
    addGlobalClass: true, // 使用全局样式
    virtualHost: true, // 虚拟化节点
    multipleSlots: true // 组件使用多个slot 必须配置 true 默认组件只能有一个slot
  },

  data: {
    contentStyle: `height: ${wininfo.clientRect.height}px`,
    wrapStyle: `height: ${wininfo.appbarHeight}px; padding-top:${wininfo.statusBarHeight}px; padding:${wininfo.statusBarHeight}px ${wininfo.padding}px 0 ${wininfo.padding}px`,
    rectStyle: `flex: ${wininfo.clientRect.width}px 0 0; height: ${wininfo.clientRect.height}px; border-radius: ${wininfo.clientRect.height * 0.5}px`,
  }
})
<view class="wrap" style="{{wrapStyle}}">
  <view style="{{rectStyle}}">
    <slot name="left"></slot>
  </view>
  <view class="content" style="{{contentStyle}}">
    <slot></slot>
  </view>
  <view style="{{rectStyle}}">
    <slot name="right"></slot>
  </view>
</view>
.wrap {
  width: 100vw;
  display: flex;
  align-items: center;
  box-sizing: border-box;
  background-color: transparent;
}

.content {
  flex: 1;
  height: 100%;
}

iAppbar是一个容器组件 设置 (virtualHost: true)虚拟化节点后不可在组件上使用样式 如下面写法是错误的,将没有效果:

<i-appbar style="width: 750rpx; height: 100rpx"></i-appbar>

头部容器组件

微信小程序引入字体图标

头部通用主组需要使用iconfont图片所有先引入图标 iconfont 我们在项目根目录创建 iconfont.wxss直接复制iconfont上项目的.css到iconfont.wxss, 再再app.wxss中引入字体 iconfont.wxss如下:

@font-face {
  font-family: "iconfont"; /* Project id 4848352 */
  src: url('//at.alicdn.com/t/c/font_4848352_f3cl6piqgkt.woff2?t=1742017152673') format('woff2'),
       url('//at.alicdn.com/t/c/font_4848352_f3cl6piqgkt.woff?t=1742017152673') format('woff'),
       url('//at.alicdn.com/t/c/font_4848352_f3cl6piqgkt.ttf?t=1742017152673') format('truetype');
}

.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
}

.i-meiyoushuju01::before {
  content: "\e627";
}

.i-guanbi1::before {
  content: "\e6f2";
}

.i-zujian::before {
  content: "\e61f";
}

.i-pianhaoshezhi-bai2::before {
  content: "\eaf1";
}

.i-baohumoshi::before {
  content: "\e63b";
}

.i-zhanghaoxiangguan::before {
  content: "\e698";
}

.i-duoyuyan::before {
  content: "\e654";
}

.i-zhutise::before {
  content: "\e643";
}

.i-xiazai1::before {
  content: "\e62e";
}

.i-shanchu::before {
  content: "\e74b";
}

.i-gouxuan::before {
  content: "\e631";
}

.i-anquanyinsi::before {
  content: "\e98b";
}

.i-fankui::before {
  content: "\e623";
}

.i-tubiao-::before {
  content: "\e62c";
}

.i-kefu1::before {
  content: "\e611";
}

.i-guanyu::before {
  content: "\e7e8";
}

.i-gengxin::before {
  content: "\e650";
}

.i-dianzan_kuai::before {
  content: "\ec8c";
}

.i-good::before {
  content: "\e62a";
}

.i-xihuan::before {
  content: "\e86f";
}

.i-xihuan1::before {
  content: "\e870";
}

.i-zhifeiji::before {
  content: "\e62d";
}

.i-shoucang::before {
  content: "\e613";
}

.i-xz::before {
  content: "\e603";
}

.i-haibao::before {
  content: "\e635";
}

.i-icon_386::before {
  content: "\e60f";
}

.i-xiazai::before {
  content: "\e660";
}

.i-fanhui1::before {
  content: "\e604";
}

.i-a-chexiaofanhui::before {
  content: "\e83d";
}

.i-quxian::before {
  content: "\e694";
}

.i-kefu::before {
  content: "\ec2e";
}

.i-saoyisao::before {
  content: "\e610";
}

.i-shezhi::before {
  content: "\e63a";
}

.i-mobile::before {
  content: "\e622";
}

.i-tablet::before {
  content: "\e670";
}

.i-leibie::before {
  content: "\e632";
}

.i-discoverbeifen::before {
  content: "\e602";
}

.i-wode1::before {
  content: "\e600";
}

.i-zuojiantou::before {
  content: "\e6e1";
}

.i-guanbi::before {
  content: "\e674";
}

.i-shaixuantubiaogaozhuanqu03::before {
  content: "\e6c6";
}

.i-youjiantou::before {
  content: "\e62b";
}

.i-shouye::before {
  content: "\e60d";
}

.i-diannao2::before {
  content: "\e61e";
}

.i-sousuo::before {
  content: "\e645";
}

.i-caidan::before {
  content: "\e601";
}
@import './iconfont.wxss';
page {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  font-size: 28rpx;
  color: #030303;
  background-color: transparent;
}

iHeader组件

好了可以开始开发iheader数据组件了,再组件下创建iHeader组件,首先引入iAppbar头部布局组件

{
  "component": true,
  "usingComponents": {
    "i-appbar":"../iAppbar"
  }
}

const app = getApp()
const wininfo = app.globalData.windowInfo
/**
 *  公共头部appbat
 * @param { Number} types 显示类型 0 默认页面头部 1  tabBar页面头部
 * @param { Number} screenType 屏幕类型 0 手机、1 平板、2 桌面
 * @param { Boolean} screenType 是否显示切换设备类型的图标按钮
 * @param { String} color 默认页面头部字体颜色
 * @param { Number} backl 默认页面返回按钮边距(内边距)
 * @param { Boolean} backi 默认页面是否显示手机切换图标
 */
Component({
  options: {
    addGlobalClass: true // 全局样式
  },
  behaviors: [],
  properties: {
    types: {
      type: Number,
      value: 1
    },
    screenType: {
      type: Number,
      value: 0
    },
    showSType: {
      type: Boolean,
      value: true
    },
    color: {
      type: String,
      value: 'black'
    },
    backl: {
      type: Number,
      value: 0
    },
    backi: {
      type: Boolean,
      value: false
    }
  },
  observers: {

  },
  data: {
    wininfo,

  },
  methods: {
    // 菜单事件
    onMenu(e) {
      this.triggerEvent('menu', e)
    },
    // 屏幕类型事件
    onClientType() {
      // 短时间振动 [heavy:重、medium:中、 light:轻]
      wx.vibrateShort({ type: 'medium' })
      // 0:手机、1:平板、2:PC
      let currentScreenType = this.data.screenType + 1
      if (currentScreenType > 2) currentScreenType = 0
      // 当前选择的显示模式保存本地
      wx.setStorageSync('screen', currentScreenType)
      // 更新全局数据
      app.globalData.screenType = currentScreenType
      // 触发事件
      this.triggerEvent('sctype', currentScreenType)
    },
    // 返回
    onBack() {
      wx.navigateBack()
    }
  }
})
<wxs module="filter" src="./filter.wxs" />
<i-appbar>
  <view slot="left" class="left">
    <block wx:if="{{types === 1}}">
      <view class="item" style="line-height: {{wininfo.clientRect.height}}px;" catch:tap="onMenu">
        <text class="iconfont i-caidan text-{{skin}}" style="font-size: 18px"></text>
      </view>
      <view class="item" style="line-height: {{wininfo.clientRect.height}}px; justify-content: center;" catch:tap="onClientType">
        <block wx:if="{{showSType}}">
          <text class="iconfont i-{{filter.screen_type(screenType)}} text-{{skin}}" style="font-size: {{filter.screen_size(screenType)}}px"></text>
        </block>
      </view>
    </block>
    <view wx:else class="back-default" catch:tap="onBack" style="padding-left: {{backl}}px;width: 100%; height: 100%">
      <text class="iconfont i-a-chexiaofanhui" style="color:{{color}}"></text>
      <view wx:if="{{backi}}" class="item" style="line-height: {{wininfo.clientRect.height}}px; margin-left: 20px; text-align: right" catch:tap="onClientType">
        <block wx:if="{{showSType}}">
          <text class="iconfont i-{{filter.screen_type(screenType)}}" style="font-size: {{filter.screen_size(screenType)}}px; color: {{color}}"></text>
        </block>
      </view>
    </view>
  </view>
  <view class="content">
    <slot></slot>
  </view>
</i-appbar>
.left {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
}

.left>.item {
  width: 50%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.menu {
  background-color: rgba(255, 255, 255, 0.692);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(10rpx);
}

.left>.item>text {
  font-size: 34rpx;
  font-weight: 500;
}

.text-light {
  color: black;
}

.text-dark {
  color: #f0f0f0;
}

.back-default {
  width: 50%;
  height: 100%;
  display: flex;
  align-items: center;
  box-sizing: border-box;
}

.back-default>text {
  font-size: 24px;
  transform-origin: center center;
  box-sizing: border-box;
}

.content {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  overflow: hidden;
  box-sizing: border-box;
}

需要注意的是 .wxs 只能用es5 写 不支持 es5 以上语法。

var filter = {
  screen_type: function (type) {
    return type === 0 ? 'mobile' : type === 1 ? 'tablet' : 'diannao2'
  },
  screen_size: function (type) {
    return type === 0 ? 21 : type === 1 ? 20 : 20
  }
}

module.exports = {
  screen_type: filter.screen_type,
  screen_size: filter.screen_size
}

使用示例-1

{
  "component": true,
  "usingComponents": {
    "i-header":"../../components/iHeader"
  }
}
<view style="width: 100vw; height: 100vh; background-color: rgba(255, 0, 0, 0.2);">
  <i-header></i-header>
</view>

使用示例-2

<view style="width: 100vw; height: 100vh; background-color: rgba(0, 255, 255, 0.5);">
  <i-header showSType="{{false}}"></i-header>
</view>

使用示例-3

<view style="width: 100vw; height: 100vh; background-color: rgba(255, 0, 0, 0.7);">
  <view style="width: 100%; background-color: white;">
    <i-header types="{{0}}">
      <view style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;"><text>个人中心</text></view>
    </i-header>
  </view>
</view>

iHeader 组件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值