Jetpack Compose中通过WebView使用EChart(不推荐)

前言

下载地址

https://www.jsdelivr.com/package/npm/echarts

入门教程

https://echarts.apache.org/handbook/zh/get-started/

后文

本来想用WebView加载EChart来实现Jetpack Compose中的使用。

但是实际的显示效果不好,并且加载比较慢,体验不好,所以最终放弃了这个方案。

组件封装

目录结构

1
2
assets/echart/echarts.min.js
assets/themes/bar_chart.chtml

模板

bar_chart.chtml

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ECharts</title>
<!-- 引入刚刚下载的 ECharts 文件 -->
<script src="./js/echarts.min.js"></script>
</head>
<body>
<!-- 为 ECharts 准备一个定义了宽高的 DOM -->

<div id="main">
<div class="mchart"></div>
</div>
<style>
body {
margin: 0;
padding: 0;
background-color: transparent;
overflow: hidden;
}
#main {
width: 100vw;
height: 100vh;
}

.mchart {
width: 100%;
height: 100%;
}
</style>

<script type="text/javascript">
function init() {
// 基于准备好的dom,初始化echarts实例
if (!window.myChart) {
window.myChart = echarts.init(document.querySelector(".mchart"));
}

// 指定图表的配置项和数据
var option = {
title: {
text: ""
},
tooltip: {},
legend: {
data: ["销量"]
},
xAxis: {
data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"],
splitLine: {
show: true, // 是否显示分隔线
lineStyle: {
color: "#f3f3f3", // 分隔线颜色
width: 1, // 分隔线宽度
type: "solid" // 分隔线类型,可选值:solid, dashed, dotted
}
}
},
yAxis: {
splitLine: {
show: true, // 是否显示分隔线
lineStyle: {
color: "#f3f3f3", // 分隔线颜色
width: 1, // 分隔线宽度
type: "solid" // 分隔线类型,可选值:solid, dashed, dotted
}
}
},
series: [
{
name: "销量",
type: "line",
data: [5, 20, 36, 10, 10, 20],

itemStyle: {
color: "#28E7B3",
borderColor: "#fff",
borderWidth: 2,
shadowColor: "rgba(0, 0, 0, 0)",
shadowBlur: 0,
shadowOffsetY: 0,
shadowOffsetX: 0
},
areaStyle: {
opacity: 0.8,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "#28E7B3"
},
{
offset: 1,
color: "#ffffff"
}
])
}
}
]
};

// 使用刚指定的配置项和数据显示图表。
window.myChart.setOption(option);
}

// 防抖
function debounce(fn, wait) {
let timeout = null;
return function () {
if (timeout !== null) clearTimeout(timeout);
timeout = setTimeout(fn, wait);
};
}

function resize() {
const myDiv = document.getElementById("main");
myDiv.style.width = window.innerWidth + "px";
myDiv.style.height = window.innerHeight + "px";
if (window.myChart) {
window.myChart.resize();
}
}

init();
resize();
window.addEventListener("resize", debounce(resize, 100));
</script>
</body>
</html>

脚本地址更换为

1
<script type="text/javascript" src="file:///android_asset/echart/echarts.min.js"></script>

在加载的时候vwvh无效,所以这里使用JS设置宽高。

组件

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
48
49
50
51
52
53
54
55
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.util.AttributeSet
import android.webkit.WebSettings
import android.webkit.WebView
import com.x5.template.Chunk
import com.x5.template.Theme
import com.x5.template.providers.AndroidTemplates

@SuppressLint("SetJavaScriptEnabled")
public class ZChartBarView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) :
WebView(context, attrs, defStyleAttr) {
private val TAG_TP_NAME: String = "bar_chart"
private var mChartData: String = ""

init {
settings.allowFileAccess = true
settings.javaScriptEnabled = true
settings.cacheMode = WebSettings.LOAD_NO_CACHE
settings.displayZoomControls = false
settings.builtInZoomControls = false
settings.setSupportZoom(false)
settings.useWideViewPort = true

setBackgroundColor(Color.TRANSPARENT)
}


fun setChartData(chartData: String) {
this.mChartData = chartData
loadHTML()
}

private fun getChunk(): Chunk {
return Theme(AndroidTemplates(context)).makeChunk(TAG_TP_NAME)
}

private fun getHexColor(intColor: Int): String {
return String.format("#%06X", 0xFFFFFF and intColor)
}

/**
* 加载页面
*/
private fun loadHTML() {
val mChunk: Chunk = getChunk()
mChunk.set("ChartData", mChartData)
this.loadDataWithBaseURL(null, mChunk.toString(), "text/html", "utf-8", "about:blank")
}
}

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.viewinterop.AndroidView
import cn.psvmc.zchartview.ZChartBarView

@Composable
fun ZChartBarComp(
htmlContent: String,
modifier: Modifier = Modifier
) {
AndroidView(
modifier = modifier,
factory = { context ->
ZChartBarView(context).apply {
setChartData("")
}
},
update = { chartView ->

}
)
}