Bridge Text Effect in HTML5 Canvas

后端 未结 1 1753
粉色の甜心
粉色の甜心 2020-12-20 09:45

Want to create a Bridge Text Effect like below, i tried using arctext but it doesnt help. I tried to google id but it doesnt understand Bridge text Shapes.

相关标签:
1条回答
  • 2020-12-20 10:29

    Displacement

    There are at least two ways you can achieve a curved text effect - both share the same principle of displacement of pixels (moving them out of position relative to their real position), it's just a matter of which method we use to do this.

    In the following demo I will use simple slicing using the internal drawImage method. Optional we could have iterated the pixel buffer and manually projected the pixels but for cases such as this it's simpler to use slicing IMO and we get anti-aliasing for free.

    Example + demo

    Here is a full example (see demo for sliders and custom text) on one way of doing this:

    ONLINE DEMO HERE

    The result will be:

    Bridge example

    var ctx = demo.getContext('2d'), /// get canvas
        font = '64px impact',        /// define font
        w = demo.width,              /// cache width and height
        h = demo.height,
        curve,                       /// curve for our text
        offsetY,                     /// offset from top (see note)
        bottom,                      /// bottom origin
        textHeight,                  /// height of text
        angleSteps = 180 / w,        /// angle steps per pixel
        i = w,                       /// counter (for x)
        y,
        os = document.createElement('canvas'), /// off-screen canvas
        octx = os.getContext('2d');
    
    /// set off-screen canvas same size as our demo canavs
    os.width = w;
    os.height = h;
    
    /// prep text for off-screen canvas
    octx.font = font;
    octx.textBaseline = 'top';
    octx.textAlign = 'center';
    
    /// main render function
    function renderBridgeText() {
    
        /// snipped... get various data (see demo for detail)
    
        /// clear canvases
        octx.clearRect(0, 0, w, h);
        ctx.clearRect(0, 0, w, h);
    
        /// draw the text (see demo for details)    
        octx.fillText(iText.value, w * 0.5, 0);
    
        /// slide and dice (MAIN)
        i = w;
        while (i--) {
            /// calc distance based on curve (=radius) and x position
            y = bottom - curve * Math.sin(i * angleSteps * Math.PI / 180);
    
            /// draw the slice for this vertical line
            ctx.drawImage(os, i, offsetY, 1, textHeight,
                              i, offsetY, 1, y);
        }
    }
    

    Note on offset: offset can be many things - in this demo I let it be the top source of the text to "correct" the curving a little as texts aren't drawn at the very top (due to various glyph geometry which I'm not gonna into here) - you will see this clearly between Chrome and Firefox as the text is rendered differently.

    The demo let you change text and adjust a few parameters so you can see what effect they have on the text.

    How it works

    The width is divided first on number of pixels we want to displace on the x axis. This gives us the delta angle we need to use for each pixel step.

    Then we calculate a basic distance based on angle for y-axis using sinus using curve as radius. As the delta angle now corresponds to an angle from 0 to 180 based on x position this will gives us a nice curve matching the text width which is drawn in center.

    This value we subtract from bottom to get the y position for the bottom of text.

    Then we pick a normal sized slice from the source, one pixel thick, and we scale it to destination based on the y value. This does the trick.

    0 讨论(0)
提交回复
热议问题