]> git.proxmox.com Git - extjs.git/blame - extjs/packages/charts/src/draw/engine/Svg.js
add extjs 6.0.1 sources
[extjs.git] / extjs / packages / charts / src / draw / engine / Svg.js
CommitLineData
6527f429
DM
1/**\r
2 * @class Ext.draw.engine.Svg\r
3 * @extends Ext.draw.Surface\r
4 *\r
5 * SVG engine.\r
6 */\r
7Ext.define('Ext.draw.engine.Svg', {\r
8 extend: 'Ext.draw.Surface',\r
9 requires: ['Ext.draw.engine.SvgContext'],\r
10\r
11 statics: {\r
12 BBoxTextCache: {}\r
13 },\r
14\r
15 config: {\r
16 /**\r
17 * Nothing needs to be done in high precision mode.\r
18 */\r
19 highPrecision: false\r
20 },\r
21\r
22 getElementConfig: function () {\r
23 //TODO:ps In the Ext world, use renderTpl to create the children\r
24 return {\r
25 reference: 'element',\r
26 style: {\r
27 position: 'absolute'\r
28 },\r
29 children: [\r
30 {\r
31 reference: 'innerElement',\r
32 style: {\r
33 width: '100%',\r
34 height: '100%',\r
35 position: 'relative'\r
36 },\r
37 children: [\r
38 {\r
39 tag: 'svg',\r
40 reference: 'svgElement',\r
41 namespace: "http://www.w3.org/2000/svg",\r
42 width: '100%',\r
43 height: '100%',\r
44 version: 1.1\r
45 }\r
46 ]\r
47 }\r
48 ]\r
49 };\r
50 },\r
51\r
52 constructor: function (config) {\r
53 var me = this;\r
54 me.callParent([config]);\r
55 me.mainGroup = me.createSvgNode("g");\r
56 me.defElement = me.createSvgNode("defs");\r
57 // me.svgElement is assigned in element creation of Ext.Component.\r
58 me.svgElement.appendChild(me.mainGroup);\r
59 me.svgElement.appendChild(me.defElement);\r
60 me.ctx = new Ext.draw.engine.SvgContext(me);\r
61 },\r
62\r
63 /**\r
64 * Creates a DOM element under the SVG namespace of the given type.\r
65 * @param {String} type The type of the SVG DOM element.\r
66 * @return {*} The created element.\r
67 */\r
68 createSvgNode: function (type) {\r
69 var node = document.createElementNS("http://www.w3.org/2000/svg", type);\r
70 return Ext.get(node);\r
71 },\r
72\r
73 /**\r
74 * @private\r
75 * Returns the SVG DOM element at the given position. If it does not already exist or is a different element tag\r
76 * it will be created and inserted into the DOM.\r
77 * @param {Ext.dom.Element} group The parent DOM element.\r
78 * @param {String} tag The SVG element tag.\r
79 * @param {Number} position The position of the element in the DOM.\r
80 * @return {Ext.dom.Element} The SVG element.\r
81 */\r
82 getSvgElement: function (group, tag, position) {\r
83 var element;\r
84 if (group.dom.childNodes.length > position) {\r
85 element = group.dom.childNodes[position];\r
86 if (element.tagName === tag) {\r
87 return Ext.get(element);\r
88 } else {\r
89 Ext.destroy(element);\r
90 }\r
91 }\r
92\r
93 element = Ext.get(this.createSvgNode(tag));\r
94 if (position === 0) {\r
95 group.insertFirst(element);\r
96 } else {\r
97 element.insertAfter(Ext.fly(group.dom.childNodes[position - 1]));\r
98 }\r
99 element.cache = {};\r
100 return element;\r
101 },\r
102\r
103 /**\r
104 * @private\r
105 * Applies attributes to the given element.\r
106 * @param {Ext.dom.Element} element The DOM element to be applied.\r
107 * @param {Object} attributes The attributes to apply to the element.\r
108 */\r
109 setElementAttributes: function (element, attributes) {\r
110 var dom = element.dom,\r
111 cache = element.cache,\r
112 name, value;\r
113 for (name in attributes) {\r
114 value = attributes[name];\r
115 if (cache[name] !== value) {\r
116 cache[name] = value;\r
117 dom.setAttribute(name, value);\r
118 }\r
119 }\r
120 },\r
121\r
122 /**\r
123 * @private\r
124 * Gets the next reference element under the SVG 'defs' tag.\r
125 * @param {String} tagName The type of reference element.\r
126 * @return {Ext.dom.Element} The reference element.\r
127 */\r
128 getNextDef: function (tagName) {\r
129 return this.getSvgElement(this.defElement, tagName, this.defPosition++);\r
130 },\r
131\r
132 /**\r
133 * @inheritdoc\r
134 */\r
135 clearTransform: function () {\r
136 var me = this;\r
137 me.mainGroup.set({transform: me.matrix.toSvg()});\r
138 },\r
139\r
140 /**\r
141 * @inheritdoc\r
142 */\r
143 clear: function () {\r
144 this.ctx.clear();\r
145 this.defPosition = 0;\r
146 },\r
147\r
148 /**\r
149 * @inheritdoc\r
150 */\r
151 renderSprite: function (sprite) {\r
152 var me = this,\r
153 rect = me.getRect(),\r
154 ctx = me.ctx;\r
155\r
156 if (sprite.attr.hidden || sprite.attr.globalAlpha === 0) {\r
157 ctx.save();\r
158 ctx.restore();\r
159 return;\r
160 }\r
161\r
162 sprite.element = ctx.save();\r
163 sprite.preRender(this);\r
164 sprite.useAttributes(ctx, rect);\r
165 if (false === sprite.render(this, ctx, [0, 0, rect[2], rect[3]])) {\r
166 return false;\r
167 }\r
168 sprite.setDirty(false);\r
169 ctx.restore();\r
170 },\r
171\r
172 flatten: function (size, surfaces) {\r
173 var svg = '<?xml version="1.0" standalone="yes"?>',\r
174 className = Ext.getClassName(this),\r
175 surface, rect, i;\r
176\r
177 svg += '<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg"' +\r
178 ' width="' + size.width + '"' +\r
179 ' height="' + size.height + '">';\r
180\r
181 for (i = 0; i < surfaces.length; i++) {\r
182 surface = surfaces[i];\r
183 if (Ext.getClassName(surface) !== className) {\r
184 continue;\r
185 }\r
186 rect = surface.getRect();\r
187 svg += '<g transform="translate(' + rect[0] + ',' + rect[1] + ')">';\r
188 svg += this.serializeNode(surface.svgElement.dom);\r
189 svg += '</g>';\r
190 }\r
191 svg += '</svg>';\r
192 return {\r
193 data: 'data:image/svg+xml;utf8,' + encodeURIComponent(svg),\r
194 type: 'svg'\r
195 };\r
196 },\r
197\r
198 /**\r
199 * @private\r
200 * Serializes an SVG DOM element and its children recursively into a string.\r
201 * @param {Object} node DOM element to serialize.\r
202 * @return {String}\r
203 */\r
204 serializeNode: function (node) {\r
205 var result = '',\r
206 i, n, attr, child;\r
207 if (node.nodeType === document.TEXT_NODE) {\r
208 return node.nodeValue;\r
209 }\r
210 result += '<' + node.nodeName;\r
211 if (node.attributes.length) {\r
212 for (i = 0, n = node.attributes.length; i < n; i++) {\r
213 attr = node.attributes[i];\r
214 result += ' ' + attr.name + '="' + attr.value + '"';\r
215 }\r
216 }\r
217 result += '>';\r
218 if (node.childNodes && node.childNodes.length) {\r
219 for (i = 0, n = node.childNodes.length; i < n; i++) {\r
220 child = node.childNodes[i];\r
221 result += this.serializeNode(child);\r
222 }\r
223 }\r
224 result += '</' + node.nodeName + '>';\r
225 return result;\r
226 },\r
227\r
228 /**\r
229 * Destroys the Canvas element and prepares it for Garbage Collection.\r
230 */\r
231 destroy: function () {\r
232 var me = this;\r
233 me.ctx.destroy();\r
234 me.mainGroup.destroy();\r
235 delete me.mainGroup;\r
236 delete me.ctx;\r
237 me.callParent();\r
238 },\r
239\r
240 remove: function (sprite, destroySprite) {\r
241 if (sprite && sprite.element) {\r
242 // If sprite has an associated SVG element, remove it from the surface.\r
243 if (this.ctx) {\r
244 this.ctx.removeElement(sprite.element);\r
245 } else {\r
246 sprite.element.destroy();\r
247 }\r
248 sprite.element = null;\r
249 }\r
250 this.callParent(arguments);\r
251 }\r
252});\r