source: Dev/branches/rest-dojo-ui/client/dojox/drawing/annotations/BoxShadow.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 8.9 KB
Line 
1dojo.provide("dojox.drawing.annotations.BoxShadow");
2
3dojox.drawing.annotations.BoxShadow = dojox.drawing.util.oo.declare(
4        // summary:
5        //              Creates a box shadow under solid objects. Can change the
6        //              shadow direction, color, size, and intensity. Can center
7        //              the shadow and make it a Glow.
8        // description:
9        //              This is a psuedo shadow, created by duplicating the
10        //              original stencil and increasing the line weight while
11        //              reducing the opacity. Therefore it will not work with
12        //              text. Also won't look very good if the Stencil has no
13        //              fill or is transparent. Can't do knockouts or inner
14        //              shadows. Currently can't do paths - while doable, it
15        //              will most likely choke IE into certain death.
16        //
17        function(/*Object*/options){
18                this.stencil = options.stencil;
19                this.util = options.stencil.util;
20                this.mouse = options.stencil.mouse;
21                this.style = options.stencil.style;
22               
23                var shadowDefaults = {
24                        // summary:
25                        //              When passing a shadow object into a stencil, that shadow
26                        //              object will be mixed in with these defaults.
27                        //
28                        // size: Number, mult: Number
29                        //              These two props work together. Both affect the size and quality
30                        //              of the shadow. size affects the actual size and mult affects the
31                        //              lineWidths that overlap to make the shadow. Generally you want a
32                        //              bigger 'size' than 'mult'. The defaults are good for a shadow, but
33                        //              you will want to increase them when making a glow.
34                        //      TODO: Make this more clear or use other properties.
35                        size:6,
36                        mult:4,
37                        // alpha: Float
38                        //              Affects the alpha of the shadow. Because this is multiple shapes
39                        //              overlapped, you want much less than you may think. .1 is pretty
40                        //              dark and . is black. Higher numbers also give a sharper edge.
41                        alpha:.05,
42                        //      place: String
43                        //              Tells the position of the shadow:
44                        //                      B: bottom
45                        //                      T: top
46                        //                      L: left
47                        //                      R: right
48                        //                      C: center, or a glow
49                        //              Can be used in combinations such as BR, BL, L, T, etc. 'C' should
50                        //              be used by itself.
51                        place:"BR",
52                        //      color: String
53                        //              The color of the shadow or glow.
54                        color:"#646464"
55                }
56               
57                delete options.stencil;
58                this.options = dojo.mixin(shadowDefaults, options);
59                this.options.color = new dojo.Color(this.options.color)
60                this.options.color.a = this.options.alpha;
61                switch(this.stencil.shortType){
62                        case "image":
63                        case "rect":
64                                this.method = "createForRect"; break;
65                        case "ellipse":
66                                this.method = "createForEllipse"; break;
67                        case "line":
68                                this.method = "createForLine"; break;
69                        case "path":
70                                this.method = "createForPath"; break;
71                                //      path is a bit of a hassle. Plus I think in IE it would be
72                                //slower than the political process. Maybe TODO.
73                        case "vector":
74                                this.method = "createForZArrow"; break;
75                        default:
76                                console.warn("A shadow cannot be made for Stencil type ", this.stencil.type);
77                }
78               
79                if(this.method){
80                        this.render();
81                        this.stencil.connectMult([
82                                [this.stencil, "onTransform", this, "onTransform"],
83                                this.method=="createForZArrow"?[this.stencil, "render", this, "render"]:[this.stencil, "render", this, "onRender"],
84                                [this.stencil, "onDelete", this, "destroy"]
85                        ]);
86                }
87        },
88        {
89                showing:true,
90                render: function(){
91                        if(this.container){
92                                this.container.removeShape();
93                        }
94                        this.container = this.stencil.container.createGroup();
95                        this.container.moveToBack();
96                       
97                        var o = this.options,
98                                size = o.size,
99                                mult = o.mult,
100                                d = this.method == "createForPath"
101                                        ? this.stencil.points
102                                        : this.stencil.data,
103                                r = d.r || 1,
104                                p = o.place,
105                                c = o.color;
106                               
107                        this[this.method](o, size, mult, d, r, p, c);
108                },
109               
110                hide: function(){
111                        if(this.showing){
112                                this.showing = false;
113                                this.container.removeShape();
114                        }
115                },
116               
117                show: function(){
118                        if(!this.showing){
119                                this.showing = true;
120                                this.stencil.container.add(this.container);
121                        }
122                },
123               
124                createForPath: function(o, size, mult, pts, r, p, c){
125                        var sh = size * mult / 4,
126                                shy = /B/.test(p) ? sh : /T/.test(p) ? sh*-1 : 0,
127                                shx = /R/.test(p) ? sh : /L/.test(p) ? sh*-1 : 0;
128                       
129                        var closePath = true;
130                       
131                        for(var i=1;i<=size;i++){
132                                var lineWidth = i * mult;
133                                //var rect = this.container.createLine({x1:d.x1+shx, y1:d.y1+shy, x2:d.x2+shx, y2:d.y2+shy})
134                                //      .setStroke({width:lineWidth, color:c, cap:"round"})
135                       
136                                if(dojox.gfx.renderer=="svg"){
137                                        var strAr = [];
138                                        dojo.forEach(pts, function(o, i){
139                                                if(i==0){
140                                                        strAr.push("M " + (o.x+shx) +" "+ (o.y+shy));
141                                                }else{
142                                                        var cmd = o.t || "L ";
143                                                        strAr.push(cmd + (o.x+shx) +" "+ (o.y+shy)); // Z + undefined works here
144                                                }
145                                        }, this);
146                                        if(closePath){
147                                                strAr.push("Z");
148                                        }
149                                        this.container.createPath(strAr.join(", ")).setStroke({width:lineWidth, color:c, cap:"round"})
150                                       
151                                }else{
152                                        // Leaving this code for VML. It seems slightly faster but times vary.
153                                        var pth = this.container.createPath({}).setStroke({width:lineWidth, color:c, cap:"round"})
154                                       
155                                        dojo.forEach(this.points, function(o, i){
156                                                if(i==0 || o.t=="M"){
157                                                        pth.moveTo(o.x+shx, o.y+shy);
158                                                }else if(o.t=="Z"){
159                                                        closePath && pth.closePath();
160                                                }else{
161                                                        pth.lineTo(o.x+shx, o.y+shy);
162                                                }
163                                        }, this);
164                                       
165                                        closePath && pth.closePath();
166                                }
167                       
168                       
169                        }
170                },
171               
172                createForLine: function(o, size, mult, d, r, p, c){
173                       
174                        var sh = size * mult / 4,
175                                shy = /B/.test(p) ? sh : /T/.test(p) ? sh*-1 : 0,
176                                shx = /R/.test(p) ? sh : /L/.test(p) ? sh*-1 : 0;
177                        for(var i=1;i<=size;i++){
178                                var lineWidth = i * mult;
179                                this.container.createLine({x1:d.x1+shx, y1:d.y1+shy, x2:d.x2+shx, y2:d.y2+shy})
180                                        .setStroke({width:lineWidth, color:c, cap:"round"})
181                        }
182                },
183                createForEllipse: function(o, size, mult, d, r, p, c){
184               
185                        var sh = size * mult / 8,
186                                shy = /B/.test(p) ? sh : /T/.test(p) ? sh*-1 : 0,
187                                shx = /R/.test(p) ? sh*.8 : /L/.test(p) ? sh*-.8 : 0;
188                       
189                        for(var i=1;i<=size;i++){
190                                var lineWidth = i * mult;
191                                this.container.createEllipse({cx:d.cx+shx, cy:d.cy+shy, rx:d.rx-sh, ry:d.ry-sh, r:r})
192                                        .setStroke({width:lineWidth, color:c})
193                        }
194                },
195               
196                createForRect: function(o, size, mult, d, r, p, c){
197                       
198                        var sh = size * mult / 2,
199                                shy = /B/.test(p) ? sh : /T/.test(p) ? 0 : sh /2,
200                                shx = /R/.test(p) ? sh : /L/.test(p) ? 0 : sh /2;
201                       
202                        for(var i=1;i<=size;i++){
203                                var lineWidth = i * mult;
204                                this.container.createRect({x:d.x+shx, y:d.y+shy, width:d.width-sh, height:d.height-sh, r:r})
205                                        .setStroke({width:lineWidth, color:c})
206                        }
207                },
208               
209                arrowPoints: function(){
210                        // summary:
211                        //      Creates data used to draw arrow head.
212                        //
213                        var d = this.stencil.data;
214                        var radius = this.stencil.getRadius();
215                        var angle = this.style.zAngle + 30;
216
217                        var pt = this.util.pointOnCircle(d.x1, d.y1, radius*.75, angle);
218                       
219                        var obj = {
220                                start:{
221                                        x:d.x1,
222                                        y:d.y1
223                                },
224                                x:pt.x,
225                                y:pt.y
226                        }
227                        var angle = this.util.angle(obj);
228                        var lineLength = this.util.length(obj);
229                        var al = this.style.arrows.length;
230                        var aw = this.style.arrows.width/3;
231                        if(lineLength<al){
232                                al = lineLength/2;
233                        }
234
235                        var p1 = this.util.pointOnCircle(obj.x, obj.y, -al, angle-aw);
236                        var p2 = this.util.pointOnCircle(obj.x, obj.y, -al, angle+aw);
237                        return [
238                                {x:obj.x, y:obj.y},
239                                p1,
240                                p2
241                        ];
242                },
243               
244                createForZArrow: function(o, size, mult, pts, r, p, c){
245                        if(this.stencil.data.cosphi<1 || !this.stencil.points[0]){ return; }
246                        var sh = size * mult / 4,
247                                shy = /B/.test(p) ? sh : /T/.test(p) ? sh*-1 : 0,
248                                shx = /R/.test(p) ? sh : /L/.test(p) ? sh*-1 : 0;
249                        var closePath = true;
250                        for(var i=1;i<=size;i++){
251                                var lineWidth = i * mult;
252                                pts = this.arrowPoints();
253                                if(!pts){ return; }
254                                if(dojox.gfx.renderer=="svg"){
255                                       
256                                        var strAr = [];
257                                        dojo.forEach(pts, function(o, i){
258                                                if(i==0){
259                                                        strAr.push("M " + (o.x+shx) +" "+ (o.y+shy));
260                                                }else{
261                                                        var cmd = o.t || "L ";
262                                                        strAr.push(cmd + (o.x+shx) +" "+ (o.y+shy)); // Z + undefined works here
263                                                }
264                                        }, this);
265                                        if(closePath){
266                                                strAr.push("Z");
267                                        }
268
269                                        this.container.createPath(strAr.join(", ")).setStroke({width:lineWidth, color:c, cap:"round"}).setFill(c);
270                                       
271                                }else{
272                                        // Leaving this code for VML. It seems slightly faster but times vary.
273                                        var pth = this.container.createPath({}).setStroke({width:lineWidth, color:c, cap:"round"})
274                                       
275                                        dojo.forEach(pts, function(o, i){
276                                                if(i==0 || o.t=="M"){
277                                                        pth.moveTo(o.x+shx, o.y+shy);
278                                                }else if(o.t=="Z"){
279                                                        closePath && pth.closePath();
280                                                }else{
281                                                        pth.lineTo(o.x+shx, o.y+shy);
282                                                }
283                                        }, this);
284                                       
285                                        closePath && pth.closePath();
286                                }
287                                var sp = this.stencil.points;
288                                this.container.createLine({x1:sp[0].x, y1:sp[0].y, x2:pts[0].x, y2:pts[0].y})
289                                        .setStroke({width:lineWidth, color:c, cap:"round"});
290                       
291                        }
292                },
293               
294               
295                onTransform: function(){
296                        this.render();
297                },
298                onRender: function(){
299                        this.container.moveToBack();
300                },
301                destroy: function(){
302                        if(this.container){
303                                this.container.removeShape();
304                        }
305                }
306        }
307);
Note: See TracBrowser for help on using the repository browser.