用戶
 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

掃一掃,登錄網站

小程序社區 首頁 教程 實戰教程 查看內容

視頻無縫切換,預加載圖片資源等小程序優化

Rolan 2020-10-12 10:05

沒啥別的理由,就是閑的。最近又開始寫小程序了,不過心態不太一樣了,因為其實大家都是js。你不能總是覺得小程序low,其實人家的思維邏輯都是互通的。 ...

沒啥別的理由,就是閑的。最近又開始寫小程序了,不過心態不太一樣了,因為其實大家都是js。你不能總是覺得小程序low,其實人家的思維邏輯都是互通的。

今天把一些性能優化的解決方案拿出來分享下。能比較有效的解決頁面的一些卡頓和存在的一些問題

提示:博主用uniapp框架,但是原理都是一樣的,一些uniapp的api,你把uni替換成wx就OK了

一、data數據的性能優化,基本操作

這個其實和vue一個道理,所以大家不要把不參與渲染的數據定義在data里面了,不管是用了框架的還是原生小程序框架的。最好是大家把未定義渲染的數據放在created開始,進行約定規范,能大幅降低渲染成本。

再一個,如果你的數據不進行渲染操作,那么比如for循環賦值之類的操作,最好是先存儲一下變量。最后再賦值回去。能減少無意間的性能開銷,這個主要是針對vue,react框架這類框架。

舉例:

this.list.map()

改為

const list = this.list

list.map()

this.list = list

這樣不只是性能優化,你的代碼整潔度也能大幅上升

二、路由優化,能大幅降低性能問題

首先微信小程序為了性能優化,對頁面進行了10層最大緩存的處理,并且當10層緩存滿了之后,navigateTo函數會直接報錯,無法使用。除了我們一般經常需要注意頁面層級問題外,其實還有別的方式來解決這個問題。當然一般的電商購物類的頁面沒有這么苛刻。但是這次公司的app是視頻播放類app,本身視頻播放就很吃性能,而且看似頁面就那么幾個,但是極度容易出現層級滿了,然后頁面跳轉失效問題。

如果用reLaunch會釋放資源,那么緩存失效,更卡

redirectTo呢依舊無法避免層級超過10層問題

所以就有了下面這個函數

/*
{
 url: 'pages/index',
 type: 'navigate' //redirect分別對應navigateTo和redirectTo
}
*/
const pageJump = ({
 url,
 type = 'navigate'
}) => {
 const pageStack = getCurrentPages()
 const pageLen = pageStack.length
 const home = pageLen + 1 //如果需要返回首頁
 // 獲取頁面所在棧位置
 const page = u => {
    //獲取指定頁面所在數
    for (let i = 0; i < pageStack.length; i++) {
   if (pageStack[i].route === u) {
    return i
   }
    }
 }
 const pa1 = page(pageStack[pageLen - 1].route) // 當前頁數
 const pa2 = page(url) // 需要跳轉的頁
 //實際需要跳轉的頁數
 const pageNum = pa1 - pa2
 if (pageNum >= 0) {
    uni.navigateBack({
   delta: pageNum
    })
    return true
 }
 if (type === 'navigate') {
    uni.navigateTo({
   url: '/' + url
    })
    return true
 }
 if (type === 'redirect') {
    uni.redirectTo({
   url: '/' + url
    })
    return true
 }
}
復制代碼

使用很簡單,你直接傳入對應的下一個頁面的地址就行了,注意不要有前面的‘/’

這樣頁面在跳轉的時候就會優先找歷史中緩存的頁面,沒有的情況下才會新開頁面。有效避免了10層最大緩存問題,并且現在流暢性提高一個檔次(因為會復用緩存)。

三、小程序模擬multipart/form-data數據提交和post大數據引發的問題

這個不是性能問題,屬于個人對于小程序框架的bug踩坑

1、首先小程序一般是不支持formdata方式的,我們改造之后變成可以做到

header部分

header: {
 'content-type': 'multipart/form-data; boundary=XXX'
},
復制代碼

data傳參部分用這個函數處理一下

// 修改為formdata
getformdata(obj = {}) {
 let result = ''
 for (let name of Object.keys(obj)) {
  let value = obj[name];
  result +=
   '\r\n--XXX' +
   '\r\nContent-Disposition: form-data; name=\"' + name + '\"' +
   '\r\n' +
   '\r\n' + value
 }
 return result + '\r\n--XXX--'
}
復制代碼

這個當初要這樣做是因為曠視的人臉識別接口需要base64數據并且需要是formdata方式進行上傳

2、引發的小程序真機調試的bug

當post里面的data數據超過100kb會直接無法請求接口數據,導致接口函數直接沒有任何執行效果。萬分注意該問題

四、圖片壓縮問題

除了小程序官方提供的圖片壓縮函數wx.compressImage,我們還可以用canvas進行圖片壓縮,同時我比較不推薦官方的wx.compressImage,因為這個api會導致相冊新增圖片。像我之前的人臉識別頻繁拍照的,那真是災難。多出來幾千張照片

函數呢寫好了,

