我们在web端所理解的可视化大都是线,柱,饼等图表,以及这些基础图表的衍生和组合。在技术层面,常见的技术有SVG,canvas和webgl。
canvas基于像素,提供2D和3D绘制函数,通过脚本来绘制图形。canvas在web端常见的使用场景如下:
在IE浏览器上,从IE9开始兼容canvas
(我使用canvas实现了一个五子棋,大家有兴趣可以看看canvas和dom版本的五子棋)
SVG全称是可缩放矢量图形,是一种用来描述二维矢量图形的XML语言(关于SVG可以参考我另一篇博文使用SVG实现圆环loading进度效果)
SVG在web端的使用场景如下:
- 绘制各种图形元素,如多边形和Bezier曲线
- 渲染页面中的图表(icon)
- 制作网站logo
- 绘制线,柱,饼等图表
在图形元素的渲染上,业界的选型各有不同。如echarts使用canvas,highcharts使用的是SVG。但因为SVG在无线浏览器上支持得并不理想,一些现代图表库选择canvas以获得更好的兼容性。
看一个栗子
import React, { Component, PropTypes } from 'react'
import ReactDOM, { findDOMNode } from 'react-dom'
class Graphic extends Component {
static propTypes = {
rotation: propTypes.number,
color: propTypes.string
}
static defaultProps = {
rotation: 0,
color: 'green'
}
componentDidMount(){
const context = findDOMNode(this).getContext('2d');
this.paint(context);
}
componentDidUpdate(){
const context = findDOMNode(this).getContext('2d');
//清除矩形区域
context.clearRect(0, 0, 200, 200);
this.paint(context);
}
//利用传过来的2d上下文进行图形绘制
paint(context){
context.save();
context.translate(100, 100);
context.rotate(this.props.rotation, 100, 100);
context.fillStyle = this.props.color;
context.fillRect(-50, -50, 100, 100);
context.reStore();
}
render(){
return <canvas width={200} height={200} />
}
}
这个例子在画布上绘制了一个正方形,我们可以在使用它的时候传入rotation和color,来改变正方形的角度和颜色。我们看到,canvas是自带生命周期的,包括初始化,绘制和清空,所以在React中加入其它库的方法,就是指融合其它库的生命周期方法到React组件中。
使用SVG和使用其它HTML标签完全没有区别。这里我们来尝试绘制一个Bezier(贝塞尔)曲线。Bezier曲线需要接收起点,终点和控制点这3个控制条件,即我们需要设置这3个prop
import React, { PropTypes } from 'react';
const getPath = (start, end, controlPoints) => {
const [fx, fy, sx, sy] = controlPoints;
const controlPoints01 = [start[0] + fx * (end[0] - start[0]), start[1] + fy * (end[1] - start[1])];
const controlPoints02 = [start[0] + sx * (end[0] - start[0]), start[1] + sy * (end[1] - start[1])];
return 'M${start}C${controlPoints01} ${controlPoints02} $end';
}
const BezierCurve = (props) => {
const { width, height, startPoint, endPoint, controlPoints, ...others } = props;
return (
<svg width = {width} height = {height}>
<path
d = {getPath(startPoint, endPoint, controlPoints)}
fill="none"
stroke="black"
strokeWidth="2"
{...others}
/>
svg>
)
}
BezierCurve.defaultProps = {
width: 400,
height: 400,
controlPoints: [1/3, 0, 2/3, 1],
}
BezierCurve.propTypes = {
width: PropTypes.number,
height: PropTypes.number,
startPoint: PropTypes.arrayOf(PropTypes.number),
endPoint: PropTypes.arrayOf(PropTypes.number),
controlPoints: PropTypes.arrayOf(PropTypes.number)
}
接下来,就可以调用BezierCurve来绘制贝塞尔曲线了
0, 300]}
endPoint = {[400, 100]}
controlPoints = {[1, 0, 0, 1]}
strokeWidth = {6}
/>
我们必须先知道为什么使用SVG来绘制图标。
React中使用SVG图标一般通过设置path标签的方法转换成SVG组件,这样我们方便在任何地方插入图标