【问题标题】:Highlight a part of an extjs4 line chart突出显示 extjs4 折线图的一部分
【发布时间】:2025-12-15 19:00:02
【问题描述】:

在 extjs 4.1.1a 中,下面的代码是折线图的一个工作示例。现在我需要在给定的最小和最大时间戳上突出显示该图表的一部分。

{'xtype' : 'chart',
'store' : 'ChartData',
'height' : '100%',
'width' : '100%',
'legend' : {'position' : top},
'axes': [{
    'title': 'Power',
    'type': 'Numeric',
    'position': 'left',
    'fields': ['power']
},{
    'title': 'Timestamp',
    'type': 'Numeric',
    'position': 'bottom',
    'fields': ['timestamp'],
    'minorTickSteps': 3
}],
'series': [{
    'type': 'line',
    'fill': true,
    'axis' : 'left',
    'xField': 'timestamp',
    'yField': 'power'
}]}

我搜索了 sencha 论坛,并没有找到特别符合我要求的内容。 现在,我设法使用自定义渲染器更改折线图上点的颜色。

'renderer': function(sprite, record, attr, index, store) {
var item = store.getAt(index);
if(item != undefined && (item.get('timestamp') < startdate || item.get('timestamp') > enddate)){
    return Ext.apply(attr, {'fill': '#00cc00', 'stroke-width': 3, 'radius': 4});
}else{
    return Ext.apply(attr, {'fill': '#ff0000', 'stroke-width': 3, 'radius': 4});
}}

但我还没有找到改变线条下方颜色的方法。 有什么建议吗?

更新 - 现在工作正常

我根据科伦坡给出的答案实施了一个解决方案。

doCustomDrawing: function () {: function (p){
var me = this, chart = me.chart;
if(chart.rendered){
    var series = chart.series.items[0];
    if (me.groupChain != null) {
        me.groupChain.destroy();
        me.groupChain = null;
    }
    me.groupChain = Ext.create('Ext.draw.CompositeSprite', {
        surface: chart.surface
    });
    if(series != null && series.items != null){
        var surface = chart.surface;
        var pathV = 'M';
        var first = true;
        // need first and last x cooridnate
        var mX = 0,hX = 0;
        Ext.each(series.items, function(item){
            var storeItem = item.storeItem,
                    pointX = item.point[0],
                    pointY = item.point[1];
            // based on given startdate and enddate start collection path coordinates
            if(!(storeItem.get('timestamp') < startdate || storeItem.get('timestamp') > enddate)){
                if(hX<pointX){
                    hX = pointX;
                }
                if(first){
                    first = false;
                    mX = pointX;
                    pathV+= + pointX + ' ' + pointY;
                }else{
                    pathV+= ' L' + pointX + ' ' + pointY;
                }
            }
        });
        var sprite = Ext.create('Ext.draw.Sprite', {
            type: 'path',
            fill: '#f00',
            surface: surface,
            // to draw a sprite with the area below the line we need the y coordinate of the x axe which is in my case items[1]
            path : pathV + ' L'+ hX + ' ' + chart.axes.items[1].y + ' L'+ mX + ' ' + chart.axes.items[1].y + 'z'
        });
        me.groupChain.add(sprite);
        me.groupChain.show(true);
    }
}}

这看起来非常好,并且具有我希望的效果,如果您调整容器的大小,新的精灵会从图表中清除。再次感谢科伦坡。

【问题讨论】:

  • 您必须保留对精灵的引用并在再次创建之前销毁它。再次检查我的代码。

标签: extjs charts extjs4


【解决方案1】:

这是可以实现的。以下是我的做法。

1.为seriesafterrender 事件添加监听器。

listeners: {
                afterrender: function (p) {
                    this.doCustomDrawing();
                },
                scope: me
}

2。创建一个 CompositeSprite

doCustomDrawing: function () {
    var me = this, chart = me.chart;

    if (chart.rendered) {
        var series = chart.series.items[0];
        if (me.groupChain != null) {
            me.groupChain.destroy();
            me.groupChain = null;
        }

        me.groupChain = Ext.create('Ext.draw.CompositeSprite', {
            surface: chart.surface
        });

        // Draw hilight here
        Ext.each(series.items, function (item) {
            var storeItem = item.storeItem,
                pointX = item.point[0], 
                pointY = item.point[1];

            //TODO: Create your new line sprite using pointX and pointY
            // and add it to CompositeSprite me.groupChain  


        });

        me.groupChain.show(true);
    }
},

【讨论】:

  • 该解决方案对我来说很好。唯一的问题是,如果容器被调整大小,精灵不会从图表中清除并保持在同一个位置,并将在正确的位置重新绘制为新的精灵。你知道规避这种情况的方法吗?
  • 确保在创建新的 CompositeSprite 之前销毁旧的 CompositeSprite。
  • 是的,经过一些尝试和错误,我注意到我的第一个解决方案和您的答案之间存在差异。现在一切似乎都奏效了。谢谢
【解决方案2】:

没有“内置”方法可以解决这个问题。您可能在寻找它时遇到了一些困难,因为“突出显示”折线图目前在 ExtJS API 中意味着完全不同的东西。它通常是指将鼠标悬停在数据系列上时使线条和标记变为粗体。

不管你的想法听起来很有趣,我可能需要在我即将推出的项目中使用它。

我现在没有时间计算出确切的代码,但这可以通过创建一个矩形sprite 并将其添加到图表的surface property 来完成。

即使在使用文档中的here 描述的Ext.draw.Surface.add 方法全部呈现图表之后,您也可以这样做。

你必须想出确定宽度和定位的逻辑,如果我没记错图表 API,你应该能够通过在 items 属性中查找来提取单个记录的 x 坐标(水平位置)图表内的Ext.chart.series.Line 对象。

高亮的高度应该很容易 - 只需阅读图表的高度即可。

【讨论】: