How to make rooftext effect and valley text effect in HTML5 (or Fabric.js)

Here is a modified version of the original code (the provided code in question has changed values compared to my original code.. .-) ) which can produce all these shapes just by playing around with the parameters:

Valley

Roof

Roof inversed

Bridge

The roof is not super but I’ll leave it to you to add scaling support as this is meant as an example.

ONLINE DEMO HERE

Initialization:

var ctx = demo.getContext('2d'), /// context
    font="64px impact",        /// font
    w = demo.width,              /// cache canvas width and height
    h = demo.height,
    curve,                       /// radius
    offsetY,                     /// offset for text
    bottom,                      /// bottom of text
    textHeight,                  /// text height (region of text)
    isTri = false,               /// is triangle shaped (roof)
    dltY,                        /// delta for triangle
    angleSteps = 180 / w,        /// angle steps for curved text
    i = w,                       /// "x" backwards
    y,                           /// top of text

    /// offscreen canvas that holds original text
    os = document.createElement('canvas'),
    octx = os.getContext('2d');

os.width = w;
os.height = h;

/// set font on off-screen canvas where we draw it
octx.font = font;
octx.textBaseline="top";
octx.textAlign = 'center';

Main function:

/// render
function renderBridgeText() {

    /// demo stuff snipped (see link)

    /// clear canvases    
    octx.clearRect(0, 0, w, h);
    ctx.clearRect(0, 0, w, h);

    /// draw text (text may change)
    octx.fillText(iText.value.toUpperCase(), w * 0.5, 0);

    /// slide and dice
    dltY = curve / textHeight;  /// calculate delta for roof/triangle
    y = 0;                      /// reset y in case we do roof
    i = w;                      /// init "x"

    while (i--) {

        if (isTri) {
            /// bounce delta value mid-way for triangle
            y += dltY;
            if (i === (w * 0.5)|0) dltY = -dltY;

        } else {
            /// calc length based on radius+angle for curve
            y = bottom - curve * Math.sin(i * angleSteps * Math.PI / 180);
        }

        /// draw a slice
        ctx.drawImage(os, i, 0, 1, textHeight,
                          i, h * 0.5 - offsetY / textHeight * y, 1, y);
    }
}

Leave a Comment