DHTML Lab: Cross-Browser Visibility Transitions; Transition 0 (Box-In) | WebReference

DHTML Lab: Cross-Browser Visibility Transitions; Transition 0 (Box-In)


Logo

Cross-Browser Visibility Transitions
transition 0: box-in



Element
Visibility
Transitions
 hidden-to-visible
IE4 behavior:
  as described
NS4 behavior:
Boldsame as IE4
BItalicsimilar to IE4
Italicother trans substituted
Box in 0
Box out 1
Circle in 2
Circle out 3
Wipe up 4
Wipe down 5
Wipe right 6
Wipe left 7
Vertical blinds 8
Horizontal blinds 9
Checkerboard across10
Checkerboard down11
Random dissolve12
Split vertical in13
Split vertical out14
Split horizontal in15
Split horizontal out16
Strips left down17
Strips left up18
Strips right down19
Strips right up20
Random bars horizontal21
Random bars vertical22
Random23

Try the first example in the left column. The Box-In transition, you notice, is a gradual clipping of all four sides, making the element shrink into its own center.

The Wrong Way

Our first inclination is to include the following statements in doTransNS():

switch (transNo) {
    case 0:
        incrementW = halfW/visits;
        incrementH = halfH/visits;
        whichEl.transFunct = zero;
        break;
}
transTimer=setInterval("whichEl.transFunct()",intval);

Here, we have divided the width of half of the element by the number of visits (function calls). This gives us the pixel increment by which to clip the left and the right edges of the element on each function call. We do the same for the height, and then call the function.

function zero() {
    this.clip.left += incrementW;
    this.clip.right -= incrementW;
    this.clip.top += incrementH;
    this.clip.bottom -= incrementH;
    if (elBad.clip.height <= 0
            && elBad.clip.width <= 0) {
        clearInterval(transTimer);
        this.hideIt();
    }
}

In function zero(), we clip the four sides by the appropriate pixel increments. If both the clip width and the clip height become 0 or less, the transition is complete, so we clear the repeated function calls with clearInterval() and restore the element to its original size and hide it with hideIt().

This code results in the second example in the left column. If you are using Navigator 4, try it. What is the difference from the first example? The box does not reduce in size equally on all sides, as it does in Explorer. This is due to Navigator rounding numbers to integers, to use as pixel increments.

Let's make up for this behavior, by embellishing the code to account for (almost) every pixel!

The Long-Winded Correct Way

First we get a temporary horizontal increment (incW) by dividing halfW by visits, as above. We then check to see if incW is greater than 1 pixel. If it is, we take the full integer part of it (left of the decimal point), and assign it to incrementW using parseInt(). If incW is less than 1, we assign 0 to incrementW.

case 0:
    incW = halfW/visits;
    incrementW = (incW >= 1) ? parseInt(incW) : 0;
    xtraPixW = Math.round((incW - incrementW) * visits);
    incH = halfH/visits;
    incrementH = (incH >= 1) ? parseInt(incH) : 0;
    xtraPixH = Math.round((incH - incrementH) * visits);
    whichEl.transFunct = zero;
    break;

Next, we obtain the non-integer part of incW (right of the decimal point), by subtracting the integer part (incrementW) from it (incW - incrementW). If we multiply this fraction result by the number of visits ((incW - incrementW) * visits), we get the total number of pixels that will be stray and lost if we continue our routine as in the "wrong way" above. This number is then rounded to the closest integer using the round() method of JavaScript's built-in Math object: (Math.round((incW - incrementW) * visits)). Finally, the result (xtraPixW), represents the total number of extra pixels that we will need to account for to have the transition end in a point in the center.

We perform the same calculations for the element height before calling the zero() function.

zero()

The complete zero() function looks like this:

function zero() {
    if (xtraPixW > 0) {
        if (xtraPixW <= visits) {
            if (alternateW) {
                this.clip.left++;
                this.clip.right--;
                xtraPixW--;
            }
            alternateW = !alternateW;
        }    
        else {
            this.clip.left++;
            this.clip.right--;
            xtraPixW--;
        }
    }
    this.clip.left += incrementW;
    this.clip.right -= incrementW;
    if (xtraPixH > 0) {
        if (xtraPixH <= visits) {
            if (alternateH) {
                this.clip.top++;
                this.clip.bottom--;
                xtraPixH--;
            }
            alternateH = !alternateH;
        }    
        else {
            this.clip.top++;
            this.clip.bottom--;
            xtraPixH--;
        }
    }
    this.clip.top += incrementH;
    this.clip.bottom -= incrementH;
    visits--;
    if (this.clip.height <= 0
            && this.clip.width <= 0) {
        clearInterval(transTimer);
        this.hideIt();
    }
}

The major problem in developing zero() is the use of the extra pixels. xtrapixW and xtraPixH will always be less than the visits, by definition. We need a smoother transition closer to the end of the transition, when the element is smaller. The way to achieve this is:

  1. Clip the element by the integer increments (incrementW/incrementH) every time zero() is called, as normal.
  2. If the extra pixels are less than the visits, clip by one extra pixel every second time zero() is called. Track the extra pixels used and the visits to date.
  3. Eventually, the extra pixels still-to-use will equal the visits-still-to-come. From then on, until the end of the transition, use one of the extra pixels per visit.

The above logic leads us to this routine for horizontal clipping:

    if (xtraPixW > 0) {
        if (xtraPixW <= visits) {
            if (alternateW) {
                this.clip.left++;
                this.clip.right--;
                xtraPixW--;
            }
            alternateW = !alternateW;
        }    
        else {
            this.clip.left++;
            this.clip.right--;
            xtraPixW--;
        }
    }
    this.clip.left += incrementW;
    this.clip.right -= incrementW;

If we have extra pixels to account for ( if (xtraPixW > 0) ), we compare the extra pixels to the visit count. If the extra pixel count is less than or equal to the visits ( if (xtraPixW <= visits) ), we check the value of alternateW, the Boolean declared earlier. If alternateW is true, then we increment the left clip by one pixel ( this.clip.left++ ) and decrement the right clip by one pixel ( this.clip.right-- ). We then decrement the extra pixel counter ( xtraPixW-- ).

The value of alternateW is then toggled, regardless of whether it was originally true or false. This ensures that an extra pixel will be used every second visit, that is, when alternateW is true.

If the extra pixels are not less than the visits, then zero() clips the left and right sides by one, and decrements xtraPixW.

Finally, the left and right sides are clipped using incrementW.

The height is clipped in the same way:

    if (xtraPixH > 0) {
        if (xtraPixH <= visits) {
            if (alternateH) {
                this.clip.top++;
                this.clip.bottom--;
                xtraPixH--;
            }
            alternateH = !alternateH;
        }    
        else {
            this.clip.top++;
            this.clip.bottom--;
            xtraPixH--;
        }
    }
    this.clip.top += incrementH;
    this.clip.bottom -= incrementH;

On every visit to zero(), once the sides have been clipped, visits is decremented, and the size of the element is checked to determine whether the function calls should continue or be cancelled.

    visits--;
    if (this.clip.height <= 0
            && this.clip.width <= 0) {
        clearInterval(transTimer);
        this.hideIt();
    }

We now have a much smoother clipping routine that ends the box-in transition in the center of the element. Next, we'll reverse the effect for the box-out transition.


Produced by Peter Belesis and

All Rights Reserved. Legal Notices.
Created: Apr. 28, 1998
Revised: Apr. 28, 1998

URL: http://www.webreference.com/dhtml/column19/transBoxIn.html