我的学习笔记12.15

2021SC@SDUSC

echarts源码分析

 Series渲染过程

在ECharts中用 series表示各类图表。有line(折线图)、bar(柱状图)、pie(饼图)等Series。用户通过传递option对象来设置相应的Series。

在这部分中echarts采用了Model以及View的架构来管理Series:

Model层:model/Series.js 管理Series数据。
View:view/Charts.js 负责渲染Chart视图。


Line 折线图

LineSeries

LineSeries通过extend方法扩展自Series Model,重写了defaultOption属性以及getInitialData方法。

LineView

LineView通过extend方法扩展自Chart View,重写了init、render、highlight及downplay等方法,主要代码如下:

init: function () {
    var lineGroup = new graphic.Group();
    // 使用SymbolDraw绘制Symbol
    var symbolDraw = new SymbolDraw();
    this.group.add(symbolDraw.group);

    this._symbolDraw = symbolDraw;
    this._lineGroup = lineGroup;
},
render: function (seriesModel, ecModel, api) {
    ...
    if (
        !(polyline && prevCoordSys.type === coordSys.type && step === this._step)
    ) {
        // 折线图
        // symbolDraw绘制symbol
        showSymbol && symbolDraw.updateData(data, {
            isIgnore: isIgnoreFunc,
            // createClipShape创建方法分为极坐标createPolarClipShape以及直角坐标createGridClipShape
            // createPolarClipShape:通过graphic.Sector创建Clip区域
            // createGridClipShape:通过graphic.Rect创建Clip区域
            clipShape: createClipShape(coordSys, false, true, seriesModel)
        });
        ...
        // 通过zrender Polyline绘制折线图
        polyline = this._newPolyline(points, coordSys, hasAnimation);
        if (isAreaChart) {
            // 通过zrender Polygon绘制折线区域
            polygon = this._newPolygon(
                points, stackedOnPoints,
                coordSys, hasAnimation
            );
        }
        lineGroup.setClipPath(createClipShape(coordSys, true, false, seriesModel));
    }
    else {
        if (isAreaChart && !polygon) {
            polygon = this._newPolygon(
                points, stackedOnPoints,
                coordSys, hasAnimation
            );
        }
        else if (polygon && !isAreaChart) {
            // If areaStyle is removed
            lineGroup.remove(polygon);
            polygon = this._polygon = null;
        }

        // Update clipPath
        lineGroup.setClipPath(createClipShape(coordSys, false, false, seriesModel));

        // Always update, or it is wrong in the case turning on legend
        // because points are not changed
        showSymbol && symbolDraw.updateData(data, {
            isIgnore: isIgnoreFunc,
            clipShape: createClipShape(coordSys, false, true, seriesModel)
        });
        ...
    }
    ...
}


Bar 柱状图


BaseBarSeries

BaseBarSeries通过extend方法扩展自Series Model,重写了defaultOption属性,以及getMarkerPosition和getInitialData方法。

BarSeries

BarSeries通过extend方法扩展自BaseBarSeries,重写了getProgressive等方法。

BarView

BarView通过extendChartView方法扩展自Chart View,重写了render等方法,主要代码如下:

render: function (seriesModel, ecModel, api) {
    // 更新绘制模式
    this._updateDrawMode(seriesModel);
    var coordinateSystemType = seriesModel.get('coordinateSystem');
    // 支持笛卡尔坐标系以及极坐标系
    if (coordinateSystemType === 'cartesian2d'
        || coordinateSystemType === 'polar'
       ) {
        // 绘制
        this._isLargeDraw
            ? this._renderLarge(seriesModel, ecModel, api)
        : this._renderNormal(seriesModel, ecModel, api);
    }
    else if (__DEV__) {
        console.warn('Only cartesian2d and polar supported for bar.');
    }
    return this.group;
}
_renderNormal: function (seriesModel, ecModel, api) {
    ...
    data.diff(oldData)
        .add(function (dataIndex) {
            if (!data.hasValue(dataIndex)) {
                return;
            }
            var itemModel = data.getItemModel(dataIndex);
        	// 返回layout信息
            var layout = getLayout[coord.type](data, dataIndex, itemModel);
        	// 创建元素
        	// 通过graphic.Rect(笛卡尔坐标系)/ graphic.Sector(极坐标系)绘制柱形图
            var el = elementCreator[coord.type](
                data, dataIndex, itemModel, layout, isHorizontalOrRadial, animationModel
            );
            data.setItemGraphicEl(dataIndex, el);
            group.add(el);
            updateStyle(
                el, data, dataIndex, itemModel, layout,
                seriesModel, isHorizontalOrRadial, coord.type === 'polar'
            );
    	})
        .update(function (newIndex, oldIndex) {
        	// 更新元素
            var el = oldData.getItemGraphicEl(oldIndex);
        	...
            if (el) {
                graphic.updateProps(el, {shape: layout}, animationModel, newIndex);
            }
            else {
                el = elementCreator[coord.type](
                    data, newIndex, itemModel, layout, isHorizontalOrRadial, animationModel, true
                );
            }
        	...
    	})
        .remove(function (dataIndex) {
            var el = oldData.getItemGraphicEl(dataIndex);
            if (coord.type === 'cartesian2d') {
                el && removeRect(dataIndex, animationModel, el);
            }
            else {
                el && removeSector(dataIndex, animationModel, el);
            }
    	})
        .execute();

    this._data = data;
}


Pie 饼图


Pie.js

pie.js中注册了pieToggleSelect、pieSelect、pieUnSelect等Action

PieSeries

PieSeries通过extendSeriesModel方法扩展自Series Model,重写了defaultOption属性,以及init、mergeOption、getInitialData等方法。

PieView

PieView通过extend方法扩展自Chart View,重写了init、render等方法,主要实现如下:

render: function (seriesModel, ecModel, api, payload) {
    ...
    var onSectorClick = zrUtil.curry(
        updateDataSelected, this.uid, seriesModel, hasAnimation, api
    );

    var selectedMode = seriesModel.get('selectedMode');

    data.diff(oldData)
        .add(function (idx) {
        	// 添加
        	// PiePiece通过graphic.Sector、graphic.Polyline及graphic.Text绘制饼图的每一块扇形
        	// 并绑定了emphasis、mouseover、mouseout等处理器
            var piePiece = new PiePiece(data, idx);
            // Default expansion animation
            if (isFirstRender && animationType !== 'scale') {
                piePiece.eachChild(function (child) {
                    child.stopAnimation(true);
                });
            }
        	// 绑定点击事件处理器
            selectedMode && piePiece.on('click', onSectorClick);

            data.setItemGraphicEl(idx, piePiece);

            group.add(piePiece);
    	})
        .update(function (newIdx, oldIdx) {
        	// 更新
            var piePiece = oldData.getItemGraphicEl(oldIdx);

            piePiece.updateData(data, newIdx);

            piePiece.off('click');
            selectedMode && piePiece.on('click', onSectorClick);
            group.add(piePiece);
            data.setItemGraphicEl(newIdx, piePiece);
        })
        .remove(function (idx) {
            var piePiece = oldData.getItemGraphicEl(idx);
            group.remove(piePiece);
        })
        .execute();
    ...
    this._data = data;
}

你可能感兴趣的:(javascript)