中心bezierCurve html5画布画?

时间:2014-06-12 15:58:47

标签: javascript html5 canvas

所以我用html5画布制作了基本的图画,你可以创建的基本形状有参数来定位整个形状,下面我通过取窗口大小和划分来居中一个圆centerXcenterY由2。

context.beginPath();
context.globalCompositeOperation = 'destination-out';
context.arc(centerX, centerY, radius, Math.PI*2, false);
context.fill();
context.closePath();

上面的图画很好并且居中,但现在我正在玩贝塞尔曲线,我在网上找不到任何暗示如何居中的东西。

// some arbitrary example
context.beginPath();
context.moveTo(170, 80);
context.bezierCurveTo(130, 100, 130, 150, 230, 150);
context.bezierCurveTo(250, 180, 320, 180, 340, 150);
context.bezierCurveTo(420, 150, 420, 120, 390, 100);
context.fill();
context.globalCompositeOperation = 'destination-out';
context.closePath();

我写了一个小提琴,因此可以使用JSFIDDLE。下面是直接从我的小提琴粘贴的代码。

var canvas = document.getElementById("c");
var context = canvas.getContext("2d");

canvas.width = $(window).width();
canvas.height = $(window).height();

var centerX = canvas.width / 2;
var centerY = canvas.height / 2;

function draw() {

    context.clearRect(0, 0, canvas.width, canvas.height);

    context.beginPath();
    context.fillStyle = '#333';
    context.fillRect(0, 0, canvas.width, canvas.height);
    context.closePath();

    // custom shape (weird shape lol)
    context.beginPath();
    context.globalCompositeOperation = 'destination-out';
    context.moveTo(170, 80);
    context.bezierCurveTo(130, 100, 130, 150, 230, 150);
    context.bezierCurveTo(250, 180, 320, 180, 340, 150);
    context.bezierCurveTo(420, 150, 420, 120, 390, 100);
    context.fill();
    context.closePath();

    context.globalCompositeOperation = 'source-over';

}

draw();

2 个答案:

答案 0 :(得分:2)

这是一种准确居中立方贝塞尔曲线组的方法

演示:http://jsfiddle.net/m1erickson/6GZmp/

enter image description here

步骤#1。 使用De Casteljau算法绘制曲线组中每条曲线的点。

// De Casteljau's algorithm which calculates points along a cubic Bezier curve

// plot a point at interval T along a bezier curve
// T==0.00 at beginning of curve. T==1.00 at ending of curve
// Calculating 100 T's between 0-1 will usually define the curve sufficiently

function getCubicBezierXYatT(startPt,controlPt1,controlPt2,endPt,T){
    var x=CubicN(T,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
    var y=CubicN(T,startPt.y,controlPt1.y,controlPt2.y,endPt.y);
    return({x:x,y:y});
}

// cubic helper formula at T distance

function CubicN(T, a,b,c,d) {
    var t2 = T * T;
    var t3 = t2 * T;
    return a + (-a * 3 + T * (3 * a - a * T)) * T
    + (3 * b + T * (-6 * b + b * 3 * T)) * T
    + (c * 3 - c * 3 * T) * t2
    + d * t3;
}

步骤#2。 通过获取在#1中绘制的点的minX,maxX,minY,maxY来确定曲线组的边界框。并使用max-min确定曲线组的宽度和高度。

var curvesWidth = maxX - minX;

var curvesHeight = maxY - minY;

步骤#3。 计算所需的偏移量以使曲线组居中。

var offsetX=(canvas.width/2-curvesWidth/2)-curvesLeft;

var offsetY=(canvas.height/2-curvesHeight/2)-curvesTop;

步骤#4。了解偏移量后,您可以使用context.translate 绘制居中曲线

context.save();

context.translate(offsetX,offsetY);

context.beginPath();
context.moveTo(170, 80);
context.bezierCurveTo(130, 100, 130, 150, 230, 150);
context.bezierCurveTo(250, 180, 320, 180, 340, 150);
context.bezierCurveTo(420, 150, 420, 120, 390, 100);
context.fill();

context.restore();

答案 1 :(得分:1)

我不知道是否有快速的方法。我的尝试是这样的: 检查x轴上的每个点并将其与其他点进行比较,如果它是最左侧或最右侧存储它们在变量中的位置,否则不执行任何操作。获得这些点后,您就知道整个路径的宽度,并且可以计算偏移值以将其放置在中心内(因为您知道画布宽度)。然后只需将该偏移值添加到点坐标中即可:

http://jsfiddle.net/jonigiuro/8jsw9/4/

var canvas = document.getElementById("c"); var context = canvas.getContext("2d");

canvas.width = $(window).width(); canvas.height = $(window).height();

var centerX = canvas.width / 2; var centerY = canvas.height / 2;

var bezierSteps = [
    [130, 100, 130, 150, 230, 150],
    [250, 180, 320, 180, 340, 150],
    [420, 150, 420, 120, 390, 100]
];
var mostLeft = 2000; var mostRight = 0;

findCenter();

function findCenter() {
    for (var i = 0; i < bezierSteps.length; i++) {
        for (var p = 0; p < bezierSteps.length; p+=2) {
            mostLeft = bezierSteps[i][p] < mostLeft ? bezierSteps[i][p] : mostLeft;
            mostRight = bezierSteps[i][p] > mostRight ? bezierSteps[i][p] : mostRight;
        }
    }
    console.log(mostLeft, mostRight) } var offset = (canvas.width - mostLeft - mostRight) / 2;

console.log(offset)

function draw() {

    context.clearRect(0, 0, canvas.width, canvas.height);

    context.beginPath();
    context.fillStyle = '#333';
    context.fillRect(0, 0, canvas.width, canvas.height);
    context.closePath();

    // custom shape (weird shape lol)
    context.beginPath();
    context.globalCompositeOperation = 'destination-out';
    context.moveTo(170 + offset, 80);

    for (var i = 0, l = bezierSteps.length ; i < l ; i++) {
        context.bezierCurveTo(bezierSteps[i][0]  + offset,bezierSteps[i][1],bezierSteps[i][2] + offset,bezierSteps[i][3],bezierSteps[i][4] + offset,bezierSteps[i][5])
    }
    //context.bezierCurveTo(130, 100, 130, 150, 230, 150);
    //context.bezierCurveTo(250, 180, 320, 180, 340, 150);
    //context.bezierCurveTo(420, 150, 420, 120, 390, 100);
    context.fill();
    context.closePath();

    context.globalCompositeOperation = 'source-over';

}

draw();

抱歉脏代码..