]>
Commit | Line | Data |
---|---|---|
c4685c84 TL |
1 | /** |
2 | * @class Ext.draw.engine.Svg | |
3 | * @extends Ext.draw.Surface | |
4 | * | |
5 | * SVG engine. | |
6 | */ | |
7 | Ext.define('Ext.draw.engine.Svg', { | |
8 | extend: 'Ext.draw.Surface', | |
9 | requires: ['Ext.draw.engine.SvgContext'], | |
10 | ||
11 | statics: { | |
12 | BBoxTextCache: {} | |
13 | }, | |
14 | ||
15 | config: { | |
16 | /** | |
17 | * Nothing needs to be done in high precision mode. | |
18 | */ | |
19 | highPrecision: false | |
20 | }, | |
21 | ||
22 | getElementConfig: function () { | |
23 | return { | |
24 | reference: 'element', | |
25 | style: { | |
26 | position: 'absolute' | |
27 | }, | |
28 | children: [ | |
29 | { | |
30 | reference: 'innerElement', | |
31 | style: { | |
32 | width: '100%', | |
33 | height: '100%', | |
34 | position: 'relative' | |
35 | }, | |
36 | children: [ | |
37 | { | |
38 | tag: 'svg', | |
39 | reference: 'svgElement', | |
40 | namespace: "http://www.w3.org/2000/svg", | |
41 | version: 1.1, | |
42 | cls: 'x-surface' | |
43 | } | |
44 | ] | |
45 | } | |
46 | ] | |
47 | }; | |
48 | }, | |
49 | ||
50 | constructor: function (config) { | |
51 | var me = this; | |
52 | me.callSuper([config]); | |
53 | me.mainGroup = me.createSvgNode("g"); | |
54 | me.defElement = me.createSvgNode("defs"); | |
55 | // me.svgElement is assigned in element creation of Ext.Component. | |
56 | me.svgElement.appendChild(me.mainGroup); | |
57 | me.svgElement.appendChild(me.defElement); | |
58 | me.ctx = new Ext.draw.engine.SvgContext(me); | |
59 | }, | |
60 | ||
61 | /** | |
62 | * Creates a DOM element under the SVG namespace of the given type. | |
63 | * @param {String} type The type of the SVG DOM element. | |
64 | * @return {*} The created element. | |
65 | */ | |
66 | createSvgNode: function (type) { | |
67 | var node = document.createElementNS("http://www.w3.org/2000/svg", type); | |
68 | return Ext.get(node); | |
69 | }, | |
70 | ||
71 | /** | |
72 | * @private | |
73 | * Returns the SVG DOM element at the given position. If it does not already exist or is a different element tag | |
74 | * it will be created and inserted into the DOM. | |
75 | * @param {Ext.dom.Element} group The parent DOM element. | |
76 | * @param {String} tag The SVG element tag. | |
77 | * @param {Number} position The position of the element in the DOM. | |
78 | * @return {Ext.dom.Element} The SVG element. | |
79 | */ | |
80 | getSvgElement: function (group, tag, position) { | |
81 | var element; | |
82 | if (group.dom.childNodes.length > position) { | |
83 | element = group.dom.childNodes[position]; | |
84 | if (element.tagName === tag) { | |
85 | return Ext.get(element); | |
86 | } else { | |
87 | Ext.destroy(element); | |
88 | } | |
89 | } | |
90 | ||
91 | element = Ext.get(this.createSvgNode(tag)); | |
92 | if (position === 0) { | |
93 | group.insertFirst(element); | |
94 | } else { | |
95 | element.insertAfter(Ext.fly(group.dom.childNodes[position - 1])); | |
96 | } | |
97 | element.cache = {}; | |
98 | return element; | |
99 | }, | |
100 | ||
101 | /** | |
102 | * @private | |
103 | * Applies attributes to the given element. | |
104 | * @param {Ext.dom.Element} element The DOM element to be applied. | |
105 | * @param {Object} attributes The attributes to apply to the element. | |
106 | */ | |
107 | setElementAttributes: function (element, attributes) { | |
108 | var dom = element.dom, | |
109 | cache = element.cache, | |
110 | name, value; | |
111 | for (name in attributes) { | |
112 | value = attributes[name]; | |
113 | if (cache[name] !== value) { | |
114 | cache[name] = value; | |
115 | dom.setAttribute(name, value); | |
116 | } | |
117 | } | |
118 | }, | |
119 | ||
120 | /** | |
121 | * @private | |
122 | * Gets the next reference element under the SVG 'defs' tag. | |
123 | * @param {String} tagName The type of reference element. | |
124 | * @return {Ext.dom.Element} The reference element. | |
125 | */ | |
126 | getNextDef: function (tagName) { | |
127 | return this.getSvgElement(this.defElement, tagName, this.defPosition++); | |
128 | }, | |
129 | ||
130 | /** | |
131 | * @inheritdoc | |
132 | */ | |
133 | clearTransform: function () { | |
134 | var me = this; | |
135 | me.mainGroup.set({transform: me.matrix.toSvg()}); | |
136 | }, | |
137 | ||
138 | /** | |
139 | * @inheritdoc | |
140 | */ | |
141 | clear: function () { | |
142 | this.ctx.clear(); | |
143 | this.defPosition = 0; | |
144 | }, | |
145 | ||
146 | /** | |
147 | * @inheritdoc | |
148 | */ | |
149 | renderSprite: function (sprite) { | |
150 | var me = this, | |
151 | region = me.getRegion(), | |
152 | ctx = me.ctx; | |
153 | if (sprite.attr.hidden || sprite.attr.opacity === 0) { | |
154 | ctx.save(); | |
155 | ctx.restore(); | |
156 | return; | |
157 | } | |
158 | try { | |
159 | sprite.element = ctx.save(); | |
160 | sprite.preRender(this); | |
161 | sprite.useAttributes(ctx, region); | |
162 | if (false === sprite.render(this, ctx, [0, 0, region[2], region[3]])) { | |
163 | return false; | |
164 | } | |
165 | sprite.setDirty(false); | |
166 | } finally { | |
167 | ctx.restore(); | |
168 | } | |
169 | }, | |
170 | ||
171 | /** | |
172 | * Destroys the Canvas element and prepares it for Garbage Collection. | |
173 | */ | |
174 | destroy: function (path, matrix, band) { | |
175 | var me = this; | |
176 | me.ctx.destroy(); | |
177 | me.mainGroup.destroy(); | |
178 | delete me.mainGroup; | |
179 | delete me.ctx; | |
180 | me.callSuper(arguments); | |
181 | }, | |
182 | ||
183 | remove: function (sprite, destroySprite) { | |
184 | if (sprite && sprite.element) { | |
185 | //if sprite has an associated svg element remove it from the surface | |
186 | if (this.ctx) { | |
187 | this.ctx.removeElement(sprite.element); | |
188 | } else { | |
189 | sprite.element.destroy(); | |
190 | } | |
191 | sprite.element = null; | |
192 | } | |
193 | this.callSuper(arguments); | |
194 | } | |
195 | }); |