如何绘制好看的动态排序图,今天手把手教学

开发 项目管理
学了 Java之后才知道自己是有多菜,,,以前并没有刻意的去了解语言背后的基础知识,例如进程、内存管理,比如程序启动后没报错但长时间没有反应、通过任务管理器发现资源一直在消耗着;是一直等着或者重新再启动程序,还是去定位问题并解决、优化代码,如果要定位问题从哪里下手?

[[403827]]

本文转载自微信公众号「小张Python」,作者zeroingi 。转载本文请联系小张Python公众号。

 0. 前言

大家好啊,已经好久没更原创文了,失踪人口回归 ~,近期要准备秋招了在学一些 Java 相关知识,更文什么的也就耽搁了

之前一直是在与 Python 打交道,但这不马上要找工作了么,Python 虽然全能但目前不是企业所需的主流语言,跟C++、Java 相比还挺弱势的,因此想借此好好学一下 Java,希望能赶上秋招的末班车

学了 Java之后才知道自己是有多菜,,,以前并没有刻意的去了解语言背后的基础知识,例如进程、内存管理,比如程序启动后没报错但长时间没有反应、通过任务管理器发现资源一直在消耗着;是一直等着或者重新再启动程序,还是去定位问题并解决、优化代码,如果要定位问题从哪里下手?

网络TCP/IP 协议:猜测现在看这篇文章的很多小伙伴们是为了学爬虫而学 Python,现在也有两个问题问大家:1,Response Headers 中常见的Cookie 、Session指的是什么, 针对反爬机制带 Cookie去访问服务器的原理又是什么?2,当请求目标站点获取数据时,返回的状态码中2xx,3xx,4xx分别代表什么?以上列举的这两个问题都与计算机网络相关,了解它们之后做爬虫的话才更能游刃有余,而类似于正则、bs4文本解析只是工具而已,学习的话上手很快

垃圾回收、缓存一致性等相关知识:有时候为了缩短任务执行周期,会用到线程,使用时 Python 中的 GIL(全局解释器锁)能够保证程序运行时的数据一致性问题,但里面的原理机制是什么?

后来接触了这些知识才发现,操作系统、语言特性、计算机网络、数据结构与算法这些基础知识才是计算机入门的开始(语言只能说是一种工具),只有掌握了基础知识,以后的学习之路才会更扎实、更顺利;也就应证了一句老话 基础不牢、地动山摇

平常的我只知道为了一些功能学习一下相关库函数,把脚本实现出来即可俗称 调包侠 吧。也希望大家在以后的学习路上引以为戒,重视基础知识。

1. anichart 介绍

啰嗦了这么多,正式开始本期技术案例分享,关于动态排序图制作之前分享过一篇文章,用的是 matplolib 的 animation 函数,感兴趣的可以看下用python制作超燃动态排序图!

基本功能是实现了,但最终效果并不那么友好,这种方法制图的基本原理就是先把数据借助 Matplotlib 可视化为每一帧图片,再将每一帧拼接为视频,缺点很明显:步骤繁琐、代码量多,可视化效果差

今天分享另外一种方法,制作此类状态图,用到的是一个 Github 项目 anichart,众所周知目前如果想做一些丝滑流畅的可视化交互效果,javascripts 是必不可缺少的,而这个项目主要是用 typescript 实现,项目是由一个 B 站 Up主【Jannchie见齐】维护

typescript 语言是基于 js 开发的一门编程语言,为了弥补后者可维护性差、类型混乱等缺点;anichart 的主要功能是来制作动态排序图,可视化效果要好得多,下面是我根据针对项目中提供的测试数据最终绘制的排序图,

2. 环境介绍

先交代下本次用到的项目环境,anichart 整体算是一个前端项目,因此本次用到的工具都是一些与前端相关的,本期教程只是介绍给大家这个项目怎么用,关于具体细节不需要去考虑,所以无需担心自己是否具备前端知识;

需要用到的软件如下:

  • node.js;
  • ffmpeg;

测试系统为 Win10;

