theme: fancy
hello,大家好,我是莓創-陳楊。最近忙著改圖表組件的BUG,還有定制化開發一些圖表。沒啥時間寫新東西,草稿里面放了十幾個要實現的案例分享,欠的實在太多了,后面再慢慢還吧。這次分享一下之前使用HarmonyOS NEXT Canvas做的動態視頻的一個案例,沒有感情,全是技術。
開發準備
開發流程與進度
這次整體開發流程主要如下:
- 獲取圖片素材列表數據,初始化視頻的幀數以及canvas畫布
- 繪畫視頻控制器,編寫視頻按幀數播放的功能
- 動態切換幀數進行播放
- 支持播放詞條進行控制播放
- 添加音樂
- 導出視頻
目前已經開發完第三步了,后面會繼續開發,而且也會繼續分享出來。感興趣的開發可以關注一下。
代碼講解
接下來我簡單講解一下代碼,也是需要注意點
1、獲取圖片素材列表,大家想要生成什么GIF或者視頻就去找什么素材。可以用第三方的鏈接,可以用base64,可以用本地項目圖片。最后都通過ImageBitmap方法將圖片存儲為canvas渲染的像素數據。非常方面,在H5還要擔心跨域之類的問題。
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、繪畫視頻控制器主體,這里主要控制變量就是視頻的幀數fps,再結合循環計時器形成一個小型播放器,循環器的時間規則就是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 // 是否是暫停狀態
@State plusNum: number = 0 // 幀總量
@State plusCount: number = 0 // 幀總量計數器(判斷循環次數)
@State count: number = 0 // 當前幀
@State fps: number = 25 // 25幀/秒
@State fpsNumber: number = 2 // 25幀/秒
@State recordFrom: number = 0 // 記錄起始幀
@State recordTo: number = 0 // 記錄結束幀
@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
// 先清除上次未執行完的動畫
clearInterval(playTimer)
const timeFn = (): undefined = > {
if (self.ispause) {
return
}
// 當總量計數器達到幀總量的時候退出
if (self.plusNum <= self.plusCount) {
self.resetData()
// clearInterval(playTimer)
return
} else {
// 未達到,繼續循環
// 幀計數器
self.count++
// 一次循環結束,重置keyCount為from
if (self.count > to) {
self.count = from
}
this.scroller.scrollTo({ xOffset: self.count * 150, yOffset: 0 })
self.goto(self.count)
// 總量計數器
self.plusCount++
return
}
}
// 總量計數器
this.plusCount = 0
// 幀總量 幀數*循環次數first
this.plusNum = to - from + 1
this.ispause = false
this.recordFrom = from
this.recordTo = to
timeFn()
playTimer = setInterval(timeFn, 1000 / fps)
}
// 重置數據 停止并回到第一幀或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%' } })
}
}
以上就是前三步的實現代碼,這三個步驟整體并不難。在頁面能夠實現簡單的播放之后,后面就是生成視頻或者GIF了。其實還有一個功能也很重要,就是導入視頻,解析視頻,然后就可以做視頻編輯器了,這個也是一個大工程,想玩的可以去嘗試嘗試
審核編輯 黃宇
-
HarmonyOS
+關注
關注
79文章
2005瀏覽量
31670 -
Harmony
+關注
關注
0文章
57瀏覽量
2825
發布評論請先 登錄
相關推薦
人類與機器人有感情產生嗎?
HarmonyOS NEXT新能力,一站式高效開發HarmonyOS應用
如何將MP4視頻轉換為GIF
HarmonyOS NEXT新能力,一站式高效開發HarmonyOS應用
HarmonyOS NEXT新能力,一站式高效開發HarmonyOS應用
淘寶與華為合作將基于HarmonyOS NEXT啟動鴻蒙原生應用開發
HDC 2024上,HarmonyOS NEXT有哪些精彩亮點值得期待?

華為“純血”鴻蒙系統 HarmonyOS NEXT 將于9月底推出正式版
華為HarmonyOS NEXT 10月8日開啟公測

AWTK 最新動態:支持鴻蒙系統(HarmonyOS Next)

評論