/** * @class Ext.draw.Container * @extend Ext.draw.ContainerBase * @alternateClassName Ext.draw.Component * @xtype draw * The container that holds and manages instances of the {@link Ext.draw.Surface} * in which {@link Ext.draw.sprite.Sprite sprites} are rendered. Draw containers are * used as the foundation for all of the chart classes but may also be created directly * in order to create custom drawings. * * @example packages=[reactor] * import React, { Component } from 'react'; * import { Panel, Draw, Toolbar, Button, Spacer, Label } from '@extjs/ext-react'; * * export default class DrawExample extends Component { * * componentDidMount() { * this.refs.draw.on({ * element: 'element', * mousedown: this.onMouseDown, * mousemove: this.onMouseMove, * mouseup: this.onMouseUp, * mouseleave: this.onMouseUp * }); * } * * clear = () => { * const { draw } = this.refs; * draw.getSurface().destroy(); * draw.getSurface('overlay').destroy(); * draw.renderFrame(); * } * * onMouseDown = (e) => { * let { draw } = this.refs, * surface = draw.getSurface(), * xy, x, y; * * if (!draw.sprite) { * xy = surface.getEventXY(e); * x = xy[0]; * y = xy[1]; * * draw.list = [x, y, x, y]; * draw.lastEventX = x; * draw.lastEventY = y; * * draw.sprite = surface.add({ * type: 'path', * path: ['M', draw.list[0], draw.list[1], 'L', draw.list[0] + 1e-1, draw.list[1] + 1e-1], * lineWidth: 30 * Math.random() + 10, * lineCap: 'round', * lineJoin: 'round', * strokeStyle: new Ext.util.Color(Math.random() * 127 + 128, Math.random() * 127 + 128, Math.random() * 127 + 128) * }); * * surface.renderFrame(); * } * } * * onMouseMove = (e) => { * let { draw } = this.refs, * surface = draw.getSurface(), * path, xy, x, y, dx, dy, D; * * if (draw.sprite) { * xy = surface.getEventXY(e); * x = xy[0]; * y = xy[1]; * dx = draw.lastEventX - x; * dy = draw.lastEventY - y; * D = 10; * * if (dx * dx + dy * dy < D * D) { * draw.list.length -= 2; * draw.list.push(x, y); * } else { * draw.list.length -= 2; * draw.list.push(draw.lastEventX = x, draw.lastEventY = y); * draw.list.push(draw.lastEventX + 1, draw.lastEventY + 1); * } * * path = smoothList(draw.list); * * draw.sprite.setAttributes({ * path: path * }); * * if (Ext.os.is.Android) { * Ext.draw.Animator.schedule(() => surface.renderFrame(), draw); * } else { * surface.renderFrame(); * } * } * } * * onMouseUp = (e) => { * this.refs.draw.sprite = null; * } * * onResize = () => { * const { draw } = this.refs; * const size = draw.element.getSize(); * draw.getSurface().setRect([0, 0, size.width, size.height]); * draw.renderFrame(); * } * * render() { * return ( * <Panel shadow layout="fit"> * <Toolbar docked="top"> * <div style={{fontSize: Ext.os.is.Phone ? '12px' : '14px'}}>Use your {Ext.supports.Touch ? 'finger' : 'mouse'} to paint on the surface below.</div> * <Spacer/> * <Button handler={this.clear} text="Clear"/> * </Toolbar> * <Draw ref="draw"/> * </Panel> * ) * } * } * * function smoothList(points) { * if (points.length < 3) { * return ['M', points[0], points[1]]; * } * * var dx = [], dy = [], result = ['M'], * i, ln = points.length; * * for (i = 0; i < ln; i += 2) { * dx.push(points[i]); * dy.push(points[i + 1]); * } * * dx = Ext.draw.Draw.spline(dx); * dy = Ext.draw.Draw.spline(dy); * result.push(dx[0], dy[0], 'C'); * * for (i = 1, ln = dx.length; i < ln; i++) { * result.push(dx[i], dy[i]); * } * * return result; * } */ /** * @cfg {String} [engine="Ext.draw.engine.Canvas"] * Defines the engine (type of surface) used to render draw container contents. * * The render engine is selected automatically depending on the platform used. Priority * is given to the {@link Ext.draw.engine.Canvas} engine due to its performance advantage. * * You may also set the engine config to be `Ext.draw.engine.Svg` if so desired. */ /** * @event spritemousemove * Fires when the mouse is moved on a sprite. * @param {Object} sprite * @param {Event} event */ /** * @event spritemouseup * Fires when a mouseup event occurs on a sprite. * @param {Object} sprite * @param {Event} event */ /** * @event spritemousedown * Fires when a mousedown event occurs on a sprite. * @param {Object} sprite * @param {Event} event */ /** * @event spritemouseover * Fires when the mouse enters a sprite. * @param {Object} sprite * @param {Event} event */ /** * @event spritemouseout * Fires when the mouse exits a sprite. * @param {Object} sprite * @param {Event} event */ /** * @event spriteclick * Fires when a click event occurs on a sprite. * @param {Object} sprite * @param {Event} event */ /** * @event spritedblclick * Fires when a double click event occurs on a sprite. * @param {Object} sprite * @param {Event} event */ /** * @event spritetap * Fires when a tap event occurs on a sprite. * @param {Object} sprite * @param {Event} event */ /** * @event bodyresize * Fires when the size of the draw container body changes. * @param {Object} size The object containing 'width' and 'height' of the draw container's body. */ /** * @cfg {Function} [resizeHandler=null] * The resize function that can be configured to have a behavior, * e.g. resize draw surfaces based on new draw container dimensions. * The `resizeHandler` function takes a single parameter - * the size object with `width` and `height` properties. * * __Note:__ since resize events trigger {@link #renderFrame} calls automatically, * return `false` from the resize function, if it also calls `renderFrame`, * to prevent double rendering. * @accessor */ /** * @cfg {Object[]} [sprites=null] * Defines a set of sprites to be added to the drawContainer surface. * * For example: * * sprites: [{ * type: 'circle', * fillStyle: '#79BB3F', * r: 100, * x: 100, * y: 100 * }] * * @accessor */ /** * @cfg {Object[]} [gradients=[]] * Defines a set of gradients that can be used as color properties * (fillStyle and strokeStyle, but not shadowColor) in sprites. * The gradients array is an array of objects with the following properties: * - **id** - string - The unique name of the gradient. * - **type** - string, optional - The type of the gradient. Available types are: 'linear', 'radial'. Defaults to 'linear'. * - **angle** - number, optional - The angle of the gradient in degrees. * - **stops** - array - An array of objects with 'color' and 'offset' properties, where 'offset' is a real number from 0 to 1. * * For example: * * gradients: [{ * id: 'gradientId1', * type: 'linear', * angle: 45, * stops: [{ * offset: 0, * color: 'red' * }, { * offset: 1, * color: 'yellow' * }] * }, { * id: 'gradientId2', * type: 'radial', * stops: [{ * offset: 0, * color: '#555', * }, { * offset: 1, * color: '#ddd', * }] * }] * * Then the sprites can use 'gradientId1' and 'gradientId2' by setting the color attributes to those ids, for example: * * sprite.setAttributes({ * fillStyle: 'url(#gradientId1)', * strokeStyle: 'url(#gradientId2)' * }); * * @accessor */ /** * @cfg {String} [downloadServerUrl] * The default URL used by the {@link #download} method. * @accessor */