HarmonyOS烟花特效组件开发

开发 OpenHarmony
之前看到“粒子消散”的特效组件,于是就产生想法(自己也弄个特效组件应该挺有意思的)。这个烟花特效可以添加到游戏胜利的界面中,可能还有其他应用场景哈哈~。

[[431264]]

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

前言

之前看到“粒子消散”的特效组件,于是就产生想法(自己也弄个特效组件应该挺有意思的)。这个烟花特效可以添加到游戏胜利的界面中,可能还有其他应用场景哈哈~。这也算是我做的第一个组件原创demo啦。

概述

效果图如下:

有三种模式可以选择,一种是图案只有五角星,一种是图案只有三角形,还有一种是图案既有五角星又有三角星。颜色有10种,还有背景音乐(自己DIY的烟花音效)!话不多说,开整!

正文

1.创建一个空白的工程

DevEco Studio下载安装成功后,打开DevEco Studio,点击左上角的File,点击New,再选择New Project,选择Empty Ability,然后点击Next,给项目命名Framework,选择设备类型Phone,选择语言类型JS最后点击Finish。

代码删除的部分

在entry>src>main>js>default>pages.index>index.hml 文件里把以下代码删掉

<text class="title"
        {{ $t('strings.hello') }} {{ title }} 
    </text> 
  • 1.
  • 2.
  • 3.

 在entry>src>main>js>default>pages.index>index.js 文件里把以下代码删掉

title:" " 
   onInit() { 
        this.title = this.$t('strings.world'); 
    } 
  • 1.
  • 2.
  • 3.
  • 4.

 在entry>src>main>js>default>pages.index>index.css 文件里把container部分以下的代码删掉

2.布局设计

index.hml

该组件是画布组件,画布的大小是整个屏幕,而按钮是显示画布上方的,所以要添加个栈组件,依次放入画布组件和按钮组件。代码如下👇,注意这里画布组件添加了触摸事件touchstartfunc,下文会讲解这步。

<stack class="stack"
      <canvas class="canvas " ref="canvas " @touchstart='touchstartfunc' ></canvas> 
      <input type="button" class="STAR"  value="五角星" onclick="click_star"/> 
      <input type="button" class="TRIANGLE"  value="三角形" onclick="click_triangle"/> 
      <input type="button" class="MIX"  value="混合" onclick="click_mix"/> 
  </stack> 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

index.css

给画布组件和按钮组件设置属性,代码如下👇