Node.js 在这里主要有两个作用:1,管理下载项目所需要的一些依赖项,2,启动 js 脚本;

ffmpeg 主要是将序列图片转化为视频

关于 node.js 与 ffmpeg 在 windows下载安装方式比较简单,这里不多做介绍啦,这里给大家推荐两个链接可以参考下:

Node.js 安装:https://www.jianshu.com/p/2958fc051bfb

ffmpeg 安装:https://zhuanlan.zhihu.com/p/118362010

两个软件安装好之后,不要忘记配置环境变量~

3. anichart 库使用

3.1 anichart安装

anichart 作者已经把上传至 npm 官网中,打开命令行,借助 npm i anichart 命令即可安装,不需要我们再从 Github 上克隆,

npm是什么东东?npm其实是Node.js的包管理工具(package manager),也就是说你配置好 Node.js 命令之后,npm 就可以正常使用了

3.2 新建一个 js文件

安装完之后,接下来就能使用了,在anichart 安装路径下 新建一个 js 文件,文件名可任意命名,然后把下面代码添加到刚刚建立的 js 文件

  1. const ani = require('anichart'
  2. const stage = new ani.Stage() 
  3. stage.options.fps = 24 
  4. stage.options.sec = 30 
  5. stage.output = false 
  6.  
  7. const bgAni = new ani.RectAni() 
  8. bgAni.component.shape = { 
  9.   width: stage.canvas.width, 
  10.   height: stage.canvas.height, 
  11. bgAni.component.fillStyle = '#1e1e1e' 
  12.  
  13. const textLinesAni = new ani.TextLinesAni() 
  14.  
  15. textLinesAni.component.fillStyle = '#eee' 
  16. textLinesAni.component.textAlign = 'center' 
  17. textLinesAni.component.textBaseline = 'middle' 
  18. textLinesAni.component.position = { 
  19.   x: stage.canvas.width / 2, 
  20.   y: stage.canvas.height / 2, 
  21.  
  22. const textAnichart = new ani.TextAni() 
  23. textAnichart.component.fontSize = 48 
  24. textAnichart.component.font = 'Sarasa Mono Slab SC' 
  25. textAnichart.component.text = 'Anichart' 
  26. textAnichart.component.fontWeight = 'bolder' 
  27. textAnichart.type = 'blur' 
  28.  
  29.  
  30. textLinesAni.children.push(textAnichart) 
  31.  
  32.  
  33. ani.recourse.loadImage('H:/Data/data/ANI.png''logo'
  34. ani.recourse.loadImage( 
  35.   'https://avatars3.githubusercontent.com/u/29743310?s=460&u=8e0d49b98c35738afadc04e70c7f3918d6ad8cdb&v=4'
  36.   'jannchie' 
  37.  
  38. ani.recourse.loadCSV('H:/Data/data/test.csv''data'
  39.  
  40.  
  41. const rectAni = ani.createAni( 
  42.   [ 
  43.     new ani.Rect({ 
  44.       position: { x: 100, y: 0 }, 
  45.       shape: { width: 100, height: 0 }, 
  46.       fillStyle: '#d23'
  47.     }), 
  48.     new ani.Rect({ 
  49.       shape: { width: 100, height: 200 }, 
  50.       fillStyle: '#2a3'
  51.       alpha: 1, 
  52.     }), 
  53.     new ani.Rect({ 
  54.       shape: { width: 100, height: 0 }, 
  55.       fillStyle: '#569'
  56.       alpha: 0, 
  57.     }), 
  58.   ], 
  59.   [0, 1, 2], 
  60.   ani.ease.easeElastic 
  61.  
  62. const logoCenter = new ani.Image({ 
  63.   path: 'H:/Data/data/ANI.png'
  64.   position: { 
  65.     x: stage.canvas.width / 2, 
  66.     y: stage.canvas.height / 2, 
  67.   }, 
  68.   alpha: 0.25, 
  69.   center: { x: 128, y: 128 }, 
  70.   shape: { width: 256, height: 256 }, 
  71. }) 
  72. const logoAni = ani.createAni( 
  73.   [ 
  74.     new ani.Image({ 
  75.       path: 'H:/Data/data/ANI.png'
  76.       position: { 
  77.         x: 0, 
  78.         y: stage.canvas.height - 108, 
  79.       }, 
  80.       shape: { width: 128, height: 128 }, 
  81.     }), 
  82.     new ani.Image({ 
  83.       path: 'H:/Data/data/ANI.png'
  84.       position: { 
  85.         x: stage.canvas.width - 128, 
  86.         y: stage.canvas.height - 108, 
  87.       }, 
  88.       shape: { width: 128, height: 128 }, 
  89.       alpha: 1.0, 
  90.     }), 
  91.     new ani.Image({ 
  92.       path: 'H:/Data/data/ANI.png'
  93.       position: { 
  94.         x: stage.canvas.width - 128, 
  95.         y: stage.canvas.height - 108, 
  96.       }, 
  97.       shape: { width: 128, height: 128 }, 
  98.       alpha: 0, 
  99.     }), 
  100.   ], 
  101.   [0, 1, 2], 
  102.   ani.ease.easeBounce 
  103.  
  104. const barChart = new ani.BarChart({ 
  105.   shape: { width: stage.canvas.width, height: stage.canvas.height }, 
  106.   labelFormat(id) { 
  107.     return id 
  108.     // return meta.get(id).name
  109.   }, 
  110.   aniTime: [0, 30], 
  111. }) 
  112.  
  113. const lineChart = new ani.LineChart({ 
  114.   aniTime: [0, 30], 
  115.   shape: { width: stage.canvas.width, height: stage.canvas.height / 2 }, 
  116.   position: { x: 0, y: stage.canvas.height / 2 }, 
  117. }) 
  118.  
  119.  
  120. stage.addChild(bgAni) 
  121. // stage.addChild(a) 
  122. stage.addChild(logoCenter) 
  123. stage.addChild(textLinesAni) 
  124. stage.addChild(rectAni) 
  125. stage.addChild(logoAni) 
  126. stage.addChild(barChart) 
  127. stage.addChild(lineChart) 
  128.  
  129.  
  130. const pie = new ani.PieChart({ 
  131.   aniTime: [0, 30], 
  132.   radius: [80, 120], 
  133.   position: { x: stage.canvas.width / 2, y: stage.canvas.height / 2 }, 
  134. }) 
  135.  
  136. stage.addChild(pie) 
  137. stage.play() 

运行之前,需要改几个参数,第一个更改数据路径

  1. ani.recourse.loadCSV('H:/Data/data/test.csv''data'

数据形式需以下面形式存放,后面 data 代表数据源中更改的列名,比如这里是以日期作为变量进行序列化

  1. name,date,value,channel,other 
  2. Jannchie,2020-01-01,1,科技,other 
  3. Jannchie,2020-01-03,6,科技,other 
  4. Jannchie,2020-01-05,3,科技,other 
  5. Jannchie,2020-01-07,-,科技,other 
  6. Jannchie,2020-01-09,7,科技,other 
  7. Jannchie,2020-01-12,12,科技,other 
  8. Cake47,2020-01-03,10,生活,other 
  9. Cake47,2020-01-02,5,生活,other 
  10. Cake47,2020-01-06,2,生活,other 
  11. Cake47,2020-01-09,3,生活,other 
  12. Cake47,2020-01-11,4,生活,other 

第二个需要更改一下所有 png 路径,改成你自己的,可以随意替换为你的 图片路径,影响不大

  1. ani.recourse.loadImage('H:/Data/data/ANI.png''logo'

3.2 运行 js 脚本

以上修改完之后,接下来就是启动脚本,在 js 同文件目录下打开一个命令行,输入 node XXX.js ,回车即可,XXX.js 代表你的 js 文件,效果如下

之后会有一个out 文件夹生成,里面存放的就是 anichart 绘制好的图片

3.3 借助ffmpeg图片生成视频

最后,进入out 文件夹,借助ffmpeg 命令将图片合成视频,

  1. ffmpeg -f image2 -framerate 12 -i output-%d.png foo.avi 

-framerate 后面参数 12 代表生成视频的fps,可 根据自己情况设定,这里我设置的是 24;

最终一个动态排序视频就生成了,随后自己也可以加一些 bgm 给视频加一些 feel

4. js中一些参数介绍

关于 anichart 的使用,原作者并没有介绍太多,Github 主页上只介绍了最简单的使用方法

因此为了大家生成一些比较不错的可视化图,对上面 js 代码中的部分参数做一些简单介绍,增加一些对这个 anichart 库的理解

4.1 fps、sec

  1. stage.options.fps = 24 
  2.  
  3. stage.options.sec = 30 

fps 顾名思义就是一秒多少帧,sec 代表生成切片持续多长时间(单位:秒);用上面参数来设定的话,会生成 24x30 = 720 张图片;这两个参数决定最终视频的流畅度,后面用 ffmpeg 生成视频时,建议 framerate 参数 fps保持 一致

4.2 ani.recourse.loadImage

  1. ani.recourse.loadImage( 
  2.   'https://avatars3.githubusercontent.com/u/29743310?s=460&u=8e0d49b98c35738afadc04e70c7f3918d6ad8cdb&v=4'
  3.   'jannchie' 

loadImage用来给柱状图中每个数据条上加一个 图片 logo,方法需要加入两个参数,前者表示图片路径或网页链接,后者表示需要加logo 的数据条名字,例如这里选择的数据条名字为 jannchie,可视化效果如下

4.3 BarChart、LineChart、PieChart

BarChart、LineChart、PieChart 分别表示柱状图、曲线图、饼图;anichart 除了这三类图形外还有 ItemChart、BaseChart、MapChart 等,

anichart 在所有图形对象中,都需要加入两个参数,shape 和 aniTime,前者代表形状大小、后者表示该图形持续时间,单位 s

4.4 stage.addChild(xx)

anichart 通过 stage.addChild() 函数使得创建的对象生效 ,stage 表示全局 画布,通过以下命令生成

  1. const ani = require('anichart'
  2.  
  3. const stage = new ani.Stage() 

5. 源码数据获取

为了方便,本文中涉及到的源码、测试数据已经被我打包在一起了,获取方式:在公众号 小张Python 后台,回复关键字:210605 即可获取

6. 小结

关于动态排序图制作除了这两种方法之外,再向大家推荐一个网站名叫 flourish,网址:https://flourish.studio/examples/

flourish 最终生成效果也非常不错,但缺点是需要微调大量参数

好了,关于排序图的制作就介绍到这里了,如果内容对你有帮助的话不妨点个赞来鼓励一下我~

 

责任编辑:武晓燕 来源: 小张Python
相关推荐

2022-07-27 08:16:22

搜索引擎Lucene

2022-12-07 08:42:35

2021-12-06 18:22:15

数据项目技术

2021-01-27 21:55:13

代码参数值ECharts

2014-08-08 13:22:54

测试手机站点移动设备

2022-06-06 08:50:40

CIOIT转型

2021-01-19 09:06:21

MysqlDjango数据库

2021-07-14 09:00:00

JavaFX开发应用

2022-02-16 16:24:05

HarmonyOS鸿蒙操作系统

2009-08-27 18:10:58

PHP绘制3D图形

2021-01-21 09:10:29

ECharts柱状图大数据

2011-04-28 09:23:36

REST

2022-05-10 10:43:35

数据源动态切换Spring

2021-09-26 16:08:23

CC++clang_forma

2010-07-06 09:43:57

搭建私有云

2021-11-09 06:55:03

水印图像开发

2010-07-06 09:38:51

搭建私有云

2011-01-10 14:41:26

2011-05-03 15:59:00

黑盒打印机

2009-10-21 10:47:03

Siliverligh
点赞
收藏

51CTO技术栈公众号