图表

当接到类似以上需求时,你的第一想法是不是跟我一样,使用 Canvas 来绘制,啥都不说就开始撸代码。如果你是用 Vue 之类的 MVVM 框架,那意味着你得提供一个结点供 Canvas 着陆,同时让 Canvas 能够响应数据变动。

写起代码来应该是长这样的:

<template><canvas ref="chart"></canvas>
</template>
<script>/* eslint-disable */import Chart from 'utils/chart'export default {props: {duration: {type: Number,default: 2000},data: {type: Object,default: []}},watch: {'data' (val, oldVal) {this.redraw()}},mounted () {this.chart = Chart.init(this.$refs.chart)this.redraw()},methods: {redraw () {this.chart.draw({duration: this.duratioin})}}}
</script>

类似的做法之前写过很多,比如上一篇文章里面绘制六芒星的方式,但是这种做法成本比较大,首先你得从‘头’开始写代码(创建 Canvas,计算所有坐标点,绘制所有可视内容),同时要求你熟练掌握 Canvas API,并且能够在两种不同的开发思想下来回切换代码,总体上成本较高,所以当设计师给我这样的设计稿时,我是拒绝的!(直接放个数字不行吗,搞这么麻烦)

当然这种为自己偷懒而找的理由最终都会被驳回,因为在你身经百战的 Leader 眼里,这些小 Case 都是不经入目的。

“有工作量吗?” —— Leader
“没有没有。” —— 我

需求接都接了,一个字,干!
做是肯定要做的了,那么应对这种需求,有没有更顺滑的方式?尝试下用 SVG 吧。

SVG 是什么就不说了。SVG 很很突出的一个特性是,用文本编辑器打开就能看到源代码,编辑保存就能修改图片!!!

<svg width="100" height="100"><circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
</svg>

SVG 的属性很多,但还好一眼就能看出什么意思。了解一番之后,设计稿直接切图导出,拿到类似这样的东西:

<svg width="622px" height="245px" viewBox="0 0 622 245" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><circle id="path-1" cx="10" cy="16" r="10"></circle><filter x="-37.5%" y="-37.5%" width="175.0%" height="175.0%" filterUnits="objectBoundingBox" id="filter-2"><feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset><feGaussianBlur stdDeviation="2.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur><feColorMatrix values="0 0 0 0 0   0 0 0 0 0   0 0 0 0 0  0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix></filter><!--省略--></defs><g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g  transform="translate(0.000000, -1.000000)"><g id="曲线" transform="translate(18.000000, 33.000000)"><!-- 这是一条曲线 --><path d="M10.6640625,19.6210938 C39.8348416,119.651983 77.4858832,169.520472 123.617188,169.226563 C231.858912,168.536938 285.925216,10.7569151 351.429688,10.1484375 C405.739364,9.64394951 415.953125,132.3125 464.898438,132.3125 C493.393229,132.3125 531.016927,113.764323 577.769531,76.6679688" stroke="#47E0FF" stroke-width="6" stroke-linecap="round"></path><!-- 这是一个点 --><g id="Oval-6"><use fill="black" fill-opacity="1" filter="url(#filter-2)" xlink:href="#path-1"></use><use fill="#47E0FF" fill-rule="evenodd" xlink:href="#path-1"></use></g><!--省略--></g></g></g>
</svg>

密密麻麻一堆像乱码的东西,但是能看出来,defs 里面定义了一些图形,通过 use 被引用,然后 path 就是那条曲线。

defs 里面我们不需要关心,设计师帮我们画好了。我们关心的是点的位置,曲线的位置,锚点。其他的都可以不用管。

点的位置,可以通过控制 g 元素的 translate 进行偏移也好写。那么线是怎么控制的?path 这里只有一个 d 属性。

<path d="M10.6640625,19.6210938 C39.8348416,119.651983 77.4858832,169.520472 123.617188,169.226563 C231.858912,168.536938 285.925216,10.7569151 351.429688,10.1484375 C405.739364,9.64394951 415.953125,132.3125 464.898438,132.3125 C493.393229,132.3125 531.016927,113.764323 577.769531,76.6679688" stroke="#47E0FF" stroke-width="6" stroke-linecap="round"></path>

看代码容易蒙圈,对照下指令表就清晰多了。

SVG Path 指令列表
/Users/helkyle/projects/w3ctrain
图片来自 SVG 研究之路 (4) - Path 基礎篇

所以 d 属性的值就是一堆指令和点的有机组合。
设计师用画笔绘制曲线的时候也不是一像素一像素绘制的,而是先定一个起点(M),选择点模式(这里用的是二阶贝塞尔曲线 C),选中下一个点,然后确定两个控制点,然后第二个点为起始点,继续描绘。

链接了生成规则之后,通过 Vue 的 computed 自动生成 d,轻而易举。

