echarts自定义tooltip绘制轨迹

之前用过一阵子echarts做APP上的趋势图,修改过源码实现一些自定义效果。以及设置一些echarts-m.js的隐藏setting,在此Mark一下,防止忘记。

1. 自定义tooltip绘制轨迹。

    echarts提供的tooltip,在绘制直线时,只提供了实线,虚线,阴影线。如果要在直线的基础上,增加一些功能,比如线要超出图的边界(如果用formatter事件注入,会有延迟效果),就需要修改一下源码,指导内部的绘制路径,因为echarts本身就是用canvas画tootip的。废话不多说。

    A. 新增Config属性。

在'echarts/component/tooltip'模块下,ecConfig.tooltip的定义中,扩展下axisPointer,新增selfDefine属性,默认为String,不启用。传入function可以覆盖使用。

	axisPointer: {
            type: 'line',
            lineStyle: {
                color: '#48b',
                width: 2,
                type: 'solid',
                selfDefine : 'self defined function to help draw tip panel'   //modify, new add
            },
            crossStyle: {
                color: '#1e90ff',
                width: 1,
                type: 'dashed',
                selfDefine : 'self defined function to help draw tip panel'   //modify, new add
            },
            shadowStyle: {
                color: 'rgba(150,150,150,0.3)',
                width: 'auto',
                type: 'default',
                selfDefine : 'self defined function to help draw tip panel'   //modify, new add
            }
        },
  B. 在Tooltip.prototype = {}的定义中,修改_styleAxisPointer方法,注意//new add 注解部分为selfDefine方法的注入。

_styleAxisPointer: function (seriesArray, xStart, yStart, xEnd, yEnd, gap, x, y) {
            if (seriesArray.length > 0) {
                var queryTarget;
                var curType;
                var axisPointer = this.option.tooltip.axisPointer;
                var pointType = axisPointer.type;
                var appendStyle = this.option.tooltip.appendStyle; 
                var style = {
                    line: {},
                    cross: {},
                    shadow: {}
                };
                for (var pType in style) {
                    style[pType].color = axisPointer[pType + 'Style'].color;
                    style[pType].width = axisPointer[pType + 'Style'].width;
                    style[pType].type = axisPointer[pType + 'Style'].type;
                    style[pType].selfDefine = axisPointer[pType + 'Style'].selfDefine;   // new add
                }
                for (var i = 0, l = seriesArray.length; i < l; i++) {
                    queryTarget = seriesArray[i];
                    curType = this.query(queryTarget, 'tooltip.axisPointer.type');
                    pointType = curType || pointType;
                    if (curType) {
                        style[curType].color = this.query(queryTarget, 'tooltip.axisPointer.' + curType + 'Style.color') || style[curType].color;
                        style[curType].width = this.query(queryTarget, 'tooltip.axisPointer.' + curType + 'Style.width') || style[curType].width;
                        style[curType].type = this.query(queryTarget, 'tooltip.axisPointer.' + curType + 'Style.type') || style[curType].type;
                        style[curType].selfDefine = style[curType].selfDefine;  //new add
                    }
                }
                if (pointType === 'line') {
                    var lineWidth = style.line.width;
                    var isVertical = xStart == xEnd;
                    this._axisLineShape.style = {
                        xStart: isVertical ? this.subPixelOptimize(xStart, lineWidth) : xStart,
                        yStart: isVertical ? yStart : this.subPixelOptimize(yStart, lineWidth),
                        xEnd: isVertical ? this.subPixelOptimize(xEnd, lineWidth) : xEnd,
                        yEnd: isVertical ? yEnd : this.subPixelOptimize(yEnd, lineWidth),
                        strokeColor: style.line.color,
                        lineWidth: lineWidth,
                        lineType: style.line.type,
                        selfDefine : style.line.selfDefine   //new add 
                    };
                    this._axisLineShape.invisible = false;
                    this.zr.modShape(this._axisLineShape.id);
                } else if (pointType === 'cross') {
                    var crossWidth = style.cross.width;
                    this._axisCrossShape.style = {
                        brushType: 'stroke',
                        rect: this.component.grid.getArea(),
                        x: this.subPixelOptimize(x, crossWidth),
                        y: this.subPixelOptimize(y, crossWidth),
                        text: ('( ' + this.component.xAxis.getAxis(0).getValueFromCoord(x) + ' , ' + this.component.yAxis.getAxis(0).getValueFromCoord(y) + ' )').replace('  , ', ' ').replace(' ,  ', ' '),
                        textPosition: 'specific',
                        strokeColor: style.cross.color,
                        lineWidth: crossWidth,
                        lineType: style.cross.type
                    };
                    if (this.component.grid.getXend() - x > 100) {
                        this._axisCrossShape.style.textAlign = 'left';
                        this._axisCrossShape.style.textX = x + 10;
                    } else {
                        this._axisCrossShape.style.textAlign = 'right';
                        this._axisCrossShape.style.textX = x - 10;
                    }
                    if (y - this.component.grid.getY() > 50) {
                        this._axisCrossShape.style.textBaseline = 'bottom';
                        this._axisCrossShape.style.textY = y - 10;
                    } else {
                        this._axisCrossShape.style.textBaseline = 'top';
                        this._axisCrossShape.style.textY = y + 10;
                    }
                    this._axisCrossShape.invisible = false;
                    this.zr.modShape(this._axisCrossShape.id);
                } else if (pointType === 'shadow') {
                    if (style.shadow.width == null || style.shadow.width === 'auto' || isNaN(style.shadow.width)) {
                        style.shadow.width = gap;
                    }
                    if (xStart === xEnd) {
                        if (Math.abs(this.component.grid.getX() - xStart) < 2) {
                            style.shadow.width /= 2;
                            xStart = xEnd = xEnd + style.shadow.width / 2;
                        } else if (Math.abs(this.component.grid.getXend() - xStart) < 2) {
                            style.shadow.width /= 2;
                            xStart = xEnd = xEnd - style.shadow.width / 2;
                        }
                    } else if (yStart === yEnd) {
                        if (Math.abs(this.component.grid.getY() - yStart) < 2) {
                            style.shadow.width /= 2;
                            yStart = yEnd = yEnd + style.shadow.width / 2;
                        } else if (Math.abs(this.component.grid.getYend() - yStart) < 2) {
                            style.shadow.width /= 2;
                            yStart = yEnd = yEnd - style.shadow.width / 2;
                        }
                    }
                    this._axisShadowShape.style = {
                        xStart: xStart,
                        yStart: yStart,
                        xEnd: xEnd,
                        yEnd: yEnd,
                        strokeColor: style.shadow.color,
                        lineWidth: style.shadow.width
                    };
                    this._axisShadowShape.invisible = false;
                    this.zr.modShape(this._axisShadowShape.id);
                }
               
                this.zr.refreshNextFrame();
                if(appendStyle && (typeof appendStyle === 'function')){  //new add
                	appendStyle.call(this, x, y);
                }
            }
        },
   C.  修改模块'zrender/shape/Line', Line.prototype = {} 的定义处,指导buildPath绘制。如果有传入selfDefine函数,使用selfDefine的画图路径,通过这种方式,可以绘制各种样式,不一定要按照echarts提供的几种tooltip.

