1. #1
    Sencha User stevemc's Avatar
    Join Date
    Sep 2007
    Location
    London
    Posts
    29
    Vote Rating
    4
    stevemc is on a distinguished road

      2  

    Default TreeMap chart

    TreeMap chart


    A TreeMap chart is a sort of interlocking rectangle chart where the size of the individual rectangles are proportional to their values. You can see a flash version on The Guardian website at: http://www.guardian.co.uk/politics/interactive/2010/oct/19/comprehensive-spending-review-cuts

    I've started my own version in Ext - see example at:
    http://www.stevemcarthur.co.uk/widgets/SpendCuts/

    Code:
    /**
     *
     * @author Steve McArthur
     * @class HK.chart.TreeMap
     * @extends Ext.draw.Component
     * Treemaps display hierarchical (tree-structured) data as a set of nested rectangles.
     * Each nested rectangle has an area proportional to a specified dimension on the data.
     * See: http://en.wikipedia.org/wiki/Treemapping
     * By default this class uses the Squarify algorithmn to calculate the tree map. It is
     * based on the open source code written by Martin Cowie and found at: http://js-treemap.sourceforge.net/
     *
     * Example usage:
     <pre><code>
    
    
     Ext.define("Dept", {
     extend : 'Ext.data.Model',
     fields : ['id', 'Name', 'Title', {
     name : 'Cost',
     type : 'float'
     }],
     hasMany : {
     model : 'Savings',
     name : 'savings'
     }
     });
    
    
     var myStore = Ext.create('Ext.data.ArrayStore', {
     autoDestroy : true,
     model : 'Dept',
     data : [[1, "Corporate, Subsidy, Grant & Levies etc", "Corporate, Subsidy, Grant & Levies etc", 556.23], [2, "Health and Community Services", "Health and Community Services", 171.71], [3, "Children and Young People", "Children and\r\n Young People", 51.87], [4, "Finance and Resources", "Finance and Resources", 47.39], [5, "Legal, HR and Regulatory Services", "Legal, HR and\r\n Regulatory Services", 15.74], [6, "Chief Executive", "Chief Executive", 8.24], [7, "Housing", "Housing", 2]]
     });
    
    
     Ext.create('HK.chart.TreeMap', {
     chartWidth: 1000,
     chartHeight: 530,
     chartX: 0,
     chartY: 40,
     store: myStore,
     renderTo: Ext.getBody()
     });
     </code></pre>
     * @xtype treemap
     *
     */
    
    
    Ext.define('HK.chart.TreeMap', {
        extend: 'Ext.draw.Component',
        alternateClassName: 'TreeMap',
        requires: ['HK.chart.Squarify', 'HK.chart.TreeMapSprite'],
        type: 'treemap',
        store: {},
        nodes: [],
        sprites: [],
        startTotal: 0,
        textThreshold: 5,
        inheritableStatics: {
            TreeMapEngine: {
                'squarify': HK.chart.Squarify
            }
        },
        setOpacity: function(cmp, op, speed, callback) {
            var duration = speed || 500;
            if (!callback) {
                callback = Ext.emptyFn;
            }
            // cmp.stopAnimation();
            return cmp.animate({
                to: {
                    opacity: op
                },
                duration: duration,
                callback: callback
            });
        },
        setSpriteOpacity: function(op, cmp, speed, arr) {
            var me = this;
            var items = arr || me.sprites;
            var op2 = op === 1 ? 0 : 1;
            me.hoverTitle.setAttributes({
                text: cmp.text,
                opacity: op2
            }, true);
            Ext.each(items, function(item, idx, all) {
                if (item.id != cmp.id) {
                    item.stopAnimation();
                    me.setOpacity(item, op, speed);
                    if (item.title && !item.title.hidden) {
                        item.title.stopAnimation();
                        item.subTitle.stopAnimation();
                        me.setOpacity(item.title, op, speed);
                        me.setOpacity(item.subTitle, op, speed);
    
    
                    }
                }
            });
        },
        /**
        * Creates new TreeMap.
        * @param {Object} config Config object.
        */
        constructor: function(config) {
            var me = this;
            me.store = config.store;
    
    
            var defaults = {
                viewBox: false,
                autoShow: true,
                width: config.chartWidth + 50,
                height: config.chartHeight + 70,
                x: 0,
                y: 0,
                renderTo: Ext.get('div1'),
                engine: 'squarify'
            };
            config = Ext.apply(defaults, config);
    
    
            me.callParent([config]);
            var engine = TreeMap.TreeMapEngine[this.engine];
    
    
            me.nodes = engine.create(me.store, config.chartX, config.chartY, config.chartWidth, config.chartHeight);
            me.startTotal = HK.chart.Squarify.getTotal(me.nodes);
            TreeMapSprite.surface = me.surface;
    
    
            me.hoverTitle = Ext.create('Ext.draw.Sprite', {
                type: 'text',
                "text-anchor": "end",
                "text": "hoverTitle",
                opacity: 0,
                font: 'bold 14px Arial',
                fill: '#666666',
                x: 950,
                y: this.chartY + this.chartHeight + 20
            });
            me.surface.add(me.hoverTitle).show(true);
        },
    
    
        show: function() {
            var me = this;
            var l = me.nodes.length;
            var nodes = me.nodes;
            for (var i = 0; i < l; i++) {
                var rec = nodes[i];
                var clr = Ext.draw.Color.fromString(rec.col);
                //this will be the fade out color
                var clr2 = clr.getLighter(0.4);
                var width = rec.coords.width;
                var height = rec.coords.height;
                var txtX = rec.coords.x + 10;
                var txtY = rec.coords.y + 20;
    
    
                var text = "£" + rec.Cost;
                text = rec.Cost < 150 ? text + "bn" : text + " billion";
                var textSize = "25px";
                var hidden = false;
                if (rec.Cost < 150 && rec.Cost > 40) {
                    textSize = "20px";
                } else if (rec.Cost < 41) {
                    textSize = "16px";
                }
                if (rec.Cost < this.textThreshold) {
                    hidden = true;
                }
    
    
                var cfg = {
                    x: rec.coords.x,
                    y: rec.coords.y,
                    width: width,
                    height: height,
                    startFill: clr2.toString(),
                    fill: rec.col,
                    costs: rec.Cost,
                    text: rec.Title + " " + text,
                    titleTxt: rec.Title,
                    itemNo: i,
                    hidden: false,
                    opacity: 0,
                    treeMap: me,
                    title: Ext.create('Ext.draw.Sprite', {
                        type: 'text',
                        "text-anchor": "left",
                        "text": text,
                        font: '500 ' + textSize + ' "Times New Roman",Georgia,Serif',
                        fill: '#FFFFFF',
                        // surface: this.surface,
                        hidden: hidden,
                        x: txtX,
                        y: txtY,
                        zIndex: 10
                    }),
                    subTitle: Ext.create('Ext.draw.Sprite', {
                        type: 'text',
                        "text-anchor": "left",
                        "text": rec.Name,
                        font: 'bold 12px Arial',
                        fill: '#FFFFFF',
                        hidden: hidden,
                        // surface: this.surface,
                        x: txtX,
                        y: txtY + 20,
                        zIndex: 10
                    })
                };
    
    
                var item = Ext.create('HK.chart.TreeMapSprite', cfg);
                me.sprites.push(item);
    
    
            }
    
    
            Ext.each(me.sprites, function(sp, idx) {
                me.surface.add(sp).show(true).animate({
                    to: {
                        opacity: 1
                    },
                    duration: 1000,
                    easing: 'easeIn'
                });
    
    
                me.surface.add(sp.title).show(!sp.title.hidden);
                me.surface.add(sp.subTitle).show(!sp.subTitle.hidden);
    
    
            });
            me.showBorder();
        },
        showBorder: function() {
            var me = this;
            if (!me.chartBorder) {
                me.chartBorder = Ext.create('Ext.draw.Sprite', {
                    type: 'rect',
                    width: me.chartWidth,
                    height: me.chartHeight,
                    x: me.chartX,
                    y: me.chartY,
                    stroke: '#000000',
                    "stroke-opacity": 1,
                    "stroke-width": 3,
                    fill: 'none',
                    opacity: 1,
                    zIndex: 9999
                });
                me.surface.add(me.chartBorder);
            }
            me.chartBorder.show(true);
        }
    })
    TreeMap.jpg
    One of the main differences with the Guardian chart is that mine recalculates it size after changes are made.

    Just looking for feedback really.
    Attached Files
    Last edited by stevemc; 14 Jun 2012 at 10:21 AM. Reason: Add screen shot

  2. #2
    Sencha - Support Team scottmartin's Avatar
    Join Date
    Jul 2010
    Location
    Houston, Tx
    Posts
    9,197
    Vote Rating
    482
    scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future

      0  

    Default


    Thank you for the contribution.

    Scott.

  3. #3
    Sencha User stevemc's Avatar
    Join Date
    Sep 2007
    Location
    London
    Posts
    29
    Vote Rating
    4
    stevemc is on a distinguished road

      0  

    Default Simple TreeMap Example

    Simple TreeMap Example


    Hi all

    I've now added a more simple example of a TreeMap chart at: http://www.stevemcarthur.co.uk/widge...sicTreeMap.htm.

    Planning to do an example in conjunction with either a plain html table or Ext Grid where they user can change the values
    Last edited by stevemc; 15 Jun 2012 at 11:04 AM. Reason: additional though

  4. #4
    Sencha User stevemc's Avatar
    Join Date
    Sep 2007
    Location
    London
    Posts
    29
    Vote Rating
    4
    stevemc is on a distinguished road

      1  

    Default


    I've now added some additional animation to get it to work like the Guardian version with the rectangles moving in from the edge of the page. At the moment, this is hard coded into the extension as I'm not sure how to generate the direction based on the data. Have a look again:
    http://www.stevemcarthur.co.uk/widge...sicTreeMap.htm

  5. #5
    Sencha User mgavr's Avatar
    Join Date
    Jun 2011
    Location
    San Jose, USA
    Posts
    5
    Vote Rating
    0
    mgavr is on a distinguished road

      0  

    Default


    Hi Steve,

    I need a TreeMap in my current project. It seems that all links that you provided in this thread are no longer valid. Is your TreeMap plugin still available?

    Mikhail

  6. #6
    Sencha User
    Join Date
    Jan 2014
    Location
    Mumbai, India
    Posts
    4
    Vote Rating
    0
    manish.sharma1992 is on a distinguished road

      0  

    Default TreeMap

    TreeMap


    Hi Steve,

    The links you have provided in the above thread seems to be no longer valid I request you to please send us the new link to your website for our reference and study on it.

    Thank you in advance

    Awaiting for your positive reply

    Manish Sharma