这是一篇关于使用ECharts制作UE图表的一些知识
0、前言
在UE中想要实现一个好看可交互的图表实现起来非常的麻烦,但是有一种办法可以将网页在UE的UI中显示,借助这个办法就可以配合知名度很高的ECharts实现直观,交互丰富,可高度个性化定制的数据可视化图表。
ECharts网页:Apache ECharts
那么接下来我要做到的效果是
- 在UE中显示简单折线图
- 按键传递UE产生的数据给html,然后此UI同步数据更新折线图
- 与html交互,产生的数据发给UE并log打印出来
1、试用ECharts
先快速入门一下,然后再在UE中使用。
创建文件夹
HTML |-js | |-js文件 html文件
下载JS库
下载方式:下载
我使用的是在线定制,我把我需要的勾上(chart: Bar、Line、Radar, coordinate systems: Grid、Polar, 默认, others: 只勾选工具集)然后下载。
将下载好的js库放入js文件夹 然后新建一个html
<!DOCTYPE html>
<html lang="en" style="height: 100%">
<head>
<meta charset ="utf-8">
</head>
<body style="height: 100%; margin: 0">
<!--容器,后面脚本会根据此容器id放入echart-->
<div id="container" style="height: 100%"></div>
<!--引入js库-->
<script src='js/echarts.js'></script>
<script type="text/javascript">
//初始化ECharts实例
var dom = document.getElementById('container');
var myChart = echarts.init(dom);
// ECharts基础配置:折线图
var option;
option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line'
}
]
};
//显示
myChart.setOption(option);
// 窗口大小自适应
window.onresize = function () {
myChart.resize();
};
</script>
</body>
</html>
双击后即可看到一条普通的折线图,此示例参考自简单折线图,使用起来非常简单,还有很生动且完善的文档,比如快速上手的使用手册,所有的配置项和很多示例
2、接入UE
刚才用过ECharts之后,很明显,他只是一个方便在网页写图表的库和UE没有一点关系,不过之前也说了,有一种办法可以将网页显示在UI上,这个工具我用的是Web UI,他提供免费下载渠道,功能是在UI中创建基于网页的UI并且JavaScript与UE相互通信等。
下载好以后会有两个文件夹:WebUI和JsonLibrary,将这两个文件夹放到引擎插件的Marketplace下,打开项目后开启这俩插件,创建Widget Blueprint就会发现Common栏多了一个Web Interface,拖进来后如图所示填写Web Interface实例的LoadFile函数的参数,文件名是你创建的,现在将他Add to viewport就已经可以看到你上一章节创建的折线图了

当然,现阶段UE与这个UI的交互仅仅是鼠标和html的交互,这远远达不到想要的效果
挂载函数,绑定委托
要想进行与UE的交互还需要在html里写一些东西,将代码放到第一章写的script下方,不然myChart这个变量还没初始化
<script>
// ===================== 必加:UE WebUI 通信助手函数 =====================
if (typeof ue != "object" || typeof ue.interface != "object") {
if (typeof ue != "object") ue = {};
ue.interface = {};
ue.interface.broadcast = function (name, data) {
if (typeof name != "string") return;
var args = [name, ""];
if (typeof data != "undefined") args[1] = data;
var hash = encodeURIComponent(JSON.stringify(args));
if (
typeof history == "object" &&
typeof history.pushState == "function"
) {
history.pushState({}, "", "#" + hash);
history.pushState({}, "", "#" + encodeURIComponent("[]"));
} else {
document.location.hash = hash;
document.location.hash = encodeURIComponent("[]");
}
};
}
// 全局ue5函数,简化调用:ue5(事件名, 数据)
var ue5 = ue.interface.broadcast;
</script>
<script>
// ===================== 供UE调用的【数据更新函数】(UE→ECharts) =====================
// 挂载到ue.interface对象上,UE可通过Call节点调用此函数,参数为JSON格式的图表数据
ue.interface.updateEChartsData = function (chartData) {
// chartData是UE传递的JSON对象,直接更新ECharts配置
myChart.setOption({
series: [
{
data: chartData[0],type: 'line'
}
],
});
// 可选:将更新结果回传给UE(前端→UE)
var res = { status: chartData, time: new Date().getTime() };
ue5("ECharts_Updated", JSON.stringify(res));
};
// ===================== ECharts交互事件→UE 数据发送(核心:ECharts→UE) =====================
// 点击ECharts图表,将点击的节点数据发送给UE
myChart.on("click", function (params) {
// 构造要发送给UE的JSON数据
var clickData = {
chartType: "line",
seriesName: params.seriesName,
dataIndex: params.dataIndex,
value: params.value,
name: params.name,
};
// 通过ue5()发送给UE,事件名:ECharts_Click(UE端需监听此名称)
ue5("ECharts_Click", JSON.stringify(clickData));
});
</script>
JavaScript代码很简单,注释也写清楚了,接下来就是UE蓝图了
ECharts到UE

