如何绘制好看的动态排序图,教你用 js包 anichart 来实现

1. anichart 介绍

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

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

image-20210604131428463

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

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

(img-ZXk1tRET-1622908645251]

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 上克隆,

image-20210604171440229

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

3.2 新建一个 js文件

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

const ani = require('anichart')
const stage = new ani.Stage()
stage.options.fps = 24
stage.options.sec = 30
stage.output = false

const bgAni = new ani.RectAni()
bgAni.component.shape = {
  width: stage.canvas.width,
  height: stage.canvas.height,
}
bgAni.component.fillStyle = '#1e1e1e'

const textLinesAni = new ani.TextLinesAni()

textLinesAni.component.fillStyle = '#eee'
textLinesAni.component.textAlign = 'center'
textLinesAni.component.textBaseline = 'middle'
textLinesAni.component.position = {
  x: stage.canvas.width / 2,
  y: stage.canvas.height / 2,
}

const textAnichart = new ani.TextAni()
textAnichart.component.fontSize = 48
textAnichart.component.font = 'Sarasa Mono Slab SC'
textAnichart.component.text = 'Anichart'
textAnichart.component.fontWeight = 'bolder'
textAnichart.type = 'blur'


textLinesAni.children.push(textAnichart)


ani.recourse.loadImage('H:/Data/data/ANI.png', 'logo')
ani.recourse.loadImage(
  'https://avatars3.githubusercontent.com/u/29743310?s=460&u=8e0d49b98c35738afadc04e70c7f3918d6ad8cdb&v=4',
  'jannchie'
)

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


const rectAni = ani.createAni(
  [
    new ani.Rect({
      position: { x: 100, y: 0 },
      shape: { width: 100, height: 0 },
      fillStyle: '#d23',
    }),
    new ani.Rect({
      shape: { width: 100, height: 200 },
      fillStyle: '#2a3',
      alpha: 1,
    }),
    new ani.Rect({
      shape: { width: 100, height: 0 },
      fillStyle: '#569',
      alpha: 0,
    }),
  ],
  [0, 1, 2],
  ani.ease.easeElastic
)

const logoCenter = new ani.Image({
  path: 'H:/Data/data/ANI.png',
  position: {
    x: stage.canvas.width / 2,
    y: stage.canvas.height / 2,
  },
  alpha: 0.25,
  center: { x: 128, y: 128 },
  shape: { width: 256, height: 256 },
})
const logoAni = ani.createAni(
  [
    new ani.Image({
      path: 'H:/Data/data/ANI.png',
      position: {
        x: 0,
        y: stage.canvas.height - 108,
      },
      shape: { width: 128, height: 128 },
    }),
    new ani.Image({
      path: 'H:/Data/data/ANI.png',
      position: {
        x: stage.canvas.width - 128,
        y: stage.canvas.height - 108,
      },
      shape: { width: 128, height: 128 },
      alpha: 1.0,
    }),
    new ani.Image({
      path: 'H:/Data/data/ANI.png',
      position: {
        x: stage.canvas.width - 128,
        y: stage.canvas.height - 108,
      },
      shape: { width: 128, height: 128 },
      alpha: 0,
    }),
  ],
  [0, 1, 2],
  ani.ease.easeBounce
)

const barChart = new ani.BarChart({
  shape: { width: stage.canvas.width, height: stage.canvas.height },
  labelFormat(id) {
    return id
    // return meta.get(id).name;
  },
  aniTime: [0, 30],
})

const lineChart = new ani.LineChart({
  aniTime: [0, 30],
  shape: { width: stage.canvas.width, height: stage.canvas.height / 2 },
  position: { x: 0, y: stage.canvas.height / 2 },
})


stage.addChild(bgAni)
// stage.addChild(a)
stage.addChild(logoCenter)
stage.addChild(textLinesAni)
stage.addChild(rectAni)
stage.addChild(logoAni)
stage.addChild(barChart)
stage.addChild(lineChart)


const pie = new ani.PieChart({
  aniTime: [0, 30],
  radius: [80, 120],
  position: { x: stage.canvas.width / 2, y: stage.canvas.height / 2 },
})

stage.addChild(pie)
stage.play()

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

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

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

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

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

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

3.2 运行 js 脚本

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

image-20210604173143277

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

Snipaste_2021-06-04_15-19-26

3.3 借助ffmpeg图片生成视频

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

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

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

