技术图文:如何利用C# + Echarts 绘制「堆叠条形图」?

背景

前几天,我们介绍了 如何利用C# + Echarts 绘制 Bar Simple?,原以为把 Echarts 封装到这种程度就可以完成当前任务了。

应用01

可是,把软件原型提交给对方时,发现对方更希望“可视化设备发生缺陷的具体数据”。也即利用 堆叠条形图 来可视化设备缺陷的数据。

堆叠条形图

百度提供的详细Demo如下:

百度Sample

于是,咱们就需要在之前的基础上对 Echarts 进行近一步的封装。


技术分析

在进行封装代码之前,咱们先聊聊知识的层次问题。即我们所学的知识是分层次的。

第一层:应用层,即解决 How 的问题。我们学习的各种工具,解决问题的具体方法都属于这个层次,按照步骤去做就好。

第二层:认知层,即解决 What 的问题。我们所使用的工具,解决问题的方法,它们到底是什么。

第三层:原理层,即解决 Why 的问题,要想明白为什么可以怎样做。

咱们写的图文大部分属于 How 这个层次,而这个层次的知识往往是不稳定的,多变的。咱们还需往底层去学,这样才能举一反三,触类旁通,掌握真正的知识。

好了,我们开始封装 堆叠条形图 的代码。

首先,我们对比一下百度提供的 “Bar Simple” 和 “堆叠条形图” 的示例代码

Bar Simple 示例代码:

option = {
 xAxis: {
 type: 'category',
 data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
 },
 yAxis: {
 type: 'value'
 },
 series: [{
 data: [120, 200, 150, 80, 70, 110, 130],
 type: 'bar'
 }]
};

堆叠条形图 示例代码:

app.title = '堆叠条形图';
option = {
 tooltip : {
 trigger: 'axis',
 axisPointer : { // 坐标轴指示器,坐标轴触发有效
 type : 'shadow' // 默认为直线,可选为:'line' | 'shadow'
 }
 },
 legend: {
 data: ['直接访问', '邮件营销','联盟广告','视频广告','搜索引擎']
 },
 grid: {
 left: '3%',
 right: '4%',
 bottom: '3%',
 containLabel: true
 },
 xAxis: {
 type: 'value'
 },
 yAxis: {
 type: 'category',
 data: ['周一','周二','周三','周四','周五','周六','周日']
 },
 series: [
 {
 name: '直接访问',
 type: 'bar',
 stack: '总量',
 label: {
 normal: {
 show: true,
 position: 'insideRight'
 }
 },
 data: [320, 302, 301, 334, 390, 330, 320]
 },
 {
 name: '邮件营销',
 type: 'bar',
 stack: '总量',
 label: {
 normal: {
 show: true,
 position: 'insideRight'
 }
 },
 data: [120, 132, 101, 134, 90, 230, 210]
 },
 {
 name: '联盟广告',
 type: 'bar',
 stack: '总量',
 label: {
 normal: {
 show: true,
 position: 'insideRight'
 }
 },
 data: [220, 182, 191, 234, 290, 330, 310]
 },
 {
 name: '视频广告',
 type: 'bar',
 stack: '总量',
 label: {
 normal: {
 show: true,
 position: 'insideRight'
 }
 },
 data: [150, 212, 201, 154, 190, 330, 410]
 },
 {
 name: '搜索引擎',
 type: 'bar',
 stack: '总量',
 label: {
 normal: {
 show: true,
 position: 'insideRight'
 }
 },
 data: [820, 832, 901, 934, 1290, 1330, 1320]
 }
 ]
};

通过两段代码的对比,我们还需要对 tooltip、legend、grid 进行封装,其余的 xAxis、yAxis、series 已经封装过了,只不过需要在每个对应的类中添加新增的属性即可。

再重复一下封装百度 Echarts 的思路:

首先,创建一个在 Windows 窗体应用程序中使用的控件项目 LSGO.Core.ECharts。

其次,在该控件项目的设计器中,拖入一个 WebBrowser 控件,并设置其 Dock 属性为 Fill,即让 WebBrowser 充满整个容器。

接着,写一个 InitialECharts 方法,加载指定目录的网页.\assets\echarts.html,让该网页在 WebBrowser 中打开。

当该网页加载完成后,触发 WebBrowser 的 WebBrowserDocumentCompletedEventHandler 事件,在该事件注册的方法中调用该网页中用 JS 写的 showChart 方法,则在该网页中显示图形。

