Warp text

HTML

<canvas id=demo width=400 height=300></canvas>

<br>
<span>Top wave height:</span>
<input id="iTa" type="range" min=-100 max=100 value=0>
<span id="vTa">0</span>

<br>
<span>Top wave ripples:</span>
<input id="iTp" type="range" min=1 max=3 value=1>
<span id="vTp">1</span>

<br>
<span>Bottom wave height:</span>
<input id="iBa" type="range" min=-100 max=100 value=50>
<span id="vBa">50</span>



<br>
<span>Bottom wave ripples:</span>
<input id="iBp" type="range" min=1 max=3 value=1>
<span id="vBp">1</span>

<br>
<span>Waves width:</span>
<input id="iWw" type="range" min=20 max=100 value=80>
<span id="vWw">80</span>

<br>
<span>Offset Y:</span>
<input id="iYo" type="range" min=0 max=100 value=30>
<span id="vYo">30</span>

<br>
<span>Text height:</span>
<input id="iTh" type="range" min=10 max=100 value=60>
<span id="vTh">60</span>

<br>
<span>Text top gap:</span>
<input id="iTo" type="range" min=0 max=30 value=12>
<span id="vTo">12</span>

<br>
<span>Text:</span>
<input id="iText" type="text" value="BRIDGE TEXT">

CSS

span {
    display:inline-block;
    width:120px;
    text-align:right;
    font:12px sans-serif;
}

JavaScript

/// (c) Ken Fyrstenberg Nilsen, Abidas Software .com
/// License: CC-Attribute

var ctx = demo.getContext('2d'),
    font = '64px impact',
    w = demo.width,
    h = demo.height,
    os = document.createElement('canvas'),
    octx = os.getContext('2d');

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

octx.font = font;
octx.textBaseline = 'top';
octx.textAlign = 'center';

function decimalToHex(d, padding) {
    var hex = Number(d).toString(16);
    padding = typeof (padding) === "undefined" || padding === null ? padding = 2 : padding;

    while (hex.length < padding) {
        hex = "0" + hex;
    }

    return hex;
}

function renderArtText() 
{

		var ta = parseInt(iTa.value, 10);
    var tp = parseInt(iTp.value, 10);
    var ba = parseInt(iBa.value, 10);
    var bp = parseInt(iBp.value, 10);
    var yo = parseInt(iYo.value, 10);
    var ww = parseInt(iWw.value, 10);
    var th = parseInt(iTh.value, 10);
    var to = parseInt(iTo.value, 10);
    
    
    vTa.innerHTML = ta;
    vTp.innerHTML = tp;
    vBa.innerHTML = ba;
    vBp.innerHTML = bp;
    vYo.innerHTML = yo;
    vWw.innerHTML = ww;
    vTh.innerHTML = th;
    vTo.innerHTML = to;
    
    octx.clearRect(0, 0, w, h);
    ctx.clearRect(0, 0, w, h);

    octx.fillText(iText.value.toUpperCase(), w * 0.5, 0);
		
		var l = w*ww/100;
		ta = ta*th/100;
    ba = ba*th/100;

		for (var x = 0; x < w; x++)
    {
    		var s, f;
        
        s = ta*Math.sin(2*Math.PI*x/l * tp);
        f = ba*Math.sin(2*Math.PI*x/l * bp);

        ctx.drawImage
        (
        	os, 
          x, to, 1, th, 
          x, yo-s, 1, th-f+s
        );
    
    	
    }
}

iTa.onchange = iTp.onchange  = iBa.onchange = iWw.onchange = 
iBp.onchange = iText.onkeyup = iYo.onchange = 
iTh.onchange = iTo.onchange  = renderArtText;

renderArtText();