绑定html回调函数,就是JavaScript里的ue5(),Name就是第一个参数,Data就是第二个参数,Stringfy函数是JsonLibrary里的
然后你会发现还有一个Callback没有用到这个东西我看文档是说ue5()这个函数可以接收四个参数,但是我上方写的UE WebUI 通信助手函数只能接收两个,所以需要更改助手函数,下文所示,这下就可以了
<script>
//==================UE WebUI 通信助手函数=====================
("object" != typeof ue && (ue = {}),
(uuidv4 = function () {
return "10000000-1000-4000-8000-100000000000".replace(
/[018]/g,
function (t) {
return (
t ^
(crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (t / 4)))
).toString(16);
},
);
}),
(ue5 = (function (r) {
return "object" != typeof ue.interface ||
"function" != typeof ue.interface.broadcast
? ((ue.interface = {}),
function (t, e, n, o) {
var u, i;
"string" == typeof t &&
("function" == typeof e && ((o = n), (n = e), (e = null)),
(u = [t, "", r(n, o)]),
void 0 !== e && (u[1] = e),
(i = encodeURIComponent(JSON.stringify(u))),
"object" == typeof history &&
"function" == typeof history.pushState
? (history.pushState({}, "", "#" + i),
history.pushState({}, "", "#" + encodeURIComponent("[]")))
: ((document.location.hash = i),
(document.location.hash = encodeURIComponent("[]"))));
})
: ((i = ue.interface),
(ue.interface = {}),
function (t, e, n, o) {
var u;
"string" == typeof t &&
("function" == typeof e && ((o = n), (n = e), (e = null)),
(u = r(n, o)),
void 0 !== e
? i.broadcast(t, JSON.stringify(e), u)
: i.broadcast(t, "", u));
});
var i;
})(function (t, e) {
if ("function" != typeof t) return "";
var n = uuidv4();
return (
(ue.interface[n] = t),
setTimeout(
function () {
delete ue.interface[n];
},
1e3 * Math.max(1, parseInt(e) || 0),
),
n
);
})));
</script>
第三个参数传函数引用,第四个参数传销毁第三个参数的函数引用的时间默认是1秒,我真是实验下来发现,默认1秒,在UE中延迟2秒后调用Callback发现Callback的Valid仍然返回true,但是函数已经无法执行,这一点需要注意
ue5("ECharts_Click", JSON.stringify(clickData), function(v){
myChart.setOption({
series: [
{
data: [4,5,v],
type: "line",
},
],
});
}, 3);//3秒

UE到ECharts

CopyFromFloatArray可以将UE的浮点数据合并到一个数组里(),Add Value可以给JSON List添加数据,在html读取就当做数组读,最后使用WebInterface调用Call,函数名就填你挂载函数的名称ue.interface.updateEChartsData中的updateEChartsData
3、其他
打包的话需要在Project Setting-Packaging-Additional Non-Asset Directories to Package添加HTML
可以不使用这种静态文件,除了Load File还有Load URL