path () {let steps = []this.valueArr.forEach((curr, index) => {if (index === 0) {// 移动到起点steps.push('M' + curr.x + ',' + curr.y)}if (index !== this.valueArr.length - 1) {let next = this.valueArr[index + 1]// 两个控制点坐标var ctrl1 = {x: (curr.x + next.x) * 0.5,y: curr.y}var ctrl2 = {x: ctrl1.x,y: next.y}steps.push('C' + ctrl1.x + ',' + ctrl1.y)steps.push(ctrl2.x + ',' + ctrl2.y)steps.push(next.x + ',' + next.y)}})return steps.join(' ')
}

为了让曲线看上去比较均匀,自然,我们选择让两个控制点的 x 值为起始点和结束点的 x 值的中间值,y 值分别还是起始点和结束点的 y 值。

cubic-bezier
通过工具更容易看出来怎么选择控制点的位置 cubic-bezier

代码调整一下,再结合 Tween 来实现渐进动画。

doAnimation () {animation.progress = 0new TWEEN.Tween(animation).delay(1000).to({progress: 1}, this.duration, TWEEN.Easing.Quadratic.Out).onUpdate(this.onUpdate).start()
},
onUpdate () {this.valueArr.forEach((item) => {item.y = item.startY + (item.targetY - item.startY) * this.animation.progress})}

效果如下:

line-chart-animation

通过 Vue 的数据-视图绑定,我们只需要修改 data 数组的值,和 progress 动画进度,就可以实现图表数据更新和曲线动画了。又一次,我们的关注点回归到我们无比熟悉的数据层,Niceeeeeeeee!

设计稿出自伟大的 Ray.John

codepen地址

如需转载,请注明出处: http://w3ctrain.com/2017/09/19/vue-svg-chart/

使用 Vue SVG 快速绘制曲线图(带动画)相关推荐

  1. MATLAB 快速绘制曲线图的形状,粗细,颜色

    目录 MATLAB 快速绘制曲线图的形状,粗细,颜色 1.通过改变R-G-B 的值改变线条的颜色: 2.通过改变c∈[1,+∞)的值改变线条的粗细: 3.线条形状,粗细,颜色选择: 4.Matlab中 ...

  2. vue实现签到功能,带动画需引入animate,无接口

    首先需要引入animate动画组件下载css样式 animate动画库下载提取码: k9qz html <template><div class="sign"&g ...

  3. iOS开发(OC)——折线图的绘制(带动画)

    新建一个DrawLine类继承UIView DrawLine.h代码 @property (nonatomic,strong)NSMutableArray *data;@property (nonat ...

  4. vue实现签到功能,带动画需引入animate,有接口

    首先需要引入animate动画组件下载css样式 animate动画库下载提取码: k9qz html <template><div class="sign"&g ...

  5. vue鼠标移入移除带动画事件实例

    vue鼠标移入移除事件实例 文章目录 vue鼠标移入移除事件实例 效果图: 一. 技术分析 二.实例的实现分析 1. 初始状态 2. 鼠标移入状态 3. 鼠标移出状态 三.源代码 四.举一反三的例子 ...

  6. layui做折线图_绘制曲线图/折线图只需4步

    绘制曲线图/折线图只需4步 8390251284.gif 下载YJGraph文件拖入工程后 1.导入头文件 #import "YJGraphView.h" #import &quo ...

  7. vue伸缩效果_Vue2(三)实现子菜单展开收缩,带动画效果实现方法

    以前做这种操作就是简单的display:block,但现在用户的要求也越来越高,需要美观和动画感. 现在介绍用一种简单的方式来实现子菜单从上向下展开子菜单. 看下效果图: 点开效果: 其实原理比较简单 ...

  8. GDI+入门(5、在GDI+中绘制带动画效果的图片)

    五.在GDI+中绘制带动画效果的图片 private void Form2_Load(object sender, EventArgs e) { SetStyle(ControlStyles.Doub ...

  9. html5快速制作,html5动画制作(教你如何快速绘制HTML5动画)

    html5动画制作(教你如何快速绘制HTML5动画) 本周在给学生讲授JavaScript课程中setInterval方法时,想到了我们在网上看到的各类GIF动图比较有意思,就将其引入到教学中,教学内 ...

最新文章

  1. 面向对象数据库和关系数据库的区别
  2. 初识 Vue(18)---(非父子组件间的传值)
  3. 数据库开发——MySQL——索引原理
  4. java io流文件损坏_java使用io流下载.docx. xlsx文件,出现文件损坏提示
  5. java基础之lambda表达式
  6. 入门讲解:使用numpy实现简单的神经网络(BP算法)
  7. linux 主机大华 摄像头,linux设备上的Onvif 实现21:解决大华摄像头无法使用问题...
  8. c++删除数组中重复元素_C / C ++中的数组
  9. ffmpeg中的时间单位
  10. DOS命令与批处理学习历程
  11. 计算机开关机命令,电脑自动关机命令
  12. bootstrap 日历
  13. 数据库优化方案之分库分表
  14. 那些年,我们一起做过的 Java 课后练习题(71 - 75)
  15. eBPF系列学习(4)了解libbpf、CO-RE (Compile Once – Run Everywhe) | 使用go开发ebpf程序(云原生利器cilium ebpf )
  16. Altium Designer使用介绍和界面介绍
  17. 系统是综合应用最新多媒体计算机技术,RM-6280C多道生理信号采集处理系统
  18. python空间数据处理_基于Python语言的空间数据处理
  19. 学习笔记之——Python中类和对象的理解
  20. < CSS技巧 之 弹性布局( Flex布局 ) - 实例篇 >

热门文章

  1. 网页通过url传递数据
  2. python做相册_《自拍教程73》Python 自动生成相册文件夹
  3. 前端基础之浮动个人相册
  4. 回溯法求解N皇后问题及其时间复杂度分析
  5. 把 14 亿中国人都拉到一个微信群,程序员在技术上能实现吗?
  6. 用python爬取交大图书馆图书信息
  7. 淘淘商城业务--加油
  8. 5G要来了,实际测试告诉你它的速度到底有多快!
  9. 数据库查询中的n+1问题
  10. Revit相关问题:符号线,转转问题,生成三维视图