React可视化

我们在web端所理解的可视化大都是线,柱,饼等图表,以及这些基础图表的衍生和组合。在技术层面,常见的技术有SVG,canvas和webgl。

canvas

canvas基于像素,提供2D和3D绘制函数,通过脚本来绘制图形。canvas在web端常见的使用场景如下:

  • 绘制各种图形元素,如多边形和Bezier曲线
  • 图片图像处理
  • 创建复杂的动画
  • 视频处理与渲染

在IE浏览器上,从IE9开始兼容canvas
(我使用canvas实现了一个五子棋,大家有兴趣可以看看canvas和dom版本的五子棋)

SVG

SVG全称是可缩放矢量图形,是一种用来描述二维矢量图形的XML语言(关于SVG可以参考我另一篇博文使用SVG实现圆环loading进度效果)
SVG在web端的使用场景如下:
- 绘制各种图形元素,如多边形和Bezier曲线
- 渲染页面中的图表(icon)
- 制作网站logo
- 绘制线,柱,饼等图表

比较SVG和canvas

在图形元素的渲染上,业界的选型各有不同。如echarts使用canvas,highcharts使用的是SVG。但因为SVG在无线浏览器上支持得并不理想,一些现代图表库选择canvas以获得更好的兼容性。

React中的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组件中。

React中的SVG

使用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图标

我们必须先知道为什么使用SVG来绘制图标。

  1. 我们常用的雪碧图有高清屏幕的兼容问题,对于divicePixelRatio = 1,2,3等不同像素比的屏幕,为了使图标能够在各种屏幕上能够正常显示,一般我们会分开做几套不同比例的图片进行适配,一旦某个图标需要改动,就要修改相应数量的图片,可维护性比较差
  2. iconfont字体图标锯齿问题。使用iconfont时,能够方便设置font-size和color来改变图标的填充颜色和大小,并且能够自动适配各种像素比的屏幕,但是由于iconfont本身是一种字体文件,而浏览器会对文字进行抗锯齿优化,所以当图标的大小小于16px,或者图标比较复杂时,往往会出现图标无法显示清晰的问题。

React中使用SVG图标一般通过设置path标签的方法转换成SVG组件,这样我们方便在任何地方插入图标

你可能感兴趣的:(React)