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