2011-04-28 11 views
6

EXTJS 4 - Próbuję dostosować funkcję renderera dla "serii" w StackedBarChart. Chcę warunkowo pokolorować paski.ExtJS - Skumulowana bargraficzna barwienie warunkowe

renderer: function(sprite, record, curAttr, index, store) { 
         return Ext.apply(curAttr, { 
           fill: color 
         }); 
         return curAttr; 
}, 

Moje pytanie brzmi: jak sprawdzić, który element jest aktualnie renderowany. Chcę nadać biały kolor pierwszemu elementowi każdego rekordu w moim magazynie danych/serii.

Dziękuję.

+0

pan rozwiązać ten problem? podzieliłbyś się, jeśli tak? ty – Armance

Odpowiedz

2

Znalazłem sposób na wykrycie, który element jest aktualnie renderowany. Po pierwsze, będziesz potrzebować następującego nadpisania, które rozwiązuje kilka problemów z renderer parameters. Nie powinno to wpływać na normalne wykresy słupkowe, ale ich nie testowałem.

Ext.override(Ext.chart.series.Bar,{ 
    drawSeries: function() { 
     var me = this, 
      chart = me.chart, 
      store = chart.getChartStore(), 
      surface = chart.surface, 
      animate = chart.animate, 
      stacked = me.stacked, 
      column = me.column, 
      enableShadows = chart.shadow, 
      shadowGroups = me.shadowGroups, 
      shadowGroupsLn = shadowGroups.length, 
      group = me.group, 
      seriesStyle = me.seriesStyle, 
      items, ln, i, j, baseAttrs, sprite, rendererAttributes, shadowIndex, shadowGroup, 
      bounds, endSeriesStyle, barAttr, attrs, anim; 

     // ---- start edit ---- 
     var currentCol, currentStoreIndex; 
     // ---- end edit ---- 


     if (!store || !store.getCount()) { 
      return; 
     } 

     //fill colors are taken from the colors array. 
     delete seriesStyle.fill; 
     endSeriesStyle = Ext.apply(seriesStyle, this.style); 
     me.unHighlightItem(); 
     me.cleanHighlights(); 

     me.getPaths(); 
     bounds = me.bounds; 
     items = me.items; 

     baseAttrs = column ? { 
      y: bounds.zero, 
      height: 0 
     } : { 
      x: bounds.zero, 
      width: 0 
     }; 
     ln = items.length; 
     // Create new or reuse sprites and animate/display 
     for (i = 0; i < ln; i++) { 
      sprite = group.getAt(i); 
      barAttr = items[i].attr; 

      if (enableShadows) { 
       items[i].shadows = me.renderShadows(i, barAttr, baseAttrs, bounds); 
      } 

      // ---- start edit ---- 
      if (stacked && items[i].storeItem.index != currentStoreIndex) { 
       //console.log("i: %o, barsLen: %o, j: %o, items[i]: %o",i,bounds.barsLen,i/bounds.barsLen,items[i]); 
       currentStoreIndex = items[i].storeItem.index; 
       currentCol = 0; 
      } 
      else { 
       ++currentCol; 
      } 
      // ---- end edit ---- 

      // Create a new sprite if needed (no height) 
      if (!sprite) { 
       attrs = Ext.apply({}, baseAttrs, barAttr); 
       attrs = Ext.apply(attrs, endSeriesStyle || {}); 
       sprite = surface.add(Ext.apply({}, { 
        type: 'rect', 
        group: group 
       }, attrs)); 
      } 
      if (animate) { 
       // ---- start edit ---- 
       rendererAttributes = me.renderer(sprite, items[i].storeItem, barAttr, (stacked? currentStoreIndex : i), store, (stacked? currentCol : undefined)); 
       // ---- end edit ---- 
       sprite._to = rendererAttributes; 
       anim = me.onAnimate(sprite, { to: Ext.apply(rendererAttributes, endSeriesStyle) }); 
       if (enableShadows && stacked && (i % bounds.barsLen === 0)) { 
        j = i/bounds.barsLen; 
        for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) { 
         anim.on('afteranimate', function() { 
          this.show(true); 
         }, shadowGroups[shadowIndex].getAt(j)); 
        } 
       } 
      } 
      else { 
       // ---- start edit ---- 
       rendererAttributes = me.renderer(sprite, items[i].storeItem, Ext.apply(barAttr, { hidden: false }), (stacked? currentStoreIndex : i), store, (stacked? currentCol : undefined)); 
       // ---- end edit ---- 
       sprite.setAttributes(Ext.apply(rendererAttributes, endSeriesStyle), true); 
      } 
      items[i].sprite = sprite; 
     } 

     // Hide unused sprites 
     ln = group.getCount(); 
     for (j = i; j < ln; j++) { 
      group.getAt(j).hide(true); 
     } 
     // Hide unused shadows 
     if (enableShadows) { 
      for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) { 
       shadowGroup = shadowGroups[shadowIndex]; 
       ln = shadowGroup.getCount(); 
       for (j = i; j < ln; j++) { 
        shadowGroup.getAt(j).hide(true); 
       } 
      } 
     } 
     me.renderLabels(); 
    } 
}); 