Line.prototype = {
        type: 'line',
        buildPath: function (ctx, style) {
        	if(style.selfDefine && (typeof style.selfDefine === 'function')){
//      		console.log(style.xStart+" "+style.yStart+" "+style.xEnd+" "+style.yEnd);
        		var selfDefine = style.selfDefine;
        		selfDefine.call(this,ctx,style.xStart,style.yStart,style.xEnd,style.yEnd);
                return;
        	}else if (!style.lineType || style.lineType == 'solid') {
//          	console.log('solid line');
                ctx.moveTo(style.xStart, style.yStart);
                ctx.lineTo(style.xEnd, style.yEnd);
            } else if (style.lineType == 'dashed' || style.lineType == 'dotted') {
//          	console.log('dash line');
                var dashLength = (style.lineWidth || 1) * (style.lineType == 'dashed' ? 5 : 1);
                dashedLineTo(ctx, style.xStart, style.yStart, style.xEnd, style.yEnd, dashLength);
            }
        },
        getRect: function (style) {
            if (style.__rect) {
                return style.__rect;
            }
            var lineWidth = style.lineWidth || 1;
            style.__rect = {
                x: Math.min(style.xStart, style.xEnd) - lineWidth,
                y: Math.min(style.yStart, style.yEnd) - lineWidth,
                width: Math.abs(style.xStart - style.xEnd) + lineWidth,
                height: Math.abs(style.yStart - style.yEnd) + lineWidth
            };
            return style.__rect;
        }
    };
  D. 使用。

   修改完成后,使用配置如下。通过设置yStart-26后,可以使tooltip线超出echarts的网格区域。

tooltip: {
	showDelay:0,
	transitionDuration:0,
	backgroundColor: "#a6afb6",
	borderColor: "yellow",
	borderWidth: 2,
	padding: 0,
	showContent: false,
	trigger: 'axis', //item,axis
	position: function() {
		return [0, 0];
	},
	formatter: function(params) {	
	}, 
	axisPointer: {
		type: 'line',
		lineStyle: {
			width: 2,
			color :"#a6afb6",
			selfDefine: function(ctx,xStart,yStart,xEnd,yEnd){
				ctx.moveTo(xStart, yStart-26);
				ctx.lineTo(xEnd, yEnd);
			}
		}			
	}
},
2. echarts-m.

    echarts提供了一个m版本,删除了很多PC事件,适用于APP, 但是API和PC版有一些不一致,尤其是Y轴坐标值默认在右侧,太蛋疼。通过查看源代码,找到了这些默认设置。记录如下:

    1. Y轴坐标值水平位置

     yAxis > axisLabel > margin ,设置为35,可以调整。

yAxis: [{
	type: 'value',
	lineStyle: {
		color: '#a6afb6',
		width: 1,
		type: 'solid'
	},
	axisLine: {
		lineStyle: {
		  color: '#a6afb6',
		  width: 1,
		  type: 'solid'
		}   
   },
   axisLabel: {
		textStyle: {
		   color: '#a6afb6'
		},
		margin: 35,  //modify for ehcarts-m
		align: 'right',
		formatter: function(value){
			if(value >= 10000000){
				value = value/1000000;
				
				value = value+"M";
			}else if(value >= 10000){
				value = value/1000;
				value = value+"K";
			}else{
				value = value+"";
			}
			for(var i = value.length ; i < 5;i++){
				value = " "+value;
			}
			return value;
		}
	}
}],
  B. max3显示重复趋势线段。

设置animation:false

最后,有问题,欢迎交流。








你可能感兴趣的:(javascript)