在 Soui 中嵌入 MiniBlink 初体验(三):实现一个界面友好动态可交互的饼图
一、引言
在上周,我已经调研了在下 Soui 中嵌入 MiniBlink 浏览器控件,并且使用百度的开源可视化库 ECharts 显示图表的可行性。
这篇博客,让我们来实现一个简单的界面友好的、动态可交互的饼图显示。最后的效果图如下:
想要了解如何实现 Soui 中 MiniBlink 浏览器控件的嵌入的同学,可以点击这里:
在 Soui 中嵌入 MiniBlink 初体验(一):支持百度 ECharts 开源可视化库显示
如果在使用 ECharts 库出现了程序显示不出来,但是浏览器却可以的问题,可以点击这里:
在 Soui 中嵌入 MiniBlink 初体验(二):解决本地 Html 文件显示 ECharts 失败的问题
想要查看本篇博客代码的网友,可以点击这里:
wangying2016/ECharts-In-Soui
好,接下来,我们开始吧!
二、ECharts 在线编写 Demo
我们要实现一个饼图的显示,必然要先写 ECharts 的显示代码。
其实这个也简单,即使是像我这样对于 js 不是很了解的人也可以轻松上手。新入门 ECharts 的同学可以看看 ECharts 的教程文档,还是很容易上手的:
ECharts 教程文档
这里,我为了实现一个饼图,在 ECharts 实例中在线进行了修改,并查到了其修改饼图元素名称、值和颜色的方法(教程里有说到,可以直接看代码),写出代码如下:
app.title = '环形图';
option = {
tooltip: {
trigger: 'item',
formatter: "{a} <br/>{b}: {c} ({d}%)"
},
legend: {
orient: 'vertical',
x: 'left',
data:['五杀','四杀','三杀','送成鬼']
},
series: [
{
name:'成绩分布',
type:'pie',
radius: ['50%', '70%'],
avoidLabelOverlap: false,
label: {
normal: {
show: false,
position: 'center'
},
emphasis: {
show: true,
textStyle: {
fontSize: '30',
fontWeight: 'bold'
}
}
},
labelLine: {
normal: {
show: false
}
},
data:[
{value:1, name:'五杀',itemStyle:{color:'#26d7bc'}},
{value:1, name:'四杀',itemStyle:{color:'#24bdee'}},
{value:1, name:'三杀',itemStyle:{color:'#ffdb83'}},
{value:1, name:'送成鬼',itemStyle:{color:'#ff8181'}}
]
}
]
};
至此,我们显示一个界面友好的饼图的任务就完成了一半了。下图是在 ECharts 示例中修改代码的情况:
三、实现动态交互:怎么能让饼图数据即时刷新显示?
那么,除了要显示之外,我们还想要达到可以对饼图百分之百的控制。这也就是说,我们可以随时修改饼图的数据,并让其即时刷新。这也是引言中 Gif 的效果。
怎么做呢?
通过我的调研,发现我们可以使用这么一种思路:
我们可以这么实现饼图数据的即时刷新:
1. 在 js 代码中声明一个全局的数组,让其记录各个项目的数值
2. 写一个 js 函数,让其设置各个项目的数值并且重绘界面
3. 在 C++ 的层面,使用 C++ 调用我们在上一步中写的 js 函数,从而完成数据的设置和界面的即时刷新
思路很清晰,让我们看看具体是怎么做的:
1. 首先,我们声明一个全局的数组,记录需要的数值:
// 我们定义的全局数组,用来存储饼图各个项目的数值
var values = new Array(1,1,1,1);
...
// 这是具体设置饼图显示数据的地方,使用数组取值的方法
data: [
{ value: values[0], name: '五杀', itemStyle: { color: '#26d7bc' } },
{ value: values[1], name: '四杀', itemStyle: { color: '#24bdee' } },
{ value: values[2], name: '三杀', itemStyle: { color: '#ffdb83' } },
{ value: values[3], name: '送成鬼', itemStyle: { color: '#ff8181' } }
]
2. 然后,我们写两个函数,一个是 showPie(),用来显示饼图,一个是 changeValue(),用来设置数据并且再次显示饼图:
这是我们的 changeValue 函数,注意它包含两个逻辑,一个是修改值,另一个则还需要重新绘制饼图的逻辑。
function changeValue(value1, value2, value3, value4) {
values[0] = value1;
values[1] = value2;
values[2] = value3;
values[3] = value4;
// alert("开始修改数据,并且让 ECharts 显示");
showPie();
}
这是我们的 showPie() 函数,这个函数在两个地方调用,一次是在打开载入 html 界面中全局调用一次,另一次则就是上面那个 changeValue() 函数中调用一次:
function showPie() {
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
var option = {
tooltip: {
trigger: 'item',
formatter: "{a} <br/>{b}: {c} ({d}%)"
},
legend: {
orient: 'vertical',
x: 'left',
data: ['五杀', '四杀', '三杀', '送成鬼']
},
series: [
{
name: '成绩分布',
type: 'pie',
radius: ['50%', '70%'],
avoidLabelOverlap: false,
label: {
normal: {
show: false,
position: 'center'
},
emphasis: {
show: true,
textStyle: {
fontSize: '30',
fontWeight: 'bold'
}
}
},
labelLine: {
normal: {
show: false
}
},
data: [
{ value: values[0], name: '五杀', itemStyle: { color: '#26d7bc' } },
{ value: values[1], name: '四杀', itemStyle: { color: '#24bdee' } },
{ value: values[2], name: '三杀', itemStyle: { color: '#ffdb83' } },
{ value: values[3], name: '送成鬼', itemStyle: { color: '#ff8181' } }
]
}
]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
}
3. 最后,我们只需要使用 C++ 代码调用上面那个 changeValue() js 函数即可。这里我添加了四个按钮,分别对应了饼图的四个项目,每点击一次,则默认增加一个单位值,用以测试饼图的动态显示。在这里,最核心的代码就是 C++ 调用 changeValue() 的代码了:
// 调用 js 函数 ChangeValue
HRESULT CMainDlg::_CallJsChangeValue(UINT uValue1, UINT uValue2, UINT uValue3, UINT uValue4)
{
SOUI::SWkeWebkit *pWkeWebkit = FindChildByName2<SOUI::SWkeWebkit>(L"wke_test");
if (pWkeWebkit != NULL) {
SOUI::SStringA strCallJs;
strCallJs.Format("changeValue(%d,%d,%d,%d);", uValue1, uValue2, uValue3, uValue4);
wkeRunJS(pWkeWebkit->GetWebView(), strCallJs);
}
return S_OK;
}
看到上述代码的 SOUI::SStringA 不要害怕,这是 Soui 特有的字符串类型,使用 MiniBlink 调用 js 的函数是 wkeRunJS,这个函数还是很方便使用的,第一个参数需要传一个 wkeWebKit 类型的对象,第二个参数就是我们的 js 代码。这里我将 changeValue 的调用形式进行了可变参数匹配,用来适配多种类型的调用。
注:这里需要着重注意的是,在 MiniBlink 中,想要处理 wkeRunJS 函数调用 js 函数返回的值,需要手动添加一个 return,按照作者的说法,是为了兼容 V8 而必须加上 return,如果不加上 return ,则获取不到 js 函数的返回值:
...
// 调用方式类似
jsValue jsRet = wkeRunJS(pWkeWebkit->GetWebView(), "return getValue();");
...
这里为了处理 getValue() js 函数的返回值,需要手动加个 return。
至此,我们已经完成了这个非常有成就感的 Demo!
完结,撒花 ^_^
四、总结
这篇博客是前两篇博客的实际的探索,实现了我在一开始想要实现的效果。毕竟以需求为导向,总是能够驱动着自己去探索更多东西。
MiniBlink 真是个好玩的东西,另外,ECharts 也是一个非常强大的可视化库,也非常好玩。有时间一定还要继续深钻。
明天还要继续~~~
To be Stronger:)