Oto lista zmian dla renderer():

  • Drugim parametrem jest teraz odwzorowywane do odpowiedniej pozycji w sklepie
  • Czwarty parametr jest teraz numer indeksu sklep zamiast numeru elementu wewnętrznego (bezwartościowy inaczej IMO)
  • Dodano szósty parametr, który mówi aktualny indeks segmentu w obrębie rekordu, nie licząc innych właściwości w rekordzie, które nie należą do osi.
    Przykład: dla rekordu, który wygląda jak {name: 'metric': segment1: 12, segment2: 22} indeks dla segment1 będzie 0 zamiast 1, ponieważ pierwsza pozycja w rekordzie nie należą do jego osi (jest to nazwa kategorii)

Więc, odpowiedzieć na pytanie, teraz można użyć renderujący tak:

renderer: function(sprite, record, attr, storeIndex, store, col) { 
    // set the color to white for the first item in every record 
    return (col == 0)? Ext.apply(attr, { fill: '#fff' }) : attr; 
} 

Jeśli chcesz ustawić kolor o nazwie elementu, można również zrobić to w ten sposób:

// let's say that every record looks like this: 
// {name: 'metric one', user1: 23, user2: 50, user3: 10} 

renderer: function(sprite, record, attr, storeIndex, store, col) { 
    // retrieve the segment property name from the record using its numeric index. 
    // remember that 'col' doesn't take into account other fields that don't 
    // belong to the axis, so in this case we have to add 1 to the index 
    var uid = Ext.Object.getAt(record.data, col+1)[0]; 

    // set the color to red for 'user2' 
    return (uid == 'user2')? Ext.apply(attr, { fill: '#f00' }) : attr; 
} 

Z tego ostatniego, trzeba tę funkcję, która pozwala odzyskać nieruchomość z obiektu przy użyciu indeks liczbowy:

/** 
* Returns the key and its value at the idx position 
* @return {Array} Array containing [key, value] or null 
*/ 
Ext.Object.getAt = function(obj, idx) { 
    var keys = Ext.Object.getKeys(obj); 
    if (idx < keys.length) { 
     return [keys[idx],obj[keys[idx]]]; 
    } 
    return null; 
} 
+0

Dokładnie tego potrzebuję. Ale kiedy stworzę nadpisanie w architekturze sencha. To auto wypełnia się z ext.define (moja app.view ... Jak mogę to nadpisać. – Cripto

2

Indeks informuje, który element jest renderowany. Zauważyłem jednak, że w niektórych sytuacjach renderer() jest wywoływany 3 razy, zanim elementy zaczną być przetwarzane. Zapytałem na forach Sencha o tym, ale bezskutecznie.

+0

znalazłeś rozwiązanie? czy podzieliłbyś się plz? – Armance

+0

Znalazłem, że ustawienie 'shadow: false' rozwiązuje problem wielu wywołań do' renderer() '. To i tak nie jest duża strata, ponieważ shadowing wydaje się być zepsuty dla skumulowanych wykresów słupkowych (przynajmniej w wersji 4.0.7). –