javascript - 如何在 Canvas 上创建不同的文字艺术设计?

标签 javascript html canvas

我们正在尝试使用 html5 和 Canvas 创建如下图所示的文本艺术,但我们无法找到合适的参数来创建这种设计。

  • text art design parameters
  • text art design
    这种类型的文字艺术是否需要任何其他参数?

  • 提前致谢

    最佳答案

    因为我喜欢画画,所以我实现了你问题的两个概念文字艺术。
    即使看起来您不再关心,这也适用于任何好奇的人。

    基本原理

    为了实现上述效果,您需要利用一种本质上是 2D texture mapping 的技术。 ,但大大简化了,因为我们将保持左右边缘笔直。

    本质上,它包括将正方形变成不同的形状1

    Texture mapping concept

    蓝色方 block 代表您绘制文本的图像,红色方 block 是最终图像应该如何“变形”。
    通过选择适当的变形,您可以实现不同类型的对象。

    特例

    一般纹理映射需要一些 tessellation 2 关于被映射的形状,可能还有 Barycentric coordinate system 的使用.

    然而,在我们的例子中,我们可以创建一个 假设我们正在将一个矩形映射到一个新的(凸)形状,该形状与原始形状具有相同的宽度并且不会改变垂直边缘。

    简单来说,我们不是 做这种转变。

    A transformation not allowed

    这很重要,因为我们可以用一个简单的算法来实现我们的转换。

    变换算法

    基本上,我们将原始矩形切成垂直条纹,并根据新形状对应的条纹高度缩放每个条纹。
    例如,在上面的示例映射中,中间“条纹”的高度如何变化:

    Heights mapping

    HTML5 Canvas 让我们可以使用 drawImage 方法轻松重绘条纹,实际上是像素列格式为 drawImage(source, x, 0, 1, h, x, upperY, 1, lowerY-upperY) .
    这将获取与 x 处的条纹相对应的矩形,并将其绘制在相同的 x 处,但在不同的 y 处和不同的高度处。
    有时我们可能需要将比整个 Canvas 短的矩形作为源,但过程是相同的。

    upperY 和 lowerY 可以作为 x 的函数计算,并且可以取任何值。仔细选择生成这些值的函数将产生预期的效果。

    1.   For X = 0 To Canvas.Width
    1.1     upperY = f_upper(x);
    1.2     lowerY = f_lower(x);
    1.3     Canvas.DrawImage(SrcCanvs, x, 0, 1, SrcCanvs.Height, x, upperY, 1, lowerY-upperY);
    

    第一艺术

    关于实现

    First art

    fiddle 是here .

    首先第一件事:我们没有映射整个 Canvas ,评估它的一个子矩形,它足够高以覆盖文本并且与 Canvas 一样大。
    要参数化这个矩形,我们只需要它的高度和它到 Canvas 顶部的垂直距离。
    这两个参数是文本高度和文本顶部间隙。

    map 是

    First art mapping

    其余的相当简单:我们让用户选择设置树点对之间的距离,以文本高度美分单位,以及红色对的水平位置,以 Canvas 宽度美分单位。

    上层函数是常数函数 0。
    下面的函数是一个分段函数:当 x 在中点之前时使用前半部分,否则使用后半部分。
    对于这两种情况,我们只计算较低点之间的线:前半部分为绿-红,后半部分为红-蓝。

    第二艺术

    关于实现

    Second art

    fiddle 是here .

    我们让用户选择顶部和底部波的幅度(以文本高度美分为单位)和频率(以波纹数为单位)以及两个波周期的缩放参数(以 Canvas 宽度美分单位)。

    我无法在 InkScape 上快速绘制映射,所以我让它发挥想象力。
    基本上我们使用 sin 作为具有不同参数的上下函数。

    通过适本地改变所有四种文字艺术的波浪参数。

    第二艺术片段

    /// (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();
    span {
        display:inline-block;
        width:120px;
        text-align:right;
        font:12px sans-serif;
    }
    <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">
     


    第一艺术片段

    /// (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 renderArtText() 
    {
    
    		var hs = parseInt(iHs.value, 10);
        var hm = parseInt(iHm.value, 10);
        var hf = parseInt(iHf.value, 10);
        var xm = parseInt(iXm.value, 10);
        var yo = parseInt(iYo.value, 10);
        var th = parseInt(iTh.value, 10);
        var to = parseInt(iTo.value, 10);
        
        vHs.innerHTML = hs;
        vHm.innerHTML = hm;
        vHf.innerHTML = hf;
        vXm.innerHTML = xm;
        vYo.innerHTML = yo;
        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 ysl = (th + hs*th/100)/2;
        var yml = (th + hm*th/100)/2;
    		var yfl = (th + hf*th/100)/2;
        
        var xs = 0;
        xm = xm*w/100;
    		var xf = w;
    		yo = yo*h/100;
    
    		for (var x = 0; x < w; x++)
        {
        		var f;
            
        		if (x < xm)
              f = ysl + x*(yml-ysl)/(xm-xs);
            else
              f = yml + (x-xm)*(yfl-yml)/(xf-xm);
            
            ctx.drawImage
            (
            	os, 
              x, to, 1, th, 
              x, yo, 1, f
            );
        
        }
    }
    
    iHs.onchange = iHm.onchange  = iHf.onchange = 
    iXm.onchange = iText.onkeyup = iYo.onchange = 
    iTo.onchange = iTh.onchange  = renderArtText;
    
    renderArtText();
    span {
        display:inline-block;
        width:90px;
        text-align:right;
        font:12px sans-serif;
    }
    <canvas id=demo width=400 height=300></canvas>
    
    <br>
    <span>Start Height:</span>
    <input id="iHs" type="range" min=0 max=200 value=10>
    <span id="vHs">10</span>
    
    <br>
    <span>Middle Height:</span>
    <input id="iHm" type="range" min=0 max=200 value=167>
    <span id="vHm">167</span>
    
    <br>
    <span>End Height:</span>
    <input id="iHf" type="range" min=0 max=200 value=30>
    <span id="vHf">30</span>
    
    <br>
    <span>Middle point:</span>
    <input id="iXm" type="range" min=0 max=100 value=50>
    <span id="vXm">50</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=13>
    <span id="vTo">13</span>
    
    <br>
    <span>Text:</span>
    <input id="iText" type="text" value="TEXT ART">
     



    1 仍然具有直的侧边。

    2 仅在这种情况下是二维的。

    关于javascript - 如何在 Canvas 上创建不同的文字艺术设计?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35745362/

    相关文章:

    javascript - 如何根据其子 <a> href 将事件的 css 类应用于 li

    Javascript 鼠标步进事件

    javascript - jQuery 在一段时间后更改文本?

    java - SmartGWT,将 HTML 附加到 HTMLPane

    html - 水平滚动图像列表

    HTML 列大小 slider

    php - 在获取表单中为同一复选框字段传递两个值

    用于几何形状的 Python Canvas 库

    javascript - `createImageData()` 和 `new ImageData()` 有何不同?

    php - 如何将两个刷新div的脚本合并为一个?