async compress({ w, h, canvaId, quality = 0.1, src = '' }) {
   const ctx = uni.createCanvasContext('compress')
   const [, img] = await uni.getImageInfo({ src })
   const { path, width, height } = img
   ctx.drawImage(path, 0, 0, width, height, 0, 0, w, h) //描述圖片到畫布上
   return new Promise((reslove, reject) => {
    ctx.draw(false, async () => {
     const [err, nimg] = await uni.canvasToTempFilePath({
        fileType: 'jpg',
        canvasId: 'compress',
        quality: quality
     })
     if (err) {
        reject(err)
        return false
     } else {
        reslove(nimg.tempFilePath)
     }
    })
   })
    }
復制代碼

使用

const img = await this.compress({
   w: windowWidth, // 希望的圖片寬高
   h: windowHeight,
   canvaId: 'compress',
   quality: 0.5, // 壓縮質量
   src:
    'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1602222973914&di=80f148ded356938570ed00fe9f68b816&imgtype=0&src=http%3A%2F%2Fwww.deskcar.com%2Fdesktop%2Ffengjing%2F2007125102851%2F10.jpg'
    })
復制代碼

注意html部分

這里我提供的函數沒有對canvas的圖片的寬高動態變化,這個大家注意下。在getImageInfo這個接口之后注意要給canvas賦值下圖片本身的寬高。避免礦高比變形。

五、圖片預加載

這個其實就比較常用,特別是我們這邊有幾個比較大的前置圖片,如果進入頁面再加載那么背景圖就無法里面加載好。

這里用 uni.getImageInfo({ src: ‘’ })就可以了,注意看下官方的api,是在success之后會得到一個本地的臨時圖片地址,我們拿這個地址去全局使用就行了

六、ios和安卓多個視頻交替切換,會黑一下的問題

這個原因是因為視頻播放之前需要進行解碼,而解碼是需要時間的,那么在這個之前,播放肯定是黑的。安卓還好,ios非常嚴重。產品大大說這個必須要改

1、我們這個是多個視頻切換,那么我們增加背景視頻或者背景圖片避免黑屏尷尬

2、但是這樣我們如果只是監聽onplay是不行的,還是會比較明顯的黑一下

并且這里引出一個bug,當多個視頻之間相互切換的時候,上一個視頻幀數據會影響下一個視頻幀數據。如果是單純的去監聽api也是沒有用的。

最后我的代碼是這樣的。做到了無縫切換的感覺

<template>
 <view>
    <video
   class="vie"
   :show-fullscreen-btn="false"
   :show-play-btn="false"
   :show-center-play-btn="false"
   :enable-progress-gesture="false"
   loop
   :controls="false"
   muted
   :autoplay="true"
   :style="{ 'z-index': isplay ? 1 : 100 }"
   src="https://dtman.guiji.ai/nfs/ss-file/xz/v1/video/background_2.mp4"
    ></video>
    <video
   class="vie"
   :show-fullscreen-btn="false"
   :show-play-btn="false"
   :show-center-play-btn="false"
   :enable-progress-gesture="false"
   :style="{ 'z-index': isplay ? 100 : 1 }"
   :controls="false"
   @timeupdate="ontimeupdate"
   @ended="onended"
   :src="show"
   :initial-time='0.01'
   :autoplay="true"
    ></video>
    <button style="top: 300px;" @click="next">下一個視頻</button>
 </view>
</template>
<script>
export default {
 data() {
    return {
   isplay: false, // 是否播放了
   show: '', // 播放的視頻地址
    }
 },
 created() {
    // 這里定義的變量不會參與渲染
    this.check = false // 當前是否切換地址了
    this.index = 0 
    this.src = [
    ‘公司的視頻,自己換’,
                ‘公司的視頻,自己換’,
                ‘公司的視頻,自己換’,
                ‘公司的視頻,自己換’,
     ]
   },
   methods: {
    next() {
     this.isplay = false
     this.show = ''

     if (this.index === this.src.length - 1) {
        this.index = 0
     }
     // 模擬接口請求,500毫秒延遲
     setTimeout(() => {
        this.show = this.src[this.index] //+ '?t=' +  new Date().getTime()
        this.index = this.index + 1
        this.check = true
     }, 500)
    },
    onended() {
     this.isplay = false
    },
    //監聽視頻播放時間更新
    ontimeupdate(e) {
     const currentTime = e.detail.currentTime
     // 排除干擾因素
     if (currentTime <= 0) return false

     // 只有當前未播放,切換視頻地址情況下,并且時間開始為零點幾才可以撤銷遮罩視頻
     // 原理:多個視頻切換播放的時候上一個視頻播放幀會因為卡頓等問題延遲到下一個視頻播放
     if (!this.isplay && this.check && currentTime.toString().substring(0, 1) === '0') {
        this.isplay = true
        this.check = false
     }
    }
   }
  }
  </script>

作者:海天醬油_沃利貝爾
來源:掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
鮮花
鮮花
雞蛋
雞蛋
分享至 : QQ空間
收藏
时时彩彩票app下载手机版