|
|
|
@ -2,24 +2,25 @@
|
|
|
|
|
|
|
|
|
|
<div align="center"><img src="https://p.qlogo.cn/zc_icon/0/17e33075c1f2fc7cf4534101a18b09e416282371897452/0.png" alt="demo1 preview" /></div> |
|
|
|
|
|
|
|
|
|
下面用**demo1**的例子演示Style插件的构建,样式为**左右声道音量大小的动态显示**,如上图所示。 |
|
|
|
|
下面用**demo1**的例子演示样式插件的开发,样式为**左右声道音量大小的动态显示**,如上图所示。 |
|
|
|
|
|
|
|
|
|
**demo1**的根目录为`top.mashiros.3rd-party-style-demo.advp`,目录结构如下所示: |
|
|
|
|
|
|
|
|
|
```powershell |
|
|
|
|
top.mashiros.3rd-party-style-demo.advp |
|
|
|
|
├── demo1 |
|
|
|
|
│ └── Style.qml |
|
|
|
|
├── Demo1.qml |
|
|
|
|
└── package.json |
|
|
|
|
``` |
|
|
|
|
# *package.json* |
|
|
|
|
在根目录下新建*package.json*文件。此文件为SAO Utils 2的插件声明文件,ADV-Plugin会自动识别`catalog`为`top.mashiros.advp-style`的`resources`,并识别`entry`路径下的*Style.qml*与*Config.qml*(可选,如无配置需求可不创建)。 |
|
|
|
|
在根目录下新建*package.json*文件。此文件为SAO Utils 2的插件声明文件,ADV-Plugin会自动识别`catalog`为`top.mashiros.advp-style`的`resources`,该分类下的资源入口`entry`需要指定为组件文件。 |
|
|
|
|
|
|
|
|
|
*package.json*文件示例如下。 |
|
|
|
|
|
|
|
|
|
```json |
|
|
|
|
{ |
|
|
|
|
"name": "top.mashiros.3rd-party-style-demo.advp", |
|
|
|
|
"version": "0.0.1", |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"title": { |
|
|
|
|
"en": "ADV-Plugin 3rd party style demo", |
|
|
|
|
"zh": "音频可视化插件第三方样式演示" |
|
|
|
@ -38,71 +39,75 @@ top.mashiros.3rd-party-style-demo.advp
|
|
|
|
|
"location": "/3rd-party-demo1", |
|
|
|
|
"catalog": "top.mashiros.advp-style", |
|
|
|
|
"title": "3rd party Demo1", |
|
|
|
|
"entry": "./demo1" |
|
|
|
|
"entry": "Demo1.qml" |
|
|
|
|
} |
|
|
|
|
] |
|
|
|
|
} |
|
|
|
|
``` |
|
|
|
|
*package.json*中`resources`资源说明: |
|
|
|
|
`resources`:为此插件的资源,可包含多个资源值。 |
|
|
|
|
* `resources`:为此插件的资源,可包含多个资源值。 |
|
|
|
|
* `location`:定义本插件域内资源所在的位置(非实际路径,可自定义)。**注意:在`resources`包含多个资源值时,需要保证不同资源值内的`location`不同。** |
|
|
|
|
* `catalog`:Style插件的`catalog`需要定义为`top.mashiros.advp-style`。 |
|
|
|
|
* `title`:定义此Style的显示名称。 |
|
|
|
|
* `entry`:定义此Style资源值的相对路径,为该资源的*Style.qml*与*Config.qml*文件所在的路径。相对路径起点为此插件文件夹根目录。 |
|
|
|
|
* `catalog`:样式插件的`catalog`需要定义为`top.mashiros.advp-style`。 |
|
|
|
|
* `title`:定义此样式的显示名称。 |
|
|
|
|
* `entry`:定义此样式资源值的相对路径,为该资源文件所在的路径。相对路径起点为此插件文件夹根目录。 |
|
|
|
|
|
|
|
|
|
注:<font color='#f5a623'>一个Style对应`resources`中的一个资源值,可在一个插件内定义多个Style值(如demo2)。</font> |
|
|
|
|
注:<font color='#f5a623'>一个样式对应`resources`中的一个资源值,可在一个插件内定义多个资源值(如demo2所示)。</font> |
|
|
|
|
|
|
|
|
|
# *Style.qml* |
|
|
|
|
# *Demo1.qml* |
|
|
|
|
好了,*package.json*已经创建完毕,我们开始编写实际代码了。这一步可能需要一些QML与Canvas的知识,网络上有关的教程还是很多的。 |
|
|
|
|
下面为**demo1**的*Style.qml*代码实现,其功能为动态显示左右声道音量大小。代码功能说明写在了注释里。 |
|
|
|
|
下面为**demo1**的*Demo1.qml*代码实现,其功能为动态显示左右声道音量大小。代码功能说明写在了注释里。 |
|
|
|
|
|
|
|
|
|
```qml |
|
|
|
|
import QtQuick 2.12 |
|
|
|
|
//通过相对路径导入ADV-Plugin插件目录下qml/api文件夹,调用StyleAPI.qml组件 |
|
|
|
|
import "../../top.mashiros.widget.advp/qml/api" |
|
|
|
|
|
|
|
|
|
StyleAPI { |
|
|
|
|
//填充颜色 |
|
|
|
|
readonly property string line_color: "#f5a623" |
|
|
|
|
|
|
|
|
|
//音频数据更新时的处理代码,参数是长度为129的数组data |
|
|
|
|
onAudioDataUpdeted: { |
|
|
|
|
//清空画布 |
|
|
|
|
context.clearRect(0, 0, width, height); |
|
|
|
|
//左声道音量 |
|
|
|
|
let left_channel = 0; |
|
|
|
|
//右声道音量 |
|
|
|
|
let right_channel = 0; |
|
|
|
|
//取前128位左右声道的数据进行处理 |
|
|
|
|
for (let i=0;i<128;i++) { |
|
|
|
|
if(i<64) { |
|
|
|
|
//左声道FFT数据求和 |
|
|
|
|
left_channel += data[i]; |
|
|
|
|
} else { |
|
|
|
|
//右声道FFT数据求和 |
|
|
|
|
right_channel += data[i]; |
|
|
|
|
//通过相对路径导入ADV-Plugin插件目录下qml/api文件夹,调用相关的组件 |
|
|
|
|
import "../top.mashiros.widget.advp/qml/api" |
|
|
|
|
|
|
|
|
|
AdvpStyleTemplate { |
|
|
|
|
style: AdvpCanvasTemplate { |
|
|
|
|
//填充颜色 |
|
|
|
|
readonly property string line_color: "#f5a623" |
|
|
|
|
|
|
|
|
|
//音频数据更新时的处理代码,参数是长度为129的数组data |
|
|
|
|
onAudioDataUpdeted: { |
|
|
|
|
//清空画布 |
|
|
|
|
context.clearRect(0, 0, width, height); |
|
|
|
|
//左声道音量 |
|
|
|
|
let left_channel = 0; |
|
|
|
|
//右声道音量 |
|
|
|
|
let right_channel = 0; |
|
|
|
|
//取前128位左右声道的数据进行处理 |
|
|
|
|
for (let i=0;i<128;i++) { |
|
|
|
|
if(i<64) { |
|
|
|
|
//左声道FFT数据求和 |
|
|
|
|
left_channel += data[i]; |
|
|
|
|
} else { |
|
|
|
|
//右声道FFT数据求和 |
|
|
|
|
right_channel += data[i]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
//利用最后一位归一化系数data[128]进行动态归一化,其中20为最大高度值的调节系数 |
|
|
|
|
let normalize = 20*data[128]/height; |
|
|
|
|
left_channel /= normalize; |
|
|
|
|
right_channel /= normalize; |
|
|
|
|
//绘制左声道 |
|
|
|
|
context.fillRect(0,height,width*0.45,-left_channel); |
|
|
|
|
//绘制右声道 |
|
|
|
|
context.fillRect(width*0.55,height,width*0.45,-right_channel); |
|
|
|
|
//填充矩形 |
|
|
|
|
context.fill(); |
|
|
|
|
//QML Canvas绘制图形(绘制后需要显示必须调用canvas的requestPaint方法) |
|
|
|
|
requestPaint(); |
|
|
|
|
} |
|
|
|
|
//利用最后一位归一化系数data[128]进行动态归一化,其中20为最大高度值的调节系数 |
|
|
|
|
let normalize = 20*data[128]/height; |
|
|
|
|
left_channel /= normalize; |
|
|
|
|
right_channel /= normalize; |
|
|
|
|
//绘制左声道 |
|
|
|
|
context.fillRect(0,height,width*0.45,-left_channel); |
|
|
|
|
//绘制右声道 |
|
|
|
|
context.fillRect(width*0.55,height,width*0.45,-right_channel); |
|
|
|
|
//填充矩形 |
|
|
|
|
context.fill(); |
|
|
|
|
//QML Canvas绘制图形(绘制后需要显示必须调用canvas的requestPaint方法) |
|
|
|
|
requestPaint(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//属性configs或者context改变时的处理代码,无参数 |
|
|
|
|
onConfigsUpdated: { |
|
|
|
|
//给canvas的context赋值初始样式(填充颜色),避免在onAudioDataUpdeted处理代码中重复调用 |
|
|
|
|
context.fillStyle = line_color; |
|
|
|
|
//属性configs或者context改变时的处理代码,无参数 |
|
|
|
|
onConfigsUpdated: { |
|
|
|
|
//给canvas的context赋值初始样式(填充颜色),避免在onAudioDataUpdeted处理代码中重复调用 |
|
|
|
|
context.fillStyle = line_color; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
完成代码后,启动SDK程序加载挂件,切换Style到**3rd party Demo1**的选项,即可在挂件处进行预览(记得播放音频)。 |
|
|
|
|
**demo1**没有配置项,所以上面的示例代码没有`defaultValues`属性值与`preference`属性值。 |
|
|
|
|
|
|
|
|
|
完成代码后,启动SDK程序加载挂件,切换样式到**3rd party Demo1**的选项,即可在挂件处进行预览(记得播放音频)。 |