.canvas{ 
    width:100%; 
    height: 100%; 
    background-color:black; 

.STAR{ 
    width: 80px; 
    height: 38px; 
    font-size: 20px; 
    background-color:blue; 
    border-color: blue; 
    text-color: aquamarine; 
    top:660px; 
    left: 40px; 

.TRIANGLE{ 
    width: 80px; 
    height: 38px; 
    font-size: 20px; 
    background-color:blue; 
    border-color: blue; 
    text-color: aquamarine; 
    top:660px; 
    left: 150px; 

.MIX{ 
    width: 80px; 
    height: 38px; 
    font-size: 20px; 
    background-color:blue; 
    border-color: blue; 
    text-color: aquamarine; 
    top:660px; 
    left: 260px; 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.

此时打开模拟器,你就能得到上面效果图左1图,接下来做功能实现部分。

3.绘制图案

五角星

函数 draw_star 传的参数分别是烟花释放的圆心坐标,图案的颜色,图案移动的斜率,图案是否填充颜色。定义的变量中,x和y是图案中心的坐标,根据时间推移(会设定定时器,下文会讲)move_times增加,图案会沿着传进来的斜率方向作直线移动,以达到烟花绽放的效果。变量a-h都是为了便于绘制五角星的图案而设的公式参数值,全局变量r_star是五角星的边长,最后根据公式去绘制单个五角星图案

index.js

先在export default上方定义变量

var ctx; 
var move_times=1; 
var r_star = 5; 
var r_triangle=14;      
  • 1.
  • 2.
  • 3.
  • 4.

 然后在export default下方添加代码:

onShow() { 
       ctx = this.$refs.canvas.getContext('2d'); 
   }, 
 
draw_Star(x_1,y_1,color,x_2,y_2,fill) { 
       let x = x_1 + move_times * x_2; 
       let y = y_1 + move_times * y_2; 
       let a = r_star * Math.sin(Math.PI / 10); 
       let b = r_star * Math.cos(Math.PI / 10); 
       let c = (r_star + a) * Math.tan(Math.PI / 10); 
       let d = (r_star + a) * Math.tan(Math.PI / 5) - c; 
       let e = r_star * Math.sin(Math.PI / 5); 
       let f = r_star * Math.cos(Math.PI / 5); 
       let g = (r_star + 2 * a) * Math.cos(2 * Math.PI / 5); 
       let h = (r_star + 2 * a) * Math.sin(2 * Math.PI / 5); 
 
       ctx.lineWidth=1; 
       ctx.beginPath(); 
       ctx.moveTo(x - r_star - a, y - c); 
       ctx.lineTo(x - a, y - c); 
       ctx.lineTo(x, y - b - c); 
       ctx.lineTo(x + a, y - c); 
       ctx.lineTo(x + a + r_star, y - c); 
       ctx.lineTo(x + a + r_star - f, y + e - c); 
       ctx.lineTo(x + a + g, y + h - c); 
       ctx.lineTo(x, y + d); 
       ctx.lineTo(x - a - g, y + h - c); 
       ctx.lineTo(x - a - r_star + f, y + e - c); 
       ctx.closePath(); 
       ctx.stroke(); 
       move_times=move_times+1; 
   }, 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.

三角星

同样, draw_triangle 是绘制单个三角形并沿设定斜率移动的函数,函数的参数类型及作用与五角星的一致。全局变量r_triangle为三角形的边长,代码如下👇

draw_Triangle(x_1,y_1,color,x_2,y_2,fill){ 
       let x = x_1 + move_times * x_2; 
       let y = y_1 + move_times * y_2; 
       ctx.lineWidth=1; 
       ctx.beginPath(); 
       ctx.moveTo(x-r_triangle/2, y + Math.sqrt(3)*r_triangle/6); 
       ctx.lineTo(x, y - Math.sqrt(3)*r_triangle/3); 
       ctx.lineTo(x+r_triangle/2, y + Math.sqrt(3)*r_triangle/6); 
       ctx.closePath(); 
       ctx.stroke(); 
 
       move_times=move_times+1; 
   }, 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

图案的美化

设置了10种颜色的颜色字典,通过绘制图案函数draw中的参数 color 去控制颜色(黑色是作保护作用),颜色可通过单独设置数字1-10来选择,也可以通过随机数(1~10)去随机变化颜色。颜色填充也是如此,1为不填充,2为填充,也可随机产生1或2来随机变化是否填充颜色。

var drawcolors=[0,1,2,3,4,5,6,7,8,9,10]; 
const COLORS={ 
    "0":'black'
    "1":"#FF2E10"
    "2":"#FB8D15"
    "3":"#F4ED1C"
    "4":"#C5F31D"
    "5":"#51F11F"
    "6":"#18F8F8"
    "7":"#1166FF"
    "8":"#9833DD"
    "9":"#FC14EB"
    "10":"#C64A6A" 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

draw函数中,在ctx.lineWidth下方,在ctx.beginPath上方添加代码:

ctx.strokeStyle = COLORS[drawcolors[color].toString()]; 
  • 1.

 在ctx.stroke下方添加代码

if(fill==2) { 
            ctx.fillStyle = COLORS[drawcolors[color].toString()]; 
            ctx.fill(); 
        }; 
  • 1.
  • 2.
  • 3.
  • 4.

draw开头的函数是绘制单个图案,接下来的Draw函数是绘制8个或10个图案围成圆形向外同速率扩展的图像,run开头的函数是被循环的函数

4.绘制烟花

烟花的布局

绽放的烟花的形状是一个圆形,火花为单个图案。我设计了两种烟花绽放数量,一种是一个圆中有8个图案的,一种是一个圆中有10个图案的,它们的斜率都通过数学公式定义好了(如下的全局变量所示),单个图案沿斜率方向每次移动的距离为全局变量R的数值。

var R = 0.25; 
var s= R*Math.cos(Math.PI/5); 
var t= R*Math.sin(Math.PI/5); 
var v= R*Math.cos(Math.PI/2.5); 
var w= R*Math.sin(Math.PI/2.5); 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
Draw_Star_8(click_x,click_y){ 
       this.draw_Star(click_x,click_y,1,-R,0,Math.floor(Math.random()*2 + 1)); 
       this.draw_Star(click_x,click_y,2,-R/Math.sqrt(2),-R/Math.sqrt(2),Math.floor(Math.random()*2 + 1)); 
       this.draw_Star(click_x,click_y,3,0,-R,Math.floor(Math.random()*2 + 1)); 
       this.draw_Star(click_x,click_y,4,R/Math.sqrt(2),-R/Math.sqrt(2),Math.floor(Math.random()*2 + 1)); 
       this.draw_Star(click_x,click_y,5,R,0,Math.floor(Math.random()*2 + 1)); 
       this.draw_Star(click_x,click_y,6,R/Math.sqrt(2),R/Math.sqrt(2),Math.floor(Math.random()*2 + 1)); 
       this.draw_Star(click_x,click_y,7,0,R,Math.floor(Math.random()*2 + 1)); 
       this.draw_Star(click_x,click_y,8,-R/Math.sqrt(2),R/Math.sqrt(2),Math.floor(Math.random()*2 + 1)); 
   }, 
 
   Draw_Star_10(click_x,click_y,fill){ 
       this.draw_Star(click_x,click_y,Math.floor(Math.random()*10 + 1),-R,0,fill); 
       this.draw_Star(click_x,click_y,Math.floor(Math.random()*10 + 1),-s,-t,fill); 
       this.draw_Star(click_x,click_y,Math.floor(Math.random()*10 + 1),-v,-w,fill); 
       this.draw_Star(click_x,click_y,Math.floor(Math.random()*10 + 1),v,-w,fill); 
       this.draw_Star(click_x,click_y,Math.floor(Math.random()*10 + 1),s,-t,fill); 
       this.draw_Star(click_x,click_y,Math.floor(Math.random()*10 + 1),R,0,fill); 
       this.draw_Star(click_x,click_y,Math.floor(Math.random()*10 + 1),s,t,fill); 
       this.draw_Star(click_x,click_y,Math.floor(Math.random()*10 + 1),v,w,fill); 
       this.draw_Star(click_x,click_y,Math.floor(Math.random()*10 + 1),-v,w,fill); 
       this.draw_Star(click_x,click_y,Math.floor(Math.random()*10 + 1),-s,t,fill); 
   }, 
 
    Draw_Triangle_8(click_x,click_y,fill){ 
       this.draw_Triangle(click_x,click_y,Math.floor(Math.random()*10 + 1),-R,             0,              fill); 
       this.draw_Triangle(click_x,click_y,Math.floor(Math.random()*10 + 1),-R/Math.sqrt(2),-R/Math.sqrt(2),fill); 
       this.draw_Triangle(click_x,click_y,Math.floor(Math.random()*10 + 1), 0,            -R,              fill); 
       this.draw_Triangle(click_x,click_y,Math.floor(Math.random()*10 + 1), R/Math.sqrt(2),-R/Math.sqrt(2),fill); 
       this.draw_Triangle(click_x,click_y,Math.floor(Math.random()*10 + 1), R,             0,              fill); 
       this.draw_Triangle(click_x,click_y,Math.floor(Math.random()*10 + 1), R/Math.sqrt(2),R/Math.sqrt(2), fill); 
       this.draw_Triangle(click_x,click_y,Math.floor(Math.random()*10 + 1), 0,             R,              fill); 
       this.draw_Triangle(click_x,click_y,Math.floor(Math.random()*10 + 1),-R/Math.sqrt(2),R/Math.sqrt(2), fill); 
   }, 
 
   Draw_Triangle_10(click_x,click_y){ 
       this.draw_Triangle(click_x,click_y,1,-R,0, Math.floor(Math.random()*2 + 1)); 
       this.draw_Triangle(click_x,click_y,2,-s,-t,Math.floor(Math.random()*2 + 1)); 
       this.draw_Triangle(click_x,click_y,3,-v,-w,Math.floor(Math.random()*2 + 1)); 
       this.draw_Triangle(click_x,click_y,4,v,-w, Math.floor(Math.random()*2 + 1)); 
       this.draw_Triangle(click_x,click_y,5,s,-t, Math.floor(Math.random()*2 + 1)); 
       this.draw_Triangle(click_x,click_y,6,R,0,  Math.floor(Math.random()*2 + 1)); 
       this.draw_Triangle(click_x,click_y,7,s,t,  Math.floor(Math.random()*2 + 1)); 
       this.draw_Triangle(click_x,click_y,8,v,w,  Math.floor(Math.random()*2 + 1)); 
       this.draw_Triangle(click_x,click_y,9,-v,w, Math.floor(Math.random()*2 + 1)); 
       this.draw_Triangle(click_x,click_y,10,-s,t,Math.floor(Math.random()*2 + 1)); 
   }, 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.

火花的移动

上述提过一个movetimes,火花的移动无非就是坐标的变化,通过设置一个定时器,循环绘制图案就能实现移动的效果,先构造一个被循环的函数run_star(举五角星的实例,三角形同理;位置,美化等的参数随意),代码如下

run_star(){ 
     this.Draw_Star_10(200,300,1); 
     this.Draw_Star_10(150,200,2); 
     this.Draw_Star_8(300,218); 
     this.Draw_Star_8(110,380); 
  }, 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

 然后添加定时器

var timer_star=null;                    
var timer_triangle=null;                 
var timer_mix=null
  • 1.
  • 2.
  • 3.

 点击按钮“五角星”时会释放图案为五角星的烟花

click_star(){ 
       timer_star=setInterval(this.run_star,120); 
   }, 
  • 1.
  • 2.
  • 3.

此时,打开模拟器,你会看到图案移动了,但上一个图案没有清除

#星光计划1.0# 【木棉花】:烟花特效组件开发-鸿蒙HarmonyOS技术社区

所以要给被循环的函数添加一个清空操作(为了保护清空函数,要先在清空前加点东西),在this.Draw函数之前添加以下代码:

this.draw_Star(0,0,0,0,0,0); 
  ctx.clearRect(0,0,400,800); 
  • 1.
  • 2.

烟花的结束

按上述步骤下来,会发现烟花的圆形越来越大,最终出界。

为了实现烟花的结束,可以根据movetimes的增加次数来控制烟花绽放范围的大小。通过透明度的递减,最终透明度减为0,图案消失

var o = 1;    
  • 1.

 在draw函数里的开头位置添加以下代码:

if ((move_times >= 230 && move_times <= 330)) { 
          o = o - 0.01; 
          ctx.globalAlpha = o; 
      }; 
  • 1.
  • 2.
  • 3.
  • 4.

 烟花的循环绽放

在draw函数里的开头位置添加以下代码:

if(move_times==342){ 
           o=1; 
           ctx.globalAlpha = o; 
           move_times=1; 
       }; 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

 同理可以设置“三角形”和“混合”的被循环函数

run_triangle(){ 
        this.draw_Triangle(0,0,0,0,0,0); 
        ctx.clearRect(0,0,400,800); 
        this.Draw_Triangle_8(200,300,1); 
        this.Draw_Triangle_8(150,200,2); 
        this.Draw_Triangle_10(300,218); 
        this.Draw_Triangle_10(110,380); 
    }, 
 
 run_mix(){ 
        this.draw_Triangle(0,0,0,0,0,0); 
        ctx.clearRect(0,0,400,800); 
        this.Draw_Triangle_8(200,300,1); 
        this.Draw_Star_10(150,200,2); 
        this.Draw_Triangle_10(300,218); 
        this.Draw_Star_8(110,380); 
    }, 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

5.点击处绽放烟花

先获取点击处相对于画布组件左上角的坐标,然后作为新烟花绽放的圆心坐标传参,这里的click_b1,click_b2下文会讲解

var timer_click=null
  • 1.
run_touch(){ 
        if(click_b2==true) { 
            this.draw_Star(x, y, 0, 0, 0);     
            ctx.clearRect(0, 0, 400, 800); 
            this.Draw_Star_10(x, y, 1); 
        } 
    }, 
 
    touchstartfunc(msg) { 
        click_b1==true
        x=msg.touches[0].globalX; 
        y=msg.touches[0].globalY; 
        if(click_b1==true){ 
        timer_click=setInterval(this.run_touch,120); 
            click_b1=false
            timer_click=null
        } 
    }, 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

6.烟花图案的切换

通过设定布尔型变量来控制点击另一个按钮时,清空上一个按钮运行的定时器。

var star_b=true;                     
var mix_b=true
var triangle_b=true;                
var click_b1=true
var click_b2=true
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
click_star(){ 
        click_b2=false
        clearInterval(timer_triangle); 
        timer_triangle=null
        clearInterval(timer_mix); 
        timer_mix=null
        ctx.clearRect(0,0,400,800); 
        if(star_b==true){ 
        timer_star=setInterval(this.run_star,120); 
        star_b=false
        } 
        triangle_b=true
        mix_b=true
    }, 
 
    click_triangle(){ 
        click_b2=false
        clearInterval(timer_star); 
        timer_star=null
        clearInterval(timer_mix); 
        timer_mix=null
        ctx.clearRect(0,0,400,800); 
        if(triangle_b==true){ 
            timer_triangle=setInterval(this.run_triangle,120); 
            triangle_b=false
        } 
        star_b=true
        mix_b=true
    }, 
 
    click_mix(){ 
        click_b2=false
        clearInterval(timer_star); 
        timer_star=null
        clearInterval(timer_triangle); 
        timer_triangle=null
        ctx.clearRect(0,0,400,800); 
        if(mix_b==true){ 
            timer_mix=setInterval(this.run_mix,120); 
            mix_b=false
        } 
        star_b=true
        triangle_b=true
    }, 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.

7.背景音乐的添加

js模板中添加音频可以去看我之前的文章

index.hml

<video id='videoId' 
         src='/common/flr_5_1.mp3' 
         autoplay='true' 
         controls="false" 
         onfinish='finishCallback'></video> 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

index.js

var video_b =true;    
  • 1.

在src/common/下加入音频文件。

finishCallback:function(){ 
       if(video_b==true){ 
           this.$element('videoId').start(); 
       } 
   }, 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

别忘了生命周期的设置,在应用启动时自动播放音频,在应用隐藏的时候暂停播放音频并清空所有定时器,在应用销毁时清空所有定时器,停止播放音频。

onShow() { 
     ctx = this.$refs.canvas.getContext('2d'); 
     this.$element('videoId').start(); 
 }, 
 
 onHide(){ 
 clearInterval(timer_star); 
 timer_star=null
 clearInterval(timer_triangle); 
 timer_triangle=null
 clearInterval(timer_mix); 
 timer_mix=null
 clearInterval(timer_click); 
 timer_click=null
 video_b=false
 this.$element('videoId').pause(); 
 }, 
 
 onDestroy(){ 
     clearInterval(timer_star); 
     timer_star=null
     clearInterval(timer_triangle); 
     timer_triangle=null
     clearInterval(timer_mix); 
     timer_mix=null
     clearInterval(timer_click); 
     timer_click=null
     video_b=false
     this.$element('videoId').pause(); 
 }, 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.

结语

以上就是我这次的小分享啦❀❀!自己的第一个demo开发,略微粗糙。

文章相关附件可以点击下面的原文链接前往下载:

https://harmonyos.51cto.com/resource/1376

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

【编辑推荐】

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2016-09-19 21:37:58

vue特效组件Web

2021-05-06 10:46:40

JS代码文字烟花

2012-06-13 15:21:26

jQuery

2021-02-23 15:24:51

腾讯组件开源

2022-01-26 18:46:46

Canvas烟花粒子特效

2022-06-30 13:56:05

Rating鸿蒙

2013-05-21 13:55:51

Android游戏开发图像渐变特效

2021-01-12 12:04:40

鸿蒙HarmonyOS应用开发

2021-01-11 11:36:23

鸿蒙HarmonyOSApp开发

2021-01-21 13:21:18

鸿蒙HarmonyOSPhotoview组件

2021-01-20 09:54:56

鸿蒙HarmonyOS开发

2021-02-04 09:45:19

鸿蒙HarmonyOS应用开发

2021-01-18 09:52:20

鸿蒙HarmonyOS开发

2021-06-28 14:48:03

鸿蒙HarmonyOS应用

2010-07-30 13:40:59

Flex开发

2019-07-22 10:42:11

React组件前端

2021-02-20 12:34:53

鸿蒙HarmonyOS应用开发

2021-04-23 16:08:08

鸿蒙HarmonyOS应用

2021-09-29 10:15:00

鸿蒙HarmonyOS应用

2014-09-18 10:43:32

jquery mobi
点赞
收藏

51CTO技术栈公众号