一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

分享之前使用HarmonyOS NEXT Canvas做的動態(tài)GIF視頻的一個案例,沒有感情,全是技術(shù)。

陳姚豐 ? 來源:jf_83680738 ? 作者:jf_83680738 ? 2025-03-16 15:56 ? 次閱讀
theme: fancy

hello,大家好,我是莓創(chuàng)-陳楊。最近忙著改圖表組件的BUG,還有定制化開發(fā)一些圖表。沒啥時間寫新東西,草稿里面放了十幾個要實(shí)現(xiàn)的案例分享,欠的實(shí)在太多了,后面再慢慢還吧。這次分享一下之前使用HarmonyOS NEXT Canvas做的動態(tài)視頻的一個案例,沒有感情,全是技術(shù)。

開發(fā)準(zhǔn)備

開發(fā)流程與進(jìn)度

這次整體開發(fā)流程主要如下:

  1. 獲取圖片素材列表數(shù)據(jù),初始化視頻的幀數(shù)以及canvas畫布
  2. 繪畫視頻控制器,編寫視頻按幀數(shù)播放的功能
  3. 動態(tài)切換幀數(shù)進(jìn)行播放
  4. 支持播放詞條進(jìn)行控制播放
  5. 添加音樂
  6. 導(dǎo)出視頻

目前已經(jīng)開發(fā)完第三步了,后面會繼續(xù)開發(fā),而且也會繼續(xù)分享出來。感興趣的開發(fā)可以關(guān)注一下。

代碼講解

接下來我簡單講解一下代碼,也是需要注意點(diǎn)

1、獲取圖片素材列表,大家想要生成什么GIF或者視頻就去找什么素材。可以用第三方的鏈接,可以用base64,可以用本地項(xiàng)目圖片。最后都通過ImageBitmap方法將圖片存儲為canvas渲染的像素數(shù)據(jù)。非常方面,在H5還要擔(dān)心跨域之類的問題。

let playTimer: number = 0
@Entry
@Component
export struct VideoEditing {
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  private scroller: Scroller = new Scroller()
  @State w: number = 400; // 編程畫板的寬度
  @State h: number = 760; // 編程畫板的尺寸
  @State levelList: any[] = [
    new ImageBitmap('common/images/icon0.png'),
    new ImageBitmap('common/images/icon1.png'),
    new ImageBitmap('common/images/icon2.png'),
    new ImageBitmap('common/images/icon3.png'),
    new ImageBitmap('common/images/icon4.png'),
    new ImageBitmap('common/images/icon5.png'),
    new ImageBitmap('common/images/icon6.png'),
    new ImageBitmap('common/images/icon7.png')
    ....
  ];

  build() {
    Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Start}) {
      Column() {
        Canvas(this.context)
          .onReady(() = > {
          })
          .width(this.w)
          .height(this.h)
          .backgroundColor('#fff')
      }.justifyContent(FlexAlign.Center).clip(true).width('100%').flexGrow(1).backgroundColor('#f8f8f8')
    }
  }
}

2、繪畫視頻控制器主體,這里主要控制變量就是視頻的幀數(shù)fps,再結(jié)合循環(huán)計時器形成一個小型播放器,循環(huán)器的時間規(guī)則就是1000 / fps,代表著每秒幾幀,想快就放大fps,想慢就縮小fps,是不是很簡單。

let playTimer: number = 0
@Entry
@Component
export struct VideoEditing {
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  private scroller: Scroller = new Scroller()
  @State w: number = 400; // 編程畫板的寬度
  @State h: number = 760; // 編程畫板的尺寸
  @State levelList: any[] = [
    ....
  ]; // 圖層list
  @State ispause: boolean = true // 是否是暫停狀態(tài)
  @State plusNum: number = 0 // 幀總量
  @State plusCount: number = 0 // 幀總量計數(shù)器(判斷循環(huán)次數(shù))
  @State count: number = 0 // 當(dāng)前幀
  @State fps: number = 25 // 25幀/秒
  @State fpsNumber: number = 2 // 25幀/秒
  @State recordFrom: number = 0 // 記錄起始幀
  @State recordTo: number = 0 // 記錄結(jié)束幀
  @State imgsLen: number = 0 // 記錄幀長度

