2012-11-06 10 views
5

Nel codice extjs 4.1.1a seguente è un esempio funzionante di un grafico a linee. Ora ho bisogno di evidenziare una parte di quel grafico su un determinato timestamp min e max.Evidenziare una parte di un grafico a linee extjs4

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

Ho cercato nel forum sencha e non ho trovato nulla in particolare che soddisfi i miei requisiti. Per ora sono riuscito a cambiare il colore dei punti sul grafico a linee con un renderizzatore personalizzato.

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

Ma non ho trovato un modo per cambiare il colore sotto la linea. Qualche suggerimento su questo?

AGGIORNAMENTO - lavorando bene ora

ho implementare una soluzione basata sulla risposta data da 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); 
    } 
}} 

Questo sembra davvero buono e ha l'effetto che speravo e nel caso in cui si ridimensiona il contenitore del nuovo sprite è eliminato dal grafico. Grazie a Colombo di nuovo.

+1

Devi tenere un riferimento alla sprite e distruggerla prima di creare di nuovo. Controlla di nuovo il mio codice. – jorel

risposta

1

Questo è possibile implementare. Ecco come lo farei.

1. Aggiungere un ascoltatore per afterrender evento per series.

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

2. Creare un 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); 
    } 
}, 
+0

La soluzione funziona bene per me.L'unico problema è che nel caso in cui il contenitore viene ridimensionato, lo sprite non viene cancellato dal grafico e rimane nello stesso punto e verrà ridisegnato come un nuovo sprite nella giusta posizione. Conosci un modo per aggirare questo? – everald

+1

Assicurati che il vecchio CompositeSprite sia distrutto prima di crearne uno nuovo. – jorel

+0

Sì, dopo un po 'di tentativi ho notato la differenza tra la mia prima soluzione e la tua risposta. Ora tutto sembra funzionare. grazie – everald

0

Non esiste un metodo "integrato" per questo. Probabilmente stai incontrando delle difficoltà a cercarlo perché "evidenziare" un grafico a linee significa attualmente qualcosa di completamente diverso nell'API ExtJS. Normalmente si riferisce a rendere la linea e marcatori in grassetto quando si passa il mouse su una serie di dati.

Tuttavia la tua idea sembra interessante, potrei aver bisogno di usarla in un progetto che ho in mente.

Non ho il tempo di elaborare il codice esatto in questo momento, ma ciò potrebbe essere fatto creando uno sprite rettangolare e aggiungendolo al grafico surface property.

È possibile farlo anche dopo aver eseguito il rendering del grafico utilizzando il metodo Ext.draw.Surface.add come descritto nel documento here.

Dovrai elaborare la logica per determinare la larghezza e il posizionamento, se ricordo correttamente l'API del grafico, dovresti essere in grado di estrarre le coordinate x (posizione orizzontale) dei singoli record pescando nella proprietà items del Ext.chart.series.Line oggetto all'interno del grafico.

L'altezza del punto culminante dovrebbe essere semplice, basta leggere l'altezza del grafico.

Problemi correlati