如何使用HTML 5画布沿着弧路径绘制文本? [英] How Can I draw a Text Along arc path with HTML 5 Canvas?

查看:183
本文介绍了如何使用HTML 5画布沿着弧路径绘制文本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要绘制一个这样的动画画布:
http://www.cci.com.tr/tr/bizi-taniyin/tarihcemiz/

I want to draw a canvas graphic like this flash animation: http://www.cci.com.tr/tr/bizi-taniyin/tarihcemiz/

我画了六个弧,我想写六词在这些弧。任何想法?

I drew six arcs and I want to write six words in these arcs. Any ideas?

推荐答案

我有一个jsFiddle应用文本到任何贝塞尔曲线定义。享受 http://jsfiddle.net/Makallus/hyyvpp8g/

I have a jsFiddle to apply text to any arbitrary Bezier curve definition. Enjoy http://jsfiddle.net/Makallus/hyyvpp8g/

<table>
    <TR>
        <TH>Bezier Curve</TH>
        <TD>
            <input size="80" type="text" id="curve" name="curve" value="99.2,177.2,130.02,60.0,300.5,276.2,300.7,176.2">
        </TD>
    </TR>
    <TR>
        <TH>Text</TH>
        <TD>
            <input size="80" type="text" id="text" name="text" value="testing 1234567890">
        </TD>
    </TR>
    <TR>
        <TD colspan=2>
            <div id="canvasDiv"></div>
        </TD>
    </TR>
</table>

var first = true;
startIt();


function startIt() {
    canvasDiv = document.getElementById('canvasDiv');
    canvasDiv.innerHTML = '<canvas id="layer0" width="300" height="300"></canvas>'; //for IE
    canvas = document.getElementById('layer0');
    ctx = canvas.getContext('2d');
    ctx.fillStyle = "black";
    ctx.font = "18px arial black";
    curve = document.getElementById('curve');
    curveText = document.getElementById('text');
    $(curve).keyup(function (e) {
        changeCurve();
    });
    $(curveText).keyup(function (e) {
        changeCurve();
    });




    if (first) {
        changeCurve();
        first = false;
    }

}

function changeCurve() {
    points = curve.value.split(',');
    if (points.length == 8) drawStack();

}

function drawStack() {
    Ribbon = {
        maxChar: 50,
        startX: points[0],
        startY: points[1],
        control1X: points[2],
        control1Y: points[3],
        control2X: points[4],
        control2Y: points[5],
        endX: points[6],
        endY: points[7]
    };

    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.save();
    ctx.beginPath();

    ctx.moveTo(Ribbon.startX, Ribbon.startY);
    ctx.bezierCurveTo(Ribbon.control1X, Ribbon.control1Y,
    Ribbon.control2X, Ribbon.control2Y,
    Ribbon.endX, Ribbon.endY);

    ctx.stroke();
    ctx.restore();

    FillRibbon(curveText.value, Ribbon);
}

function FillRibbon(text, Ribbon) {

    var textCurve = [];
    var ribbon = text.substring(0, Ribbon.maxChar);
    var curveSample = 1000;


    xDist = 0;
    var i = 0;
    for (i = 0; i < curveSample; i++) {
        a = new bezier2(i / curveSample, Ribbon.startX, Ribbon.startY, Ribbon.control1X, Ribbon.control1Y, Ribbon.control2X, Ribbon.control2Y, Ribbon.endX, Ribbon.endY);
        b = new bezier2((i + 1) / curveSample, Ribbon.startX, Ribbon.startY, Ribbon.control1X, Ribbon.control1Y, Ribbon.control2X, Ribbon.control2Y, Ribbon.endX, Ribbon.endY);
        c = new bezier(a, b);
        textCurve.push({
            bezier: a,
            curve: c.curve
        });
    }

    letterPadding = ctx.measureText(" ").width / 4;
    w = ribbon.length;
    ww = Math.round(ctx.measureText(ribbon).width);


    totalPadding = (w - 1) * letterPadding;
    totalLength = ww + totalPadding;
    p = 0;

    cDist = textCurve[curveSample - 1].curve.cDist;

    z = (cDist / 2) - (totalLength / 2);

    for (i = 0; i < curveSample; i++) {
        if (textCurve[i].curve.cDist >= z) {
            p = i;
            break;
        }
    }

    for (i = 0; i < w; i++) {
        ctx.save();
        ctx.translate(textCurve[p].bezier.point.x, textCurve[p].bezier.point.y);
        ctx.rotate(textCurve[p].curve.rad);
        ctx.fillText(ribbon[i], 0, 0);
        ctx.restore();

        x1 = ctx.measureText(ribbon[i]).width + letterPadding;
        x2 = 0;
        for (j = p; j < curveSample; j++) {
            x2 = x2 + textCurve[j].curve.dist;
            if (x2 >= x1) {
                p = j;
                break;
            }
        }




    }
} //end FillRibon

function bezier(b1, b2) {
    //Final stage which takes p, p+1 and calculates the rotation, distance on the path and accumulates the total distance
    this.rad = Math.atan(b1.point.mY / b1.point.mX);
    this.b2 = b2;
    this.b1 = b1;
    dx = (b2.x - b1.x);
    dx2 = (b2.x - b1.x) * (b2.x - b1.x);
    this.dist = Math.sqrt(((b2.x - b1.x) * (b2.x - b1.x)) + ((b2.y - b1.y) * (b2.y - b1.y)));
    xDist = xDist + this.dist;
    this.curve = {
        rad: this.rad,
        dist: this.dist,
        cDist: xDist
    };
}

function bezierT(t, startX, startY, control1X, control1Y, control2X, control2Y, endX, endY) {
    //calculates the tangent line to a point in the curve; later used to calculate the degrees of rotation at this point.
    this.mx = (3 * (1 - t) * (1 - t) * (control1X - startX)) + ((6 * (1 - t) * t) * (control2X - control1X)) + (3 * t * t * (endX - control2X));
    this.my = (3 * (1 - t) * (1 - t) * (control1Y - startY)) + ((6 * (1 - t) * t) * (control2Y - control1Y)) + (3 * t * t * (endY - control2Y));
}

function bezier2(t, startX, startY, control1X, control1Y, control2X, control2Y, endX, endY) {
    //Quadratic bezier curve plotter
    this.Bezier1 = new bezier1(t, startX, startY, control1X, control1Y, control2X, control2Y);
    this.Bezier2 = new bezier1(t, control1X, control1Y, control2X, control2Y, endX, endY);
    this.x = ((1 - t) * this.Bezier1.x) + (t * this.Bezier2.x);
    this.y = ((1 - t) * this.Bezier1.y) + (t * this.Bezier2.y);
    this.slope = new bezierT(t, startX, startY, control1X, control1Y, control2X, control2Y, endX, endY);

    this.point = {
        t: t,
        x: this.x,
        y: this.y,
        mX: this.slope.mx,
        mY: this.slope.my
    };
}

function bezier1(t, startX, startY, control1X, control1Y, control2X, control2Y) {
    //linear bezier curve plotter; used recursivly in the quadratic bezier curve calculation
    this.x = ((1 - t) * (1 - t) * startX) + (2 * (1 - t) * t * control1X) + (t * t * control2X);
    this.y = ((1 - t) * (1 - t) * startY) + (2 * (1 - t) * t * control1Y) + (t * t * control2Y);

}

这篇关于如何使用HTML 5画布沿着弧路径绘制文本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