0

HTML5キャンバスに(たとえば)線を引きたい。次に、その行に画像のベベル効果を追加したいと思います。つまり、キャンバスの上にひもが置かれているように、3D に見えます。その線に沿って何かを行うことができる画像処理効果を見た人はいますか?

ここに画像の説明を入力

4

2 に答える 2

2

そのような描画を行う唯一の方法は、曲線を段階的に描画し、各段階でローカル接線に垂直なテクスチャを適用することだと思います。

しかし、別の機能が必要なようです。カーブの部分に応じてテクスチャを「ねじる」ことができます。ここには、これをパラメータ化するための非常に多くのオプションがあり、テクスチャのねじれをどのように保存/補間するかを推測できません。そのため、以下では、ベジエ曲線のパラメーターである t を使用してテクスチャを「回転」させました。

http://jsfiddle.net/gamealchemist/YPKV9/

例 : 曲線に適用されたテクスチャを示すイメージと、曲線に沿って回転する同じテクスチャを持つ同じ曲線の下。

ここに画像の説明を入力

//  ----------------------------------------------
//  Draw bezier curve filled with 
//    with txCv used as perpendicular texture 
//    signature : drawTexturedBezier ( txCv, a, b, c, d, twisted )
//    a,b,c,d are control points, twisted means
//      do we have to twist the curve.
//          Width of the bezier is == to txCv.width/2 
//          when the draw resolution is tx.height (lower = nicer+slower, 3 seems fine )
//  ----------------------------------------------
function drawTexturedBezier() {
    // build onnly once local vars
    var pt = {
        x: 0,
        y: 0
    };
    var tg = {
        x: 0,
        y: 0
    };
    var lastPt = {
        x: 0,
        y: 0
    };
    drawTexturedBezier = function (txCv, a, b, c, d, twisted) {
        var lineHeight = txCv.height;
        var t = 0;
        var incr = 1 / 1000;
        var pointCount = 0;
        pt.x = a.x;
        pt.y = a.y;
        var thisCoordsForT = coordsForT.bind(null, a, b, c, d);
        var thisTgtForT = tangentForT.bind(null, a, b, c, d);
        // scan the bezier curve by increment of lineHeight distance
        //  on the curve.
        do {
            // update last point
            lastPt.x = pt.x;
            lastPt.y = pt.y;
            // seek next point far enough from previous point
            // just compute one point ahead
            //   using average estimate for t of '1 point ahead'
            thisCoordsForT(t + incr, pt);
            var dx = pt.x - lastPt.x;
            dx *= dx;
            var dy = pt.y - lastPt.y;
            dy *= dy;
            // compute distance to previous point
            var dist = Math.sqrt(dx + dy);
            // compute required t increment
            // considering curve is locally linear
            //  0.92 compensates for the error.
            var tIncrement = 0.92 * incr * (lineHeight / dist);
            t += tIncrement;
            // compute point
            thisCoordsForT(t, pt);
            pointCount++;
            // update regular increment with local one 
            incr = 0.2 * incr + 0.8 * tIncrement;
            // compute tangent for current point
            thisTgtForT(t, tg);
            // draw with perpendicular texture
            drawTexturedLine(txCv, pt, tg, t, twisted);
        } while (t < 1);
    };
    return drawTexturedBezier.apply(this, arguments);
}

// draws a rect centered on pt, for a curve having tg as local tangent
//     having size of : txCv.width/2 X txCv.height
//      using the txCv horizontal pattern as pattern.
function drawTexturedLine(txCv, pt, tg, t, twisted) {
    var lineWidth = txCv.width / 2;
    var lineHeight = txCv.height;
    context.save();
    context.beginPath();
    context.lineWidth = 2;
    context.translate(pt.x, pt.y);
    context.rotate(Math.PI + Math.atan2(-tg.x, tg.y));
    var twistFactor = 0;
    if (twisted) {
        twistFactor = (2 * t + animating * Date.now() / 2000) % 1;
    }
    context.drawImage(txCv,
    twistFactor * lineWidth, 0, lineWidth, lineHeight, -0.5 * lineWidth, -0.5 * lineHeight, lineWidth, lineHeight);
    context.restore();
}
于 2014-06-23T22:31:40.220 に答える