    /** * The base class of every Canvas D3 Component that can also be used standalone. * For example: * *     @example *     Ext.create({ *         renderTo: document.body, * *         width: 300, *         height: 300, * *         xtype: 'd3-canvas', * *         listeners: { *             canvasresize: function (component, canvas, size) { *                 var barCount = 10, *                     barWidth = size.width / barCount, *                     barHeight = size.height, *                     context = canvas.getContext('2d'), *                     colors = d3.scale.category20(), *                     i = 0; * *                 for (; i < barCount; i++) { *                     context.fillStyle = colors(i); *                     context.fillRect(i * barWidth, 0, barWidth, barHeight); *                 } *             } *     }); */Ext.define('Ext.d3.canvas.Canvas', {    extend: 'Ext.d3.Component',    xtype: 'd3-canvas',     isCanvas: true,     config: {        /**         * @cfg {Boolean} [hdpi=true]         * If `true`, will automatically override Canvas context ('2d') methods         * when running on HDPI displays. Setting this to 'false' will greatly         * improve performance on such devices at the cost of image quality.         * It can also be useful when this class is used in conjunction with         * another Canvas library that provides HDPI support as well.         * Once set cannot be changed.         */        hdpi: true    },     requires: [        'Ext.d3.canvas.HiDPI'    ],     template: [{        tag: 'canvas',        reference: 'canvasElement',        style: {            position: 'absolute'        }    }],     canvas: null,    context2D: null,     /**     * This method will be called by the {@link #onPanZoom} method each time     * the canvas context is transformed via {@link Ext.d3.interaction.PanZoom}     * interaction.     * @method renderScene     * @param {CanvasRenderingContext2D} ctx      */    renderScene: null,     /**     * Returns the Canvas element to draw on.     * Overrides for resolution independent drawing are automatically applied     * to the '2d' rendering context of the canvas the first time the method is called.     * @return {HTMLCanvasElement}     */    getCanvas: function () {        var me = this,            canvas = me.canvas;         if (!canvas) {            canvas = me.canvasElement.dom;            if (me.getHdpi()) {                canvas = Ext.d3.canvas.HiDPI.applyOverrides(canvas);            }            me.canvas = canvas;            me.context2D = canvas.getContext('2d');        }         return canvas;    },     /**     * @private     * Calculates and sets scene size and position based on the given `size` object.     * @param {Object} size      * @param {Number} size.width     * @param {Number} size.height     */    resizeHandler: function (size) {        var me = this,            canvas = me.canvas || me.getCanvas(),            rect = me.sceneRect || (me.sceneRect = {});         rect.x = 0;        rect.y = 0;         rect.width = size.width;        rect.height = size.height;         Ext.d3.canvas.HiDPI.setSize(canvas, rect.width, rect.height);         me.onSceneResize(canvas, rect);        me.fireEvent('sceneresize', me, canvas, rect);    },     /**     * Whether or not the component got its first size.     * Can be used in the `canvasresize` event handler to do user-defined setup on first     * resize, for example:     *     *     listeners: {     *         canvasresize: function (component, canvas, rect) {     *             if (!component.size) {     *                 // set things up     *             } else {     *                 // handle resize     *             }     *         }     *     }     *     * @cfg {Object} size      * @accessor     */     /**     * @event sceneresize     * Fires after scene size has changed.     * Note that resizing the Canvas will reset its context, e.g.     * `lineWidth` will be reset to `1`, `fillStyle` to `#000000`, and so on,     * including transformations.     * @param {Ext.d3.canvas.Canvas} component     * @param {HTMLCanvasElement} canvas      * @param {Object} size An object with `width` and `height` properties.     */     /**     * @method onSceneResize     * @protected     * This method is called after the scene gets its position and size.     * It's a good place to recalculate layout(s) and re-render the scene.     * @param {HTMLCanvasElement} canvas      * @param {Object} rect      * @param {Number} rect.x     * @param {Number} rect.y     * @param {Number} rect.width     * @param {Number} rect.height     */    onSceneResize: Ext.emptyFn,     onPanZoom: function (interaction, scaling, translation) {        var me = this,            canvas = me.canvas,            ctx = me.context2D;         if (ctx && me.renderScene) {            ctx.save();            ctx.clearRect(0, 0, canvas.width, canvas.height);            ctx.setTransform(scaling[0], 0, 0, scaling[1], translation[0], translation[1]);            me.renderScene(ctx);            ctx.restore();        }    },     /**     * @private     */    getSceneRect: function () {        return this.sceneRect;    }});