  // 跳到某一幀
  goto (n: number) {
    this.count = n
    this.drawImg(this.levelList[n])
  }
  drawImg(img) {
    // const image = offCanvas.transferToImageBitmap()
    // this.context.transferFromImageBitmap(image)
    this.context.drawImage(img,0,0,this.w, this.h)
  }
  fromTo(from: number, to: number) {
    const self = this
    const fps = this.fps
    // 先清除上次未執(zhí)行完的動畫
    clearInterval(playTimer)
    const timeFn = (): undefined = > {
      if (self.ispause) {
        return
      }
      // 當(dāng)總量計數(shù)器達(dá)到幀總量的時候退出
      if (self.plusNum <= self.plusCount) {
        self.resetData()
        // clearInterval(playTimer)
        return
      } else {
        // 未達(dá)到,繼續(xù)循環(huán)
        // 幀計數(shù)器
        self.count++
        // 一次循環(huán)結(jié)束,重置keyCount為from
        if (self.count > to) {
          self.count = from
        }
        this.scroller.scrollTo({ xOffset: self.count * 150, yOffset: 0 })
        self.goto(self.count)
        // 總量計數(shù)器
        self.plusCount++
        return
      }
    }
    // 總量計數(shù)器
    this.plusCount = 0

    // 幀總量 幀數(shù)*循環(huán)次數(shù)first
    this.plusNum = to - from + 1
    this.ispause = false

    this.recordFrom = from
    this.recordTo = to

    timeFn()
    playTimer = setInterval(timeFn, 1000 / fps)
  }
  // 重置數(shù)據(jù) 停止并回到第一幀或cover幀
  resetData() {
    this.ispause = true
    clearInterval(playTimer)
    this.plusNum = 0
    this.plusCount = 0
    this.scroller.scrollTo({ xOffset: 0, yOffset: 0 })
    // 重置記錄
    this.recordFrom = 0
    this.recordTo = this.imgsLen - 1
    this.count = 0
  }
  build() {
    Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Start}) {
      Column() {
        Canvas(this.context)
          .onReady(() = > {
            this.goto(0)
          })
          .width(this.w)
          .height(this.h)
          .backgroundColor('#fff')
      }.justifyContent(FlexAlign.Center).clip(true).width('100%').flexGrow(1).backgroundColor('#f8f8f8')
      Column() {
        Flex({justifyContent: FlexAlign.SpaceBetween}) {
          Row() {
            Text(String(this.fps)).fontSize(15).margin({right: 4})
            Text('幀/秒').fontSize(12)
            Image($r('app.media.ic_public_spinner_small')).width(20)
          }.onClick(() = > {
            // this.showSex = true
            TextPickerDialog.show({
              range:  ['1', '12', '25', '30', '50', '60'],
              selected: this.fpsNumber,
              // selectedTextStyle: {color:'rgba(255, 80, 121, 1)'},
              onAccept: (value: TextPickerResult) = > {
                this.fpsNumber = Number(value.index)
                this.fps = Number(value.value)
              }
            })
          })
          Row() {
            Image($r('app.media.ic_public_play')).width(20)
              .onClick(() = > {
                this.imgsLen = this.levelList.length
                this.recordFrom = 0
                this.recordTo = this.imgsLen - 1
                this.fromTo(this.recordFrom, this.recordTo)
              })
            Image($r('app.media.ic_public_pause')).width(20)
          }
          Row() {
            Image($r('app.media.ic_public_music_filled')).width(20)
          }
        }.padding({top: 20, bottom: 20, left: 10, right: 10})
      }
    }.position({x: 0, y: 0}).width('100%').height('100%').backgroundColor('#fff').transition({ type: TransitionType.Insert, translate: { x: 0, y: '100%' } }).transition({ type: TransitionType.Delete, translate: { x: 0, y: '100%' } })
  }
}

以上就是前三步的實(shí)現(xiàn)代碼,這三個步驟整體并不難。在頁面能夠?qū)崿F(xiàn)簡單的播放之后,后面就是生成視頻或者GIF了。其實(shí)還有一個功能也很重要,就是導(dǎo)入視頻,解析視頻,然后就可以做視頻編輯器了,這個也是一個大工程,想玩的可以去嘗試嘗試

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • HarmonyOS
    +關(guān)注

    關(guān)注

    79

    文章

    2005

    瀏覽量

    31800
  • Harmony
    +關(guān)注

    關(guān)注

    0

    文章

    63

    瀏覽量

    2852
