Highlight a part of an extjs4 line chart

匿名 (未验证) 提交于 2019-12-03 08:46:08

问题:

In the extjs 4.1.1a code below is a working example of a line chart. Now I need to highlight a part of that chart on a given min and max timestamp.

{'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' }]}

I've searched the sencha forum and found nothing in particular that meets my requirements. For now I managed to change the color of the points on the line chart with a custom renderer.

'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}); }}

But I have not found a way to change the color below the line. Any suggestions on that?

UPDATE - Working fine now

I implement a solution based on the answer given by Colombo.

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);     } }}

This looks really good and has the effect I was hoping for and in case you resize the container the new sprite is cleared from the chart. Thx to Colombo again.

回答1:

This is possible to implement. Here is how I would do it.

1. Add a listener for afterrender event for series.

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

2. Create a 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);     } },


回答2:

There is no "built-in" way to go about this. You are probably running into some difficulties looking for it because "highlighting" a line chart currently means something totally different in the ExtJS API. It normally refers to making the line and markers bold when you hover the mouse over a data series.

However your idea sounds interesting, I might need use this in a project I have coming up.

I don't have the time to work out the exact code right now but this could be done by creating a rectangular sprite and adding it to the chart's surface property.

You can do that even after the chart has been all rendered using the Ext.draw.Surface.add method as described here in the docs.

You will have to come up with logic for determining width and positioning, if I remember the chart API properly, you should be able to extract x coordinates (horizontal location) of individual records by fishing around in the items property of the Ext.chart.series.Line object inside the chart.

The height of the highlight should be easy though - just read the height of the chart.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!