当窗体控件的尺寸发生变化后,触发 WebBrowser 的 SizeChanged 事件,在该事件注册的方法中调用该网页中用 JS 写的 setPosition 方法,则重新调整显示图形的布局,以满足新的尺寸。

封装控件的代码、初始网页的代码以及调用对应 JS 的代码,参见:如何利用C# + Echarts 绘制 Bar Simple?。咱们这里只写进一步封装 Echarts 的代码。


代码实现

Step01 对tooltip的封装

封装 坐标轴指示器 AxisPointer

public class AxisPointer
{
 /// <summary>
 /// 'line' 直线指示器;
 /// 'shadow' 阴影指示器;
 /// 'none' 无指示器
 /// </summary>
 public string type { get; set; } = "line";
}

封装 提示框组件 Tooltip

public class Tooltip
{
 /// <summary>
 /// 触发类型
 /// 'item':数据项图形触发,主要在散点图,饼图等无类目轴的图表中使用。
 /// 'axis':坐标轴触发,主要在柱状图,折线图等会使用类目轴的图表中使用。
 /// 'none':什么都不触发。
 /// </summary>
 public string trigger { get; set; } = "item";
 /// <summary>
 /// 坐标轴指示器
 /// </summary>
 public AxisPointer axisPointer { get; set; }
}

Step02 对legend的封装

public class Legend
{
 /// <summary>
 /// 图例的类型。
 /// 可选值:'plain','scroll'
 /// </summary>
 public string type { get; set; } = "plain";
 /// <summary>
 /// 图例列表的布局朝向。
 /// 'horizontal''vertical'
 /// </summary>
 public string orient { get; set; } = "horizontal";
 /// <summary>
 /// 图例组件离容器左侧的距离。
 /// </summary>
 public string left { get; set; } = "auto";
 /// <summary>
 /// 图例组件离容器上侧的距离。
 /// </summary>
 public string top { get; set; } = "auto";
 /// <summary>
 /// 图例组件离容器右侧的距离。
 /// </summary>
 public string right { get; set; } = "auto";
 /// <summary>
 /// 图例组件离容器下侧的距离。
 /// </summary>
 public string bottom { get; set; } = "auto";
 /// <summary>
 /// 图例的数据数组。
 /// </summary>
 public List<string> data { get; set; }
}

Step03 对 grid 的封装

public class Grid
{
 /// <summary>
 /// grid 组件离容器上侧的距离。
 /// </summary>
 public string top { get; set; } = "60";
 /// <summary>
 /// grid 组件离容器左侧的距离。
 /// </summary>
 public string left { get; set; } = "10%";
 /// <summary>
 /// grid 组件离容器右侧的距离。
 /// </summary>
 public string right { get; set; } = "10%";
 /// <summary>
 /// grid 组件离容器下侧的距离。
 /// </summary>
 public string bottom { get; set; } = "60";
 /// <summary>
 /// grid 区域是否包含坐标轴的刻度标签。
 /// </summary>
 public bool containLabel { get; set; } = false;
}

Step04 对整体的集成 Option

public class Option
{
 /// <summary>
 /// title
 /// </summary>
 public Title title { get; set; }
 /// <summary>
 /// tooltip
 /// </summary>
 public Tooltip tooltip { get; set; }
 /// <summary>
 /// legend
 /// </summary>
 public Legend legend { get; set; }
 /// <summary>
 /// grid
 /// </summary>
 public Grid grid { get; set; }
 /// <summary>
 /// x轴
 /// </summary>
 public XAxis xAxis { get; set; }
 /// <summary>
 /// y轴
 /// </summary>
 public YAxis yAxis { get; set; }
 /// <summary>
 /// 数据
 /// </summary>
 public List<SeriesItem> series { get; set; }
}

总结

集成 Echarts 之后客户端的代码,对应百度的 Demo:

private List<string> GetLegendData()
{
 List<string> reslut = new List<string>
 {
 "直接访问",
 "邮件营销",
 "联盟广告",
 "视频广告",
 "搜索引擎"
 };
 return reslut;
}
private List<string> GetYAxisData()
{
 List<string> reslut = new List<string>
 {
 "周一",
 "周二",
 "周三",
 "周四",
 "周五",
 "周六",
 "周日"
 };
 return reslut;
}
private List<SeriesItem> GetSeries()
{
 List<SeriesItem> result = new List<SeriesItem>();
 SeriesItem item1 = new SeriesItem
 {
 name = "直接访问",
 type = "bar",
 stack = "总量'",
 data = new List<double>
 {
 320,
 302,
 301,
 334,
 390,
 330,
 320
 },
 label = new LSGO.Core.ECharts.Label
 {
 show = true,
 position = "insideRight"
 }
 };
 SeriesItem item2 = new SeriesItem
 {
 name = "邮件营销",
 type = "bar",
 stack = "总量'",
 data = new List<double>
 {
 120,
 132,
 101,
 134,
 90,
 230,
 210
 },
 label = new LSGO.Core.ECharts.Label
 {
 show = true,
 position = "insideRight"
 }
 };
 SeriesItem item3 = new SeriesItem
 {
 name = "联盟广告",
 type = "bar",
 stack = "总量'",
 data = new List<double>
 {
 220,
 182,
 191,
 234,
 290,
 330,
 310
 },
 label = new LSGO.Core.ECharts.Label
 {
 show = true,
 position = "insideRight"
 }
 };
 SeriesItem item4 = new SeriesItem
 {
 name = "视频广告",
 type = "bar",
 stack = "总量'",
 data = new List<double>
 {
 150,
 212,
 201,
 154,
 190,
 330,
 410
 },
 label = new LSGO.Core.ECharts.Label
 {
 show = true,
 position = "insideRight"
 }
 };
 SeriesItem item5 = new SeriesItem
 {
 name = "搜索引擎",
 type = "bar",
 stack = "总量'",
 data = new List<double>
 {
 820,
 832,
 901,
 934,
 1290,
 1330,
 1320
 },
 label = new LSGO.Core.ECharts.Label
 {
 show = true,
 position = "insideRight"
 }
 };
 result.AddRange(new SeriesItem[]
 {
 item1, item2, item3, item4, item5
 });
 return result;
}
private void Form1_Load(object sender, EventArgs e)
{
 Option option = new Option
 {
 tooltip = new Tooltip
 {
 trigger = "axis",
 axisPointer = new AxisPointer
 {
 type = "shadow"
 }
 },
 legend = new Legend
 {
 data = GetLegendData()
 },
 grid = new Grid
 {
 left = "3%",
 right = "4%",
 bottom = "3%",
 containLabel = true
 },
 xAxis = new XAxis {type = "value"},
 yAxis = new YAxis
 {
 type = "category",
 data = GetYAxisData()
 },
 series = GetSeries(),
 };
 echarts1.InitialECharts(option);
}

代码对应结果如下:

Demo

当然,咱们封装「堆叠条形图」是为了解决实际问题,来看看这个控件在实际中的应用。

基于保护类型的缺陷原因分布情况

应用01

基于生产厂家的缺陷原因分布情况

应用02

好了,今天就到这里吧!希望咱们一起学习的知识对大家有用!See You!


相关图文

  • 如何利用 C# 实现 K 最邻近算法?
  • 如何利用 C# 实现 K-D Tree 结构?
  • 如何利用 C# + KDTree 实现 K 最邻近算法?
  • 如何利用 C# 对神经网络模型进行抽象?
  • 如何利用 C# 实现神经网络的感知器模型?
  • 如何利用 C# 实现 Delta 学习规则?
  • 如何利用 C# 爬取带 Token 验证的网站数据?
  • 如何利用 C# 向 Access 数据库插入大量数据?
  • 如何利用 C# 开发「桌面版百度翻译」软件!
  • 如何利用 C# 开发「股票数据分析软件」(上)
  • 如何利用 C# 开发「股票数据分析软件」(中)
  • 如何利用 C# 开发「股票数据分析软件」(下)
  • 如何利用 C# 爬取「财报说」中的股票数据?
  • 如何利用 C# 爬取 One 持有者返利数据!
  • 如何利用 C# 爬取Gate.io交易所的公告!
  • 如何利用 C# 爬取BigOne交易所的公告!
  • 如何利用 C# 爬取 ONE 的交易数据?
  • 如何利用 C# 爬取「猫眼电影:热映口碑榜」及对应影片信息!
  • 如何利用 C# 爬取「猫眼电影专业版:票房」数据!
  • 如何利用 C# 爬取「猫眼电影:最受期待榜」及对应影片信息!
  • 如何利用 C# 爬取「猫眼电影:国内票房榜」及对应影片信息!
  • 如何利用 C# + Python 破解猫眼电影的反爬虫机制?
  • 如何利用BigOne的API制作自动化交易系统 -- 身份验证
  • 如何利用BigOne的API制作自动化交易系统 -- 获取账户资产
  • 如何利用BigOne的API制作自动化交易系统 -- 订单系统
举报
评论 0