Skip to content
This repository has been archived by the owner on Apr 20, 2023. It is now read-only.

Commit

Permalink
Implement rendering of multiple box-shadows. Closes #4.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason Johnston committed May 23, 2010
1 parent 6b3b4dc commit 353e94c
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 95 deletions.
3 changes: 0 additions & 3 deletions documentation/properties.html
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,6 @@ <h2>box-shadow</h2>
rounding, particularly when the blur is very small (this should not be
more than a one-pixel difference).</p>

<p>PIE does not currently support multiple box shadows, but support is
planned in a future version (see <a href="http://github.com/lojjic/PIE/issues#issue/4">issue #4</a>.</p>

<p>PIE does not currently support the 'inset' keyword, but support is
planned in a future version (see <a href="http://github.com/lojjic/PIE/issues#issue/3">issue #3</a>.</p>

Expand Down
6 changes: 3 additions & 3 deletions sources/BackgroundAndBorderRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ PIE.BackgroundAndBorderRenderer = (function() {
if( color && color !== 'transparent' ) {
this.hideBackground();

shape = this.getShape( 'bgColor', 'fill', 1 );
shape = this.getShape( 'bgColor', 'fill', this.getBox(), 1 );
w = el.offsetWidth;
h = el.offsetHeight;
shape.stroked = false;
Expand Down Expand Up @@ -101,7 +101,7 @@ PIE.BackgroundAndBorderRenderer = (function() {
i = images.length;
while( i-- ) {
img = images[i];
shape = this.getShape( 'bgImage' + i, 'fill', 2 );
shape = this.getShape( 'bgImage' + i, 'fill', this.getBox(), 2 );

shape.stroked = false;
shape.fill.type = 'tile';
Expand Down Expand Up @@ -385,7 +385,7 @@ PIE.BackgroundAndBorderRenderer = (function() {
segments = this.getBorderSegments( 2 );
for( i = 0, len = segments.length; i < len; i++) {
seg = segments[i];
shape = this.getShape( 'borderPiece' + i, seg.stroke ? 'stroke' : 'fill', 3 );
shape = this.getShape( 'borderPiece' + i, seg.stroke ? 'stroke' : 'fill', this.getBox(), 3 );
shape.coordsize = w * 2 + ',' + h * 2;
shape.coordorigin = '1,1';
shape.path = seg.path;
Expand Down
151 changes: 66 additions & 85 deletions sources/BoxShadowRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,37 +27,65 @@ PIE.BoxShadowRenderer = (function() {

updateSize: function() {
if( this.isActive() ) {
var box = this.getBox(),
shape = box.firstChild,
s,
el = this.element,
bs = this.styleInfos.boxShadowInfo.getProps()[0],
spread = bs.spread.pixels( el ),
shrink = bs.blur.pixels( el ) > 0 ? 4 : 0,
var el = this.element,
shadowInfos = this.styleInfos.boxShadowInfo.getProps(),
i = shadowInfos.length,
w = el.offsetWidth,
h = el.offsetHeight;

/*if( bs.inset ) {
// if inset, the width does not include any element border
s = el.currentStyle;
w -= ( parseInt( s.borderLeftWidth, 10 ) || 0 ) + ( parseInt( s.borderRightWidth, 10 ) || 0 );
h -= ( parseInt( s.borderTopWidth, 10 ) || 0 ) + ( parseInt( s.borderBottomWidth, 10 ) || 0 );
// update width of inner element
s = box.firstChild.style;
s.width = w - spread * 2;
s.height = h - spread * 2;
} else {
}*/

s = shape.style;
s.width = w;
s.height = h;

// Blurred shadows end up slightly too wide; shrink them down
shape.coordsize = ( w * 2 + shrink ) + ',' + ( h * 2 + shrink );
shape.coordorigin = '1,1';
shape.path = this.getBoxPath( spread ? { t: -spread, r: -spread, b: -spread, l: -spread } : 0, 2 );
h = el.offsetHeight,
shadowInfo, box, shape, ss, xOff, yOff, spread, blur, shrink, halfBlur, filter, alpha;

while( i-- ) {
shadowInfo = shadowInfos[ i ];

box = this.getBox( shadowInfo.inset );
shape = this.getShape( 'shadow' + i, 'fill', box );
ss = shape.style;

xOff = shadowInfo.xOffset.pixels( el );
yOff = shadowInfo.yOffset.pixels( el );
spread = shadowInfo.spread.pixels( el ),
blur = shadowInfo.blur.pixels( el );

// Adjust the blur value so it's always an even number
halfBlur = Math.ceil( blur / 2 );
blur = halfBlur * 2;

// Apply blur filter to the shape. Applying the blur filter twice with
// half the pixel value gives a shadow nearly identical to other browsers.
if( blur > 0 ) {
filter = 'progid:DXImageTransform.Microsoft.blur(pixelRadius=' + halfBlur + ')';
ss.filter = filter + ' ' + filter;
}

// Position and size
ss.left = xOff - blur;
ss.top = yOff - blur;
ss.width = w;
ss.height = h;

// Color and opacity
shape.stroked = false;
shape.filled = true;
shape.fillcolor = shadowInfo.color.value( el );

alpha = shadowInfo.color.alpha();
if( alpha < 1 ) {
shape.fill.opacity = alpha;
}

// Blurred shadows end up slightly too wide; shrink them down
shrink = blur > 0 ? 4 : 0,
shape.coordsize = ( w * 2 + shrink ) + ',' + ( h * 2 + shrink );

shape.coordorigin = '1,1';
shape.path = this.getBoxPath( spread ? { t: -spread, r: -spread, b: -spread, l: -spread } : 0, 2 );

box.appendChild( shape );
}

// remove any previously-created border shapes which didn't get used above
i = shadowInfos.length;
while( this.deleteShape( 'shadow' + i++ ) ) {}
} else {
this.destroy();
}
Expand All @@ -68,62 +96,16 @@ PIE.BoxShadowRenderer = (function() {
this.updateSize();
},

getBox: function() {
var box = this._box, s, ss, cs, bs, xOff, yOff, blur, halfBlur, shape, el, filter, alpha;
getBox: function( isInset ) {
var zIndex = isInset ? this.insetZIndex : this.outsetZIndex,
box = this.parent.getLayer( zIndex );
if( !box ) {
el = this.element;
box = this._box = el.document.createElement( 'box-shadow' );
bs = this.styleInfos.boxShadowInfo.getProps()[0];
xOff = bs.xOffset.pixels( el );
yOff = bs.yOffset.pixels( el );
blur = bs.blur.pixels( el );

// Adjust the blur value so it's always an even number
halfBlur = Math.ceil( blur / 2 );
blur = halfBlur * 2;

s = box.style;
s.position = 'absolute';

shape = this.getShape( 'shadow', 'fill' );
ss = shape.style;
shape.stroked = false;

/*if( bs.inset ) {
cs = this.element.currentStyle;
s.overflow = 'hidden';
s.left = parseInt( cs.borderLeftWidth, 10 ) || 0;
s.top = parseInt( cs.borderTopWidth, 10 ) || 0;
s = shape.style;
s.position = 'absolute';
//TODO handle wider border if needed due to very large offsets or spread
s.left = xOff - 20 + spread - blur;
s.top = yOff - 20 + spread - blur;
s.border = '20px solid ' + bs.color.value( el );
} else {*/
s.left = xOff - blur;
s.top = yOff - blur;

shape.filled = true;
shape.fillcolor = bs.color.value( el );

alpha = bs.color.alpha();
if( alpha < 1 ) {
shape.fill.opacity = alpha;
}
/*}*/

// Apply blur filter to the outer or inner element. Applying the blur filter twice with
// half the pixel value gives a shadow nearly identical to other browsers.
if( blur > 0 ) {
filter = 'progid:DXImageTransform.Microsoft.blur(pixelRadius=' + halfBlur + ')';
ss.filter = filter + ' ' + filter;
}
box = this.element.document.createElement( ( isInset ? 'inset' : 'outset' ) + '-box-shadow' );
box.style.position = 'absolute';
this.parent.addLayer( zIndex, box );

this.parent.addLayer( bs.inset ? this.insetZIndex : this.outsetZIndex, box );
if( bs.inset ) {
// Temporarily hide inset shadows, until they are properly implemented
if( isInset ) {
box.style.display = 'none';
}
}
Expand All @@ -133,7 +115,6 @@ PIE.BoxShadowRenderer = (function() {
destroy: function() {
this.parent.removeLayer( this.insetZIndex );
this.parent.removeLayer( this.outsetZIndex );
delete this._box;
delete this._shapes;
}

Expand Down
7 changes: 3 additions & 4 deletions sources/RendererBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,14 @@ PIE.RendererBase = {
* Get a VML shape by name, creating it if necessary.
* @param {string} name A name identifying the element
* @param {string=} subElName If specified a subelement of the shape will be created with this tag name
* @param {Element} parent The parent element for the shape; will be ignored if 'group' is specified
* @param {number=} group If specified, an ordinal group for the shape. 1 or greater. Groups are rendered
* using container elements in the correct order, to get correct z stacking without z-index.
*/
getShape: function( name, subElName, group ) {
getShape: function( name, subElName, parent, group ) {
var shapes = this._shapes || ( this._shapes = {} ),
shape = shapes[ name ],
s, parent;
s;

if( !shape ) {
shape = shapes[ name ] = PIE.Util.createVmlElement( 'shape' );
Expand All @@ -100,8 +101,6 @@ PIE.RendererBase = {
this.addLayer( group, this.element.document.createElement( 'group' + group ) );
parent = this.getLayer( group );
}
} else {
parent = this.getBox();
}

parent.appendChild( shape );
Expand Down

0 comments on commit 353e94c

Please sign in to comment.