Форк Rambox
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

370 lines
9.7 KiB

/**
* The Draw Component is a surface in which sprites can be rendered. The Draw Component
* manages and holds an {@link Ext.draw.Surface} instance where
* {@link Ext.draw.Sprite Sprites} can be appended.
*
* One way to create a draw component is:
*
* @example
* var drawComponent = Ext.create('Ext.draw.Component', {
* viewBox: false,
* items: [{
* type: 'circle',
* fill: '#79BB3F',
* radius: 100,
* x: 100,
* y: 100
* }]
* });
*
* Ext.create('Ext.Window', {
* width: 215,
* height: 235,
* layout: 'fit',
* items: [drawComponent]
* }).show();
*
* In this case we created a draw component and added a {@link Ext.draw.Sprite sprite} to it.
* The {@link Ext.draw.Sprite#type type} of the sprite is `circle` so if you run this code you'll see a yellow-ish
* circle in a Window. When setting `viewBox` to `false` we are responsible for setting the object's position and
* dimensions accordingly.
*
* You can also add sprites by using the surface's add method:
*
* drawComponent.surface.add({
* type: 'circle',
* fill: '#79BB3F',
* radius: 100,
* x: 100,
* y: 100
* });
*
* ## Larger example
*
* @example
* var drawComponent = Ext.create('Ext.draw.Component', {
* width: 800,
* height: 600,
* renderTo: document.body
* }), surface = drawComponent.surface;
*
* surface.add([{
* type: 'circle',
* radius: 10,
* fill: '#f00',
* x: 10,
* y: 10,
* group: 'circles'
* }, {
* type: 'circle',
* radius: 10,
* fill: '#0f0',
* x: 50,
* y: 50,
* group: 'circles'
* }, {
* type: 'circle',
* radius: 10,
* fill: '#00f',
* x: 100,
* y: 100,
* group: 'circles'
* }, {
* type: 'rect',
* width: 20,
* height: 20,
* fill: '#f00',
* x: 10,
* y: 10,
* group: 'rectangles'
* }, {
* type: 'rect',
* width: 20,
* height: 20,
* fill: '#0f0',
* x: 50,
* y: 50,
* group: 'rectangles'
* }, {
* type: 'rect',
* width: 20,
* height: 20,
* fill: '#00f',
* x: 100,
* y: 100,
* group: 'rectangles'
* }]);
*
* // Get references to my groups
* circles = surface.getGroup('circles');
* rectangles = surface.getGroup('rectangles');
*
* // Animate the circles down
* circles.animate({
* duration: 1000,
* to: {
* translate: {
* y: 200
* }
* }
* });
*
* // Animate the rectangles across
* rectangles.animate({
* duration: 1000,
* to: {
* translate: {
* x: 200
* }
* }
* });
*
* For more information on Sprites, the core elements added to a draw component's surface,
* refer to the {@link Ext.draw.Sprite} documentation.
*/
Ext.define('Ext.draw.Component', {
/* Begin Definitions */
alias: 'widget.draw',
extend: 'Ext.Component',
requires: [
'Ext.draw.Surface',
'Ext.draw.layout.Component'
],
/* End Definitions */
/**
* @cfg {String[]} enginePriority
* Defines the priority order for which Surface implementation to use. The first
* one supported by the current environment will be used.
*/
enginePriority: ['Svg', 'Vml'],
baseCls: Ext.baseCSSPrefix + 'surface',
componentLayout: 'draw',
/**
* @cfg {Boolean} viewBox
* Turn on view box support which will scale and position items in the draw component to fit to the component while
* maintaining aspect ratio. Note that this scaling can override other sizing settings on your items.
*/
viewBox: true,
shrinkWrap: 3,
/**
* @cfg {Boolean} autoSize
* Turn on autoSize support which will set the bounding div's size to the natural size of the contents.
*/
autoSize: false,
/**
* @cfg {Object[]} gradients (optional) Define a set of gradients that can be used as `fill` property in sprites.
* The gradients array is an array of objects with the following properties:
*
* - `id` - string - The unique name of the gradient.
* - `angle` - number, optional - The angle of the gradient in degrees.
* - `stops` - object - An object with numbers as keys (from 0 to 100) and style objects as values
*
* ## Example
*
* gradients: [{
* id: 'gradientId',
* angle: 45,
* stops: {
* 0: {
* color: '#555'
* },
* 100: {
* color: '#ddd'
* }
* }
* }, {
* id: 'gradientId2',
* angle: 0,
* stops: {
* 0: {
* color: '#590'
* },
* 20: {
* color: '#599'
* },
* 100: {
* color: '#ddd'
* }
* }
* }]
*
* Then the sprites can use `gradientId` and `gradientId2` by setting the fill attributes to those ids, for example:
*
* sprite.setAttributes({
* fill: 'url(#gradientId)'
* }, true);
*/
/**
* @cfg {Ext.draw.Sprite[]} items
* Array of sprites or sprite config objects to add initially to the surface.
*/
/**
* @property {Ext.draw.Surface} surface
* The Surface instance managed by this component.
*/
suspendSizing: 0,
/**
* @event
* Event forwarded from {@link Ext.draw.Surface surface}.
* @inheritdoc Ext.draw.Surface#mousedown
*/
/**
* @event
* Event forwarded from {@link Ext.draw.Surface surface}.
* @inheritdoc Ext.draw.Surface#mouseup
*/
/**
* @event
* Event forwarded from {@link Ext.draw.Surface surface}.
* @inheritdoc Ext.draw.Surface#mousemove
*/
/**
* @event
* Event forwarded from {@link Ext.draw.Surface surface}.
* @inheritdoc Ext.draw.Surface#mouseenter
*/
/**
* @event
* Event forwarded from {@link Ext.draw.Surface surface}.
* @inheritdoc Ext.draw.Surface#mouseleave
*/
/**
* @event
* Event forwarded from {@link Ext.draw.Surface surface}.
* @inheritdoc Ext.draw.Surface#click
*/
/**
* @event
* Event forwarded from {@link Ext.draw.Surface surface}.
* @inheritdoc Ext.draw.Surface#dblclick
*/
/**
* @private
*
* Create the Surface on initial render
*/
onRender: function() {
this.callParent(arguments);
if (this.createSurface() !== false) {
this.configureSurfaceSize();
}
},
configureSurfaceSize: function(){
var me = this,
viewBox = me.viewBox,
autoSize = me.autoSize,
bbox;
if ((viewBox || autoSize) && !me.suspendSizing) {
bbox = me.surface.items.getBBox();
if (viewBox) {
me.surface.setViewBox(bbox.x, bbox.y, bbox.width, bbox.height);
} else {
me.autoSizeSurface(bbox);
}
}
},
// @private
autoSizeSurface: function(bbox) {
bbox = bbox || this.surface.items.getBBox();
this.setSurfaceSize(bbox.width, bbox.height);
},
setSurfaceSize: function (width, height) {
this.surface.setSize(width, height);
if (this.autoSize) {
var bbox = this.surface.items.getBBox();
this.surface.setViewBox(bbox.x, bbox.y - (+Ext.isOpera), width, height);
}
},
/**
* Create the Surface instance. Resolves the correct Surface implementation to
* instantiate based on the 'enginePriority' config. Once the Surface instance is
* created you can use the handle to that instance to add sprites. For example:
*
* drawComponent.surface.add(sprite);
*
* @private
*/
createSurface: function() {
var me = this,
cfg = Ext.applyIf({
renderTo: me.el,
height: me.height,
width: me.width,
items: me.items
}, me.initialConfig), surface;
// ensure we remove any listeners to prevent duplicate events since we refire them below
delete cfg.listeners;
if (!cfg.gradients) {
cfg.gradients = me.gradients;
}
me.initSurfaceCfg(cfg);
surface = Ext.draw.Surface.create(cfg, me.enginePriority);
if (!surface) {
// In case we cannot create a surface, return false so we can stop
return false;
}
me.surface = surface;
surface.owner = me;
function refire(eventName) {
return function(e) {
me.fireEvent(eventName, e);
};
}
surface.on({
scope: me,
mouseup: refire('mouseup'),
mousedown: refire('mousedown'),
mousemove: refire('mousemove'),
mouseenter: refire('mouseenter'),
mouseleave: refire('mouseleave'),
click: refire('click'),
dblclick: refire('dblclick')
});
},
initSurfaceCfg: Ext.emptyFn,
/**
* @private
*
* Clean up the Surface instance on component destruction
*/
onDestroy: function() {
Ext.destroy(this.surface);
this.callParent(arguments);
}
});