Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
767 views
in Technique[技术] by (71.8m points)

javascript - Bridge Text Effect in HTML5 Canvas

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.

enter image description here

<!DOCTYPE HTML>
<html>
  <head>
    <style>
      body {
        margin: 0px;
        padding: 0px;
      }
    </style>
  </head>
  <body>
    <canvas id="myCanvas" width="578" height="200"></canvas>
    <script>
      var canvas = document.getElementById('myCanvas');
      var context = canvas.getContext('2d');
      var x = canvas.width / 2;
      var y = canvas.height / 2;

      context.font = '30pt Calibri';
      // textAlign aligns text horizontally relative to placement
      context.textAlign = 'center';
      // textBaseline aligns text vertically relative to font style
      context.textBaseline = 'middle';
      context.fillStyle = 'blue';
      context.fillText('BRIDGE TEXT', x, y);
    </script>
  </body>
</html>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...