收藏 人收藏

    評論

    相關(guān)推薦

    HarmonyOS Next MQTT演示

    HarmonyOS Next MQTT演示
    發(fā)表于 11-07 16:54

    HarmonyOS NEXT 應(yīng)用開發(fā)練習(xí):智能視頻推薦

    、整體思路 本DEMO展示了如何在HarmonyOS NEXT平臺上開發(fā)智能視頻推薦應(yīng)用。
    發(fā)表于 01-02 16:26

    人類與機(jī)器人有感情產(chǎn)生嗎?

    `  之前看到周潤發(fā)的部電影里面的機(jī)器人,讓我對機(jī)器人有了新的看法。里面的那個機(jī)器人表情豐富、機(jī)智幽默。  現(xiàn)在人們疑惑的是人與人工智能的感情
    發(fā)表于 11-10 10:18

    Canvas怎么合成自定義Gif

    Canvas合成自定義Gif
    發(fā)表于 06-03 13:36

    HarmonyOS NEXT新能力,站式高效開發(fā)HarmonyOS應(yīng)用

    與調(diào)優(yōu)新場景,測試新體驗(yàn),以及讓元服務(wù)開發(fā)更簡單。 HarmonyOS NEXT開發(fā)者預(yù)覽版的發(fā)布,將為HarmonyOS應(yīng)用生態(tài)發(fā)展開啟
    發(fā)表于 08-14 15:08

    如何將MP4視頻轉(zhuǎn)換為GIF

    GIF。因此,在上述所有情況下,您都需要好的MP4到GIF轉(zhuǎn)換器。閱讀以下內(nèi)容,詳細(xì)了解如何使用不同的解決方案將?MP4轉(zhuǎn)換為GIF?
    的頭像 發(fā)表于 12-17 16:44 ?4480次閱讀

    HarmonyOS NEXT新能力,站式高效開發(fā)HarmonyOS應(yīng)用

    ,并分享了圍繞“次開發(fā),多端部署” “可分可合,自由流轉(zhuǎn)” “統(tǒng)生態(tài),原生智能”三大HarmonyOS應(yīng)用開發(fā)理念的實(shí)踐經(jīng)驗(yàn)。 而在8月5日,開發(fā)者主題演講上,華為對HarmonyOS
    的頭像 發(fā)表于 08-09 17:16 ?1438次閱讀

    HarmonyOS NEXT新能力,站式高效開發(fā)HarmonyOS應(yīng)用

    分享了圍繞 “次開發(fā),多端部署” “可分可合,自由流轉(zhuǎn)” “統(tǒng)生態(tài),原生智能” 三大HarmonyOS應(yīng)用開發(fā)理念的實(shí)踐經(jīng)驗(yàn)。 而在8月5日,開發(fā)者主題演講上,華為對HarmonyOS
    的頭像 發(fā)表于 08-11 12:10 ?1268次閱讀

    淘寶與華為合作將基于HarmonyOS NEXT啟動鴻蒙原生應(yīng)用開發(fā)

    1月25日,淘寶與華為舉辦鴻蒙合作簽約儀式,宣布將基于HarmonyOS NEXT啟動鴻蒙原生應(yīng)用開發(fā)。
    的頭像 發(fā)表于 01-26 16:14 ?1365次閱讀

    HDC 2024上,HarmonyOS NEXT有哪些精彩亮點(diǎn)值得期待?

    6月21日至6月23日,備受矚目的HDC2024華為開發(fā)者大會將在松山湖盛大舉辦。近日,官方對外發(fā)出了亮點(diǎn)日程海報,圍繞HarmonyOS?NEXT,大會都將帶來哪些精彩內(nèi)容呢?讓我們
    的頭像 發(fā)表于 06-19 17:02 ?733次閱讀
    HDC 2024上,<b class='flag-5'>HarmonyOS</b> <b class='flag-5'>NEXT</b>有哪些精彩亮點(diǎn)值得期待?

    華為“純血”鴻蒙系統(tǒng) HarmonyOS NEXT 將于9月底推出正式版

    HarmonyOS NEXT 將于今年 9 月底推出正式版本。 “從發(fā)布第一個版本到今年的 9 月份,這個(9 月)月底我們會正式發(fā)布 HarmonyOS
    的頭像 發(fā)表于 09-14 14:27 ?1996次閱讀

    華為HarmonyOS NEXT 10月8日開啟公測

    華為宣布,萬眾矚目的HarmonyOS NEXT操作系統(tǒng)將于10月8日正式開啟公測,標(biāo)志著這創(chuàng)新力作即將與廣大用戶見面。HarmonyOS NEX
    的頭像 發(fā)表于 09-24 15:41 ?1187次閱讀
    華為<b class='flag-5'>HarmonyOS</b> <b class='flag-5'>NEXT</b> 10月8日開啟公測

    AWTK 最新動態(tài):支持鴻蒙系統(tǒng)(HarmonyOS Next)

    為ToolkitAnyWhere,是ZLG傾心打造的套基于C語言開發(fā)的GUI框架。旨在為用戶提供功能強(qiáng)大、高效可靠、簡單易用、可輕松做出炫酷效果的GUI引擎,支
    的頭像 發(fā)表于 11-06 08:03 ?648次閱讀
    AWTK 最新<b class='flag-5'>動態(tài)</b>:支持鴻蒙系統(tǒng)(<b class='flag-5'>HarmonyOS</b> <b class='flag-5'>Next</b>)

    華為大氣啊!HarmonyOS NEXT公測發(fā)福利~這個可以有

    HarmonyOS NEXT火熱公測中,首批100萬名公測用戶速來領(lǐng)取多重權(quán)益!這波福利不錯
    的頭像 發(fā)表于 11-06 10:26 ?578次閱讀
    華為大氣?。?b class='flag-5'>HarmonyOS</b> <b class='flag-5'>NEXT</b>公測發(fā)福利~這個可以有

    HarmonyOS Next V2 @Event

    HarmonyOS Next V2 @Event 背景 在上節(jié)中,我們針對父子組件,講了關(guān)于傳遞數(shù)據(jù)的知識。我們了解到 @Local 是管理自己內(nèi)部的數(shù)據(jù)的, @Param 是負(fù)責(zé)接收父組件的數(shù)據(jù)
    的頭像 發(fā)表于 03-31 09:42 ?185次閱讀