Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Interactive visual analytics using Sencha Charts by Vitaly Kravchenko

Interactive visual analytics using Sencha Charts by Vitaly Kravchenko

Charts and graphs are core to any enterprise grade analytics application. With Ext JS 5, Sencha Charts (formerly a part of Sencha Touch) provide advanced charting capabilities with interactive features for both desktop and mobile devices. The session walks through all the Do's and Don'ts of using Sencha Charts, how to add interactions, and how to migrate from old Ext JS Charts package to Sencha Charts. You will also learn about the fundamentals of sprites to customize the rendering of various charts elements.

Lee Boonstra

June 03, 2015
Tweet

More Decks by Lee Boonstra

Other Decks in Technology

Transcript

  1. View Slide

  2. Interactive visual analytics
    using Sencha Charts
    Vitaly Kravchenko
    SenchaCon 2015 - April 9, 2015

    View Slide

  3. Vitaly Kravchenko
    Graphics Engineer, Sencha

    View Slide

  4. Ext Core

    View Slide

  5. Charts and Draw packages
    are shared by both toolkits
    Classic Modern

    View Slide

  6. View Slide

  7. View Slide

  8. items: {

    xtype: 'cartesian',


    series: {

    type: 'bar3d'

    },


    axes: [{

    type: 'numeric3d',

    position: 'left'

    }, {

    type: 'category3d',

    position: 'bottom'

    }]

    }
    3D Bar

    View Slide

  9. 3D Pie
    series: {

    type: 'pie3d'

    }

    View Slide

  10. View Slide

  11. View Slide

  12. Challenge

    View Slide

  13. View Slide

  14. View Slide

  15. View Slide

  16. View Slide

  17. View Slide

  18. View Slide

  19. Data

    View Slide

  20. {label: 'year', span: 100},
    // Northeast region

    {label: 'CT', span: 100, y2007: 0.2, ..., y2012: -0.6, state: 'Connecticut'},

    {label: 'DE', span: 100, y2007: 0.0, ..., y2012: -0.3, state: 'Delaware'},

    ...


    {label: '', span: 20},

    // Southeast region

    {label: 'AL', span: 100, y2007: -0.1, ..., y2012: -1.4, state: 'Alabama'},

    {label: 'DC', span: 100, y2007: -0.2, ..., y2012: -1.1, state: 'District of Columbia’},
    ...

    View Slide

  21. items: [

    {

    xtype: 'polar',


    store: {

    type: 'unemployment'

    },


    series: [{

    type: ‘pie',

    angleField: 'span',


    donut: 93


    }]

    }

    ]

    View Slide

  22. View Slide

  23. layout: 'absolute',

    width: 990,


    items: [

    {

    xtype: 'polar',


    width: '100%',

    height: 1375,

    insetPadding: '400 0 125 0’,
    . . .
    400
    0
    0
    125

    View Slide

  24. Adding infographic content

    View Slide

  25. HTML vs Sprites

    View Slide

  26. sprites: [

    {

    type: 'rect',

    x: 50,

    y: 40,

    width: 890,

    height: 100,

    fillStyle: 'rgb(77, 77, 77)'

    },

    {

    type: 'text',

    text: 'Changes in U.S. Unemployment',

    font: 'bold 54px Charter',

    fillStyle: 'white',

    x: 70,

    y: 120

    }

    View Slide

  27. Labels?

    View Slide

  28. series: {

    type: 'pie',

    . . .

    label: {

    field: ‘label',

    display: ‘inside',

    fillStyle: ‘white',

    fontSize: 13,
    fontWeight: ‘bold',

    fontFamily: 'Tahoma'

    }

    }

    View Slide

  29. 29

    View Slide

  30. series: {

    type: 'pie',

    angleField: ‘span',
    ...,


    label: {

    field: ‘label',
    ...,


    renderer: 'onLabelRender2012'

    },
    renderer: 'onSliceRender2012'


    }

    View Slide

  31. onLabelRender2012: function (text, sprite, config, data, index) {

    if (text === 'year') {

    return {

    text: '2012',

    font: 'bold 16px sans-serif'

    };

    }

    }

    View Slide

  32. onSliceRender2012: function (sprite, config, data, index) {

    var record = data.store.getAt(index),

    label = record.get('label'),

    unemployment = record.get('y2012'),

    style = {};


    if (label === '') {

    style.fillStyle = 'none';

    style.strokeStyle = 'none';

    } else if (label === 'year') {

    style.fillStyle = ‘#444';

    } else {

    style.fillStyle = this.getStateColor(unemployment);

    }

    return style;

    }

    View Slide

  33. 33

    View Slide

  34. series: [{

    type: 'pie',

    angleField: 'span',


    donut: 93

    }, {

    type: 'pie',

    angleField: 'span',


    radiusFactor: 93,

    donut: 86

    }, {

    type: 'pie',

    angleField: 'span',


    radiusFactor: 86,

    donut: 79,

    }, {
    . . .

    View Slide

  35. View Slide

  36. Interactions

    View Slide

  37. highlight: true
    highlightCfg: {

    margin: 20

    }
    highlight: {

    fillStyle: 'yellow'

    }
    highlight: {

    fillStyle: ‘yellow',
    margin: 0

    }
    highlightCfg: {

    fllStyle: 'yellow'

    }

    View Slide

  38. Performance Optimization

    View Slide

  39. {

    xtype: 'polar',


    interactions: ['itemhighlight'],


    series: [

    {

    type: 'pie',

    angleField: 'span',


    donut: 57,


    subStyle: {

    fillStyle: 'none',

    strokeStyle: 'none'

    },


    highlightCfg: {

    fillStyle: 'rgba(0,0,0,0.2)'

    },
    . . .

    View Slide

  40. Adding cartesian chart

    View Slide

  41. {

    xtype: 'cartesian',


    width: 350,

    height: 250,


    x: 300,

    y: 700,


    series: {

    type: 'bar',


    xField: 'year',

    yField: 'percent',


    renderer: 'onBarRender'

    }
    }

    View Slide

  42. listeners: {

    itemhighlight: 'onItemHighlight'

    }

    View Slide

  43. var storeData = [

    {year: '2007', percent: recordData.y2007},

    {year: '2008', percent: recordData.y2008},

    {year: '2009', percent: recordData.y2009},

    {year: '2010', percent: recordData.y2010},

    {year: '2011', percent: recordData.y2011},

    {year: '2012', percent: recordData.y2012}

    ];
    onItemHighlight: function (chart, item) {


    var recordData = item.record.data;
    this.lookupReference('cartesian').getStore().setData(storeData);

    View Slide

  44. View Slide

  45. Draw package

    View Slide

  46. Main features
    ✦ Allows to create arbitrary graphics
    ✦ Renderer agnostic
    ✦ Sprite based

    View Slide

  47. Ext.draw.Container
    Ext.draw.Surface
    Ext.draw.Surface
    Ext.draw.Surface
    Sprite Sprite
    Sprite

    View Slide

  48. Surface management
    Ext.draw.Container
    config: {

    resizeHandler: null
    }
    drawContainer.renderFrame();
    defaultResizeHandler: function (size) {

    this.getItems().each(function (surface) {

    surface.setRect([0, 0, size.width, size.height]);

    });

    }

    View Slide

  49. Ext.chart.AbstractChart
    series surface
    performLayout();
    bottom axis surface x
    left axis surface
    y

    View Slide

  50. Surface creation
    drawContainer.getSurface(id);

    View Slide

  51. Engines
    engine: 'Ext.draw.engine.Canvas'
    engine: 'Ext.draw.engine.SVG'

    View Slide

  52. Draw Surface
    Ext.draw.Surface
    Ext.draw.engine.Canvas Ext.draw.engine.Svg
    Canvas VML SVG
    Ext.draw.engine.SvgContext
    Native Canvas 2D context Ext.draw.engine.excanvas
    Ext.Widget Ext.Component
    CLASSIC MODERN

    View Slide

  53. Surface methods
    surface.renderFrame();
    add(config/sprite);
    remove(sprite/id);
    get(id);
    clear();
    surface.renderSprite(sprite);
    sprite.render(ctx);

    View Slide

  54. Performant Flexible Extensible
    General Purpose
    Themeable
    Bi-directional
    Renderer Agnostic
    Mobile / Touch Cross-toolkit

    View Slide

  55. Credits: http://goo.gl/5ywnzO
    Twitter: @vitalyx
    Thank you!
    Example code: https://github.com/yay/SenchaCon2015

    View Slide