]> git.proxmox.com Git - extjs.git/blame - extjs/examples/kitchensink/classic/samples/view/draw/Protractor.js
add extjs 6.0.1 sources
[extjs.git] / extjs / examples / kitchensink / classic / samples / view / draw / Protractor.js
CommitLineData
6527f429
DM
1Ext.define('KitchenSink.view.draw.Protractor', {\r
2 // Typically, you'd want to extend the Composite sprite instead of using it directly.\r
3 extend: 'Ext.draw.sprite.Composite',\r
4 alias: 'sprite.protractor',\r
5\r
6 inheritableStatics: {\r
7 def: {\r
8 // And define your own attributes on the composite that abstract away\r
9 // the actual implementation.\r
10 processors: {\r
11 // The first four attributes (start and end point coordinates)\r
12 // is all we really need for this sprite to work.\r
13 fromX: 'number',\r
14 fromY: 'number',\r
15 toX: 'number',\r
16 toY: 'number',\r
17 // The rest of the attributes is just to allow customization.\r
18 baseLineLength: 'number',\r
19 arcRadius: 'number',\r
20 arrowLength: 'number',\r
21 arrowAngle: 'number'\r
22 },\r
23 // Changes to composite attributes will then trigger the recalculation of\r
24 // attributes of composite's children sprites.\r
25 // Here we define which composite's attributes should trigger such recalculation.\r
26 // In this case we use a single updater function called 'recalculate', but it's\r
27 // possible to specify and use different updaters for different attributes.\r
28 dirtyTriggers: {\r
29 fromX: 'recalculate',\r
30 fromY: 'recalculate',\r
31 toX: 'recalculate',\r
32 toY: 'recalculate',\r
33 baseLineLength: 'recalculate',\r
34 arcRadius: 'recalculate',\r
35 arrowLength: 'recalculate',\r
36 arrowAngle: 'recalculate'\r
37 },\r
38 // Default values of composite's attributes.\r
39 defaults: {\r
40 fromX: 0,\r
41 fromY: 0,\r
42 toX: 100,\r
43 toY: 100,\r
44 baseLineLength: 50,\r
45 arcRadius: 40,\r
46 arrowLength: 10,\r
47 arrowAngle: Math.PI / 8\r
48 },\r
49 updaters: {\r
50 // This updater function is called every time the attributes\r
51 // of the composite change, including animations.\r
52 // Inside this updater we calculate and set the values of the attributes\r
53 // of the children of the composite based on the values of the composite's\r
54 // attributes.\r
55 recalculate: function (attr) {\r
56 // Please see this ticket https://sencha.jira.com/browse/EXTJS-15521\r
57 // for a graphical representation of what's going on in this function.\r
58 var me = this,\r
59 fromX = attr.fromX,\r
60 fromY = attr.fromY,\r
61 toX = attr.toX,\r
62 toY = attr.toY,\r
63 dx = toX - fromX,\r
64 dy = toY - fromY,\r
65 PI = Math.PI,\r
66 radius = Math.sqrt(dx*dx + dy*dy);\r
67\r
68 if (dx === 0 || dy === 0) {\r
69 return;\r
70 }\r
71\r
72 var alpha = Math.atan2(dy, dx),\r
73 sin = Math.sin,\r
74 cos = Math.cos,\r
75 arcRadius = attr.arcRadius,\r
76 beta = PI - attr.arrowAngle,\r
77 x = attr.arrowLength * cos(beta),\r
78 y = attr.arrowLength * sin(beta),\r
79 // Coordinates of the arc arrow tip.\r
80 ax = arcRadius * cos(alpha) + fromX,\r
81 ay = arcRadius * sin(alpha) + fromY,\r
82 mat = Ext.draw.Matrix.fly([cos(alpha), sin(alpha), -sin(alpha), cos(alpha), toX, toY]),\r
83 angleArrowThreshold = Ext.draw.Draw.radian * me.getAngleArrowThreshold(),\r
84 isSmallAngle = alpha < angleArrowThreshold && alpha > -angleArrowThreshold,\r
85 angleTextRadius = arcRadius * 1.2,\r
86 isSmallRadius = radius < angleTextRadius,\r
87 radiusTextFlip, fontSize,\r
88 theta = 0;\r
89\r
90 if (alpha > 0) {\r
91 theta = alpha + PI / 2 - attr.arrowAngle / (arcRadius * 0.1);\r
92 } else if (alpha < 0) {\r
93 theta = alpha - PI / 2 + attr.arrowAngle / (arcRadius * 0.1);\r
94 }\r
95\r
96 me.createSprites();\r
97\r
98 me.baseLine.setAttributes({\r
99 fromX: fromX,\r
100 fromY: fromY,\r
101 toX: fromX + attr.baseLineLength,\r
102 toY: fromY,\r
103 hidden: isSmallRadius\r
104 });\r
105 me.radiusLine.setAttributes({\r
106 fromX: fromX,\r
107 fromY: fromY,\r
108 toX: toX,\r
109 toY: toY,\r
110 strokeStyle: attr.strokeStyle\r
111 });\r
112 me.radiusArrowLeft.setAttributes({\r
113 fromX: toX,\r
114 fromY: toY,\r
115 toX: mat.x(x, y),\r
116 toY: mat.y(x, y),\r
117 strokeStyle: attr.strokeStyle\r
118 });\r
119 me.radiusArrowRight.setAttributes({\r
120 fromX: toX,\r
121 fromY: toY,\r
122 toX: mat.x(x, -y),\r
123 toY: mat.y(x, -y),\r
124 strokeStyle: attr.strokeStyle\r
125 });\r
126\r
127 mat = Ext.draw.Matrix.fly([cos(theta), sin(theta), -sin(theta), cos(theta), ax, ay]);\r
128\r
129 me.angleLine.setAttributes({\r
130 startAngle: 0,\r
131 endAngle: alpha,\r
132 cx: fromX,\r
133 cy: fromY,\r
134 r: arcRadius,\r
135 anticlockwise: alpha < 0,\r
136 hidden: isSmallRadius\r
137 });\r
138 me.angleArrowLeft.setAttributes({\r
139 fromX: ax,\r
140 fromY: ay,\r
141 toX: mat.x(x, y),\r
142 toY: mat.y(x, y),\r
143 hidden: isSmallAngle || isSmallRadius\r
144 });\r
145 me.angleArrowRight.setAttributes({\r
146 fromX: ax,\r
147 fromY: ay,\r
148 toX: mat.x(x, -y),\r
149 toY: mat.y(x, -y),\r
150 hidden: isSmallAngle || isSmallRadius\r
151 });\r
152 me.angleText.setAttributes({\r
153 x: angleTextRadius * cos(alpha / 2) + fromX,\r
154 y: angleTextRadius * sin(alpha / 2) + fromY,\r
155 text: me.getAngleText() + ': ' + (alpha * 180 / PI).toFixed(me.getPrecision()) + '°',\r
156 hidden: isSmallRadius\r
157 });\r
158 radiusTextFlip = ((alpha > -0.5 * PI && alpha < 0.5 * PI) || (alpha > 1.5 * PI && alpha < 2 * PI)) ? 1 : -1;\r
159 fontSize = parseInt(me.radiusText.attr.fontSize, 10);\r
160 x = 0.5 * radius * cos(alpha) + fromX + radiusTextFlip * fontSize * sin(alpha);\r
161 y = 0.5 * radius * sin(alpha) + fromY - radiusTextFlip * fontSize * cos(alpha);\r
162 me.radiusText.setAttributes({\r
163 x: x,\r
164 y: y,\r
165 rotationRads: alpha,\r
166 rotationRads: radiusTextFlip === 1 ? alpha : alpha - PI,\r
167 rotationCenterX: x,\r
168 rotationCenterY: y,\r
169 text: me.getRadiusText() + ': ' + radius.toFixed(me.getPrecision()),\r
170 hidden: isSmallRadius\r
171 });\r
172 }\r
173 }\r
174 }\r
175 },\r
176\r
177 // Additional configuration options that are meant to be used once during setup time.\r
178 // These need not be attributes, because we don't need them to animate\r
179 // or trigger changes in other attributes.\r
180 config: {\r
181 radiusText: 'length',\r
182 angleText: 'angle',\r
183 precision: 1,\r
184 angleArrowThreshold: 15\r
185 },\r
186\r
187 // The 'recalculate' updater will be called at construction time.\r
188 // But the children sprites have not been created and added to the composite yet.\r
189 // We can't add children to the composite before the parent constructor call,\r
190 // because the composite hasn't been initialized yet.\r
191 // And adding them after construction is too late, because the 'recalculate'\r
192 // updater needs them.\r
193 // So we define the 'createSprites' function that is called inside the 'recalculate'\r
194 // updater before the sprites are used.\r
195 createSprites: function () {\r
196 var me = this;\r
197\r
198 // Only create sprites if they haven't been created yet.\r
199 if (!me.baseLine) {\r
200 me.baseLine = me.add({\r
201 type: 'line',\r
202 lineDash: [2, 2]\r
203 });\r
204 me.radiusLine = me.add({\r
205 type: 'line'\r
206 });\r
207 // Left line of the radius arrow.\r
208 me.radiusArrowLeft = me.add({\r
209 type: 'line'\r
210 });\r
211 // Right line of the radius arrow.\r
212 me.radiusArrowRight = me.add({\r
213 type: 'line'\r
214 });\r
215 me.angleLine = me.add({\r
216 type: 'arc',\r
217 strokeStyle: 'black',\r
218 lineDash: [2, 2]\r
219 });\r
220 // Left line of the angle arrow.\r
221 me.angleArrowLeft = me.add({\r
222 type: 'line',\r
223 lineDash: [2, 2]\r
224 });\r
225 // Right line of the angle arrow.\r
226 me.angleArrowRight = me.add({\r
227 type: 'line',\r
228 lineDash: [2, 2]\r
229 });\r
230 me.radiusText = me.add({\r
231 type: 'text',\r
232 textAlign: 'center',\r
233 textBaseline: 'middle',\r
234 font: '12px'\r
235 });\r
236 me.angleText = me.add({\r
237 type: 'text',\r
238 textBaseline: 'middle',\r
239 font: '12px'\r
240 });\r
241 }\r
242 }\r
243\r
244});