echarts源码分析

各个Component的渲染过程

在echarts中,Component(组件)是除Series(图表)外的其他配置项,有datazoom(区域缩放)、visualMap(视图映射)、tooltip(提示框组件)、toolbox(工具栏)、brush(区域选择组件)、timeline(时间轴)、graphic(原生图形组件)、dataset(数据集)、marker(包括markPoint(图标标注)、markLine(图表标线)、markArea(图表标域)等。用户通过传递option对象来设置相应的Component。

这篇文章中将介绍tooltip、dataZoom、visualMap这三项常用的组件。

区域缩放 DataZoom

dataZoom分为inside和slider两种类型。

DataZoomModel 通过extendComponentModel扩展自Component Model,重写了defaultOption属性以及init、mergeOption等方法。

DataZoomView 通过extend扩展自Component View,重写了render方法并定义了getTargetCoordInfo方法。

Slider

SliderZoomModel 通过extend扩展自DataZoomModel,重写了defaultOption属性

SliderZoomView 通过extend扩展自DataZoomView,重写了render、remove、dispose等方法,主要实现代码如下:

render: function (dataZoomModel, ecModel, api, payload) {
    // 调用DataZoomView中的render方法
    SliderZoomView.superApply(this, 'render', arguments);
    if (!payload || payload.type !== 'dataZoom' || payload.from !== this.uid) {
        // 绘制
        this._buildView();
    // 更新
    this._updateView();
_buildView: function () {
    var thisGroup = this.group;
    thisGroup.removeAll();
    this._resetLocation();
    this._resetInterval();
    var barGroup = this._displayables.barGroup = new graphic.Group();
    // 绘制背景,通过graphic.Rect绘制背景,包括可视层以及Click panel
    this._renderBackground();
    // 绘制handle,通过graphic.Rect绘制选择的区域,并绑定拖拽相关以及mouseover、mouseout等事件处理器
    // 通过graphic.Rect绘制Frame border
    // 通过graphic.createIcon创建handler 图标,并绑定拖拽相关以及mouseover、mouseout等事件处理器
    // 通过graphic.Text绘制handle中的label数据
    this._renderHandle();
    // 通过graphic.Polyline及graphic.Polygon绘制出datazoom下的数据缩略图
    this._renderDataShadow();
    thisGroup.add(barGroup);
    this._positionGroup();

Inside

InsideZoomModel通过extend扩展自DataZoomModel,重写了defaultOption属性。

InsideZoomView通过extend扩展自DataZoomView,重写了init、render、dispose等方法,主要实现代码如下:

render: function (dataZoomModel, ecModel, api, payload) {
    // 调用DataZoomView中的render方法
    InsideZoomView.superApply(this, 'render', arguments);
    this._range = dataZoomModel.getPercentRange();
    // Reset controllers.
    zrUtil.each(this.getTargetCoordInfo(), function (coordInfoList, coordSysName) {
        zrUtil.each(coordInfoList, function (coordInfo) {
            var coordModel = coordInfo.model;
            var getRange = {};
            // 绑定pan、zoom、scrollMove事件处理器,roamHandlers中定义了相关类型的事件处理函数
            zrUtil.each(['pan', 'zoom', 'scrollMove'], function (eventName) {
                getRange[eventName] = bind(roamHandlers[eventName], this, coordInfo, coordSysName);
            }, this);
        }, this);
    }, this);

视图映射 VisualMap

VisualMap分为continuous连续型及piecewise分段型两个类型。

VisualMapAction中注册了selectDataRange action

VisualMapModel通过extendComponentModel方法扩展自Component Model,重写了defaultOption属性以及init、optionUpdated等方法,并定义了resetVisual、formatValueText等方法。

VisualMapView通过extendComponentView方法扩展自Component View,重写了init、render等方法,定义了renderBackground方法,主要代码为:

render: function (visualMapModel, ecModel, api, payload) {
    // 调用子类doRender方法
    this.doRender.apply(this, arguments);
renderBackground: function (group) {
    var visualMapModel = this.visualMapModel;
    var padding = formatUtil.normalizeCssArray(visualMapModel.get('padding') || 0);
    var rect = group.getBoundingRect();
    // 通过graphic.Rect渲染visualMap背景
    group.add(new graphic.Rect({
        z2: -1, // Lay background rect on the lowest layer.
        silent: true,
        shape: {
            x: rect.x - padding[3],
            y: rect.y - padding[0],
            width: rect.width + padding[3] + padding[1],
            height: rect.height + padding[0] + padding[2]
        style: {
            fill: visualMapModel.get('backgroundColor'),
            stroke: visualMapModel.get('borderColor'),
            lineWidth: visualMapModel.get('borderWidth')

Continuous

ContinuousView通过extend方法扩展自VisualMapView,重写了init方法并定义了doRender方法,主要代码如下:

doRender: function (visualMapModel, ecModel, api, payload) {
    if (!payload || payload.type !== 'selectDataRange' || payload.from !== this.uid) {
        this._buildView();
_buildView: function () {
    this.group.removeAll();
    var visualMapModel = this.visualMapModel;
    var thisGroup = this.group;
    this._orient = visualMapModel.get('orient');
    this._useHandle = visualMapModel.get('calculable');
    this._resetInterval();
    // 绘制visualMap映射组件
    // 1)通过graphic.Polygon绘制inRange及outOfRange形状,并为inRange形状绑定drag相关事件处理器
    // 2)若userHandle为true,则通过graphic.Polygon绘制handler,graphic.Text绘制handler label
    //    并为handler绑定drag相关时间处理器
    // 3)通过graphic.Polygon绘制指示器,graphic.Text绘制指示器 label
    this._renderBar(thisGroup);
    var dataRangeText = visualMapModel.get('text');
    // 通过graphic.Text渲染visualMap首与尾处的label
    this._renderEndsText(thisGroup, dataRangeText, 0);
    this._renderEndsText(thisGroup, dataRangeText, 1);
    this._updateView(true);
    // 调用VisualMapView中的renderBackground方法
    this.renderBackground(thisGroup);
    // 通过graphic.LinearGradient创建线性渐变
    this._updateView();
    // 绑定mouseover及mouseout相关的事件处理器
    // mouseover:showIndicator
    // mouseout:hideIndicator
    this._enableHoverLinkToSeries();
    this._enableHoverLinkFromSeries();
    this.positionGroup(thisGroup);

Piecewise

PiecewiseView通过extend方法扩展自VisualMapView,定义了doRender方法,主要代码如下:

doRender: function () {
    // 通过graphic.Text绘制
    endsText && this._renderEndsText(
        thisGroup, endsText[0], itemSize, showLabel, itemAlign
    // viewPieceList数据处理的实现在PiecewiseModel中resetMethods
    // 遍历viewPieceList调用renderItem进行片段visual的绘制
    zrUtil.each(viewData.viewPieceList, renderItem, this);
    endsText && this._renderEndsText(
        thisGroup, endsText[1], itemSize, showLabel, itemAlign
    layout.box(
        visualMapModel.get('orient'), thisGroup, visualMapModel.get('itemGap')
    // 调用VisualMapView中的renderBackground方法
    this.renderBackground(thisGroup);
    this.positionGroup(thisGroup);
    function renderItem(item) {
        var piece = item.piece;
        var itemGroup = new graphic.Group();
        // 绑定onclick时的事件处理器
        itemGroup.onclick = zrUtil.bind(this._onItemClick, this, piece);
        // 绑定mouseover、mouseout相关的事件处理器
        this._enableHoverLink(itemGroup, item.indexInModelPieceList);
        var representValue = visualMapModel.getRepresentValue(piece);
        // 通过createSymbol方法创建symbol
        this._createItemSymbol(
            itemGroup, representValue, [0, 0, itemSize[0], itemSize[1]]
        if (showLabel) {
            var visualState = this.visualMapModel.getValueState(representValue);
            // 渲染文本
            itemGroup.add(new graphic.Text({
                style: {
                    x: itemAlign === 'right' ? -textGap : itemSize[0] + textGap,
                    y: itemSize[1] / 2,
                    text: piece.text,
                    textVerticalAlign: 'middle',
                    textAlign: itemAlign,
                    textFont: textFont,
                    textFill: textFill,
                    opacity: visualState === 'outOfRange' ? 0.5 : 1
        thisGroup.add(itemGroup);

提示框 Tooltip

Tooltip.js

Tooltip.js中注册了showTip及hideTip action,trigger处理器调用TooltipView中定义的manuallyShowTip及manuallyHideTip方法。代码如下:

echarts.registerAction(
        type: 'showTip',
        event: 'showTip',
        update: 'tooltip:manuallyShowTip'
    function () {}
echarts.registerAction(
        type: 'hideTip',
        event: 'hideTip',
        update: 'tooltip:manuallyHideTip'
    function () {}

TooltipModel

TooltipModel通过extendComponentModel扩展自Component Model,重写了defaultOption属性。

TooltipView

TooltipView通过extendComponentView扩展自Component View,重写了init、render等方法,并定义了manuallyShowTip、manuallyHideTip等方法。

ECHARTS学习dataZoom组件dataZoomdataZoomInside功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 dataZoom dataZoom 组件用于区域缩放,从而能自由关注细节的数据信息,或者概览数据整 在图表中加入交互组件除了图表外 ECharts 中,提供了很多交互组件。例如:图例组件 legend、标题组件 title、视觉映射组件 visualMap、数据区域缩放组件 dataZoom、时间线组件 timeline下面以 数据区域缩放组件 dataZoom 为例,介绍如何加入这种组件。数据区域缩放组件(dataZoom)介绍『概览数据整体,按需关注数据细节』是数据可视化的基本交互需求。dat zoomOnMouseWheel 关闭滚轮缩放, 关闭后滚轮滚到最后不会有回弹抖动。这里的startValue和endValue代表初始只显示七个,七组柱子。实现效果:柱形图展示水平滚动条,并且鼠标滚动支持让滚动条平移。minValueSpan代表放大到最少到显示几个。maxValueSpan代表缩小到最多显示几个。既要内置型的能在图中滚动,又要滚动条的样式。echarts文档里,图形的滚动条分两种。而我们要实现的就是综合了这两种。开启后滚轮往下滚数据往后移动。再添加到option里即可。 1.项目需求:当数据量过大时,页面展示起来会很拥挤,此时我们需要一个滚轴,可以让用户进行鼠标滚轮滑动的展示 2.此时我们用到了Echarts中的dataZoom属性,这个属性主要用于区域缩放的功能 3.上代码: var option = { dataZoom: [ type: "slider",//slider表示有滑动块的,inside表示内置的 dataZoom的类型有两种,一个是inside,一个是slider,这里用的是inside,inside是可以实现用鼠标去直接缩放柱状图里面的数据的,slider不可以用鼠标去缩放柱状图的内容。由于数据量很多,一小块区域展不开那么多数据,于是想要做一个可以选择范围的柱状图。我其实就是想调整一下滚动条的位置,这个是我的效果图。因为用的slider,所以只能手动拖动两边实现。现在是一个很灵活的图啦,可以用鼠标拖动,伸缩~这个滚动条的位置可以这样去设置。如果用inside,这样写是不出滚动条的。 遇到以上两个错误的,可以直接复制下面三行:通过标签引入地图api地址、echarts地址、扩展插件地址,这里的ak是你在地图服务中心注册的-- 百度 -->v=3.0&ak=?-- 扩展地图插件 --> chart.on('datazoom',function(params){ console.log(params);//里面存有代表滑动条的起始的数字 let xAxis=chart.getModel().option.xAxis[0];//获取axis console.log(xAxis.data);//axis的标号数据 console.log(xAxis.rangeStart);//滑动条左端对应在xAxis.data的索引 console.log(xAxis.rangeE var myChart = echarts.init(document.getElementById("mapHourContainer")); myChart.dispatchAction({ type: 'dataZoom', // 可选,dataZoom 组件的 index,多个 dataZoom 组件时有用,默认为 0 dataZoomIndex: number,//一般不需要写 // 开始位置的百分比,0 - 100