Snipaste_2021-06-04_15-22-51

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

image-20210604173944116

4. js中一些参数介绍

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

image-20210604182018595

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

4.1 fps、sec

stage.options.fps = 24
stage.options.sec = 30

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

4.2 ani.recourse.loadImage

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

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

image-20210604184247469

4.3 BarChart、LineChart、PieChart

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

image-20210604185524192

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

4.4 stage.addChild(xx)

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

const ani = require('anichart')
const stage = new ani.Stage()
5. 源码数据获取

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

6. 小结

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

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

image-20210604190833926

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

最后感谢大家的阅读,我们下期见

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Flask 是一种轻量级的 Python Web 框架,它可以轻松的用来实现一个简单、轻量的 Web 应用程序。这里我们可以使用 Flask 和 Python 的数据可视化库 matplotlib 实现动态排序柱状。 首先,我们需要定义 Flask web app,并编写路由函数将数据渲染到模板中。在渲染过程中,我们可以使用 matplotlib 动态生成数据可视化。 接下来,我们需要准备数据。可以使用 Pandas 库读取 CSV 或者 Excel 数据,并对数据进行预处理和排序。 在渲染的模板中,我们可以使用 Bootstrap 中的 JavaScript 和样式来使其更加美观。随着数据的动态排序,我们需要使用 JavaScript 来使得表实时响应。 最后,我们需要编写后端代码响应用户的交互行为,例如通过点击事件实现数据的升降序排列。可以使用 Ajax 技术来使得用户的操作更加平滑和更加自然。 综上所述,Flask 实现动态排序柱状需要的关键技术有 Flask web app、matplotlib 可视化、JavaScript 和 Ajax 等技术。这个过程不仅可以生成有效的数据可视化,同时也可以扩展到更多的 Web 应用程序场景中去。 ### 回答2: Flask是一种Python Web框架,可以帮助我们构建基于Web的应用程序,并且非常适合用于快速构建小型项目或原型。部分网页开发开发者将Flask用于创建动态排序柱状。对于实现这种应用程序,我们需要依赖各种库,例如Flask自身、SQLAlchemy、Matplotlib等。 首先,我们需要用Flask搭建网站框架和链接到数据库。其次,我们可以从数据库中检索数据并通过排序算法得到我们所需的数据。在得到了我们要绘制的数据,我们可以使用Matplotlib库来生成柱状。Matplotlib的pyplot模块提供了plot()函数,可以用来绘制柱状,我们可以通过传递参数,调整参数来实现动态排序柱状。最后,我们需要通过Flask将柱状呈现到前端页面。 在实现这个项目的过程中,需要注意的是如何处理数据和如何让Flask与Matplotlib库交互。此外,为了加强应用程序的交互性,我们可能需要使用JavaScript的AJAX来动态刷新数据并实现动态排序柱状。 总之,Flask对于构建动态排序柱状的应用程序是一个非常好的选择。通过合理使用工具库和加强应用程序的交互性,我们可以实现一个完全动态的柱状应用程序。 ### 回答3: Flask是一款轻量级的Web开发框架,提供了灵活的扩展性,使得开发者可以方便地集成第三方库和API,实现各种功能。为了实现动态排序柱状,我们可以利用Flask的特性,结合JavaScript和HTML/CSS完成相关代码的编写。 首先,在Flask中创建一个新的路由,返回到含柱状数据的JSON格式数据。该数据应该含了要绘制的柱状的名称和值。然后,我们需要在HTML页面上添加一个占位符,以便JavaScript代码能够匹配到这个地方并将数据填充到柱状上。 然后,我们可以使用D3.js这样的JavaScript库来实现动态排序柱状。D3.js非常适合处理数据绘,它具有灵活性和强大的功能,可以让我们在JavaScript中完成所有绘的细节。 在实现动态排序柱状的过程中,我们需要为柱状添加交互性,比如排序柱子,动态更新数据等等。这可以利用JavaScript事件处理器和D3.js库的功能来实现。 最后,我们需要将所有这些组件结合在一起,以创建一个用于动态排序柱状的完整的Flask Web应用程序。我们可以将数据存储在Flask应用程序中,然后使用JavaScript和D3.js来更新柱状。这样,我们就可以实现一个功能强大且灵活的动态排序柱状,让用户能够更好地了解数据的变化和趋势。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员大飞1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值