繁体   English   中英

将bezierCurve html5画布绘图居中?

[英]Center a bezierCurve html5 canvas drawing?

因此,我使用html5画布制作了基本图形,可以创建的基本形状具有用于定位整个形状的参数,在我下面,通过取窗口大小并除以2,将圆心centerXcenterY

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();

这是一种使您的三次贝塞尔曲线精确居中的方法

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

在此处输入图片说明

第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;

第四步。 了解了偏移量后,您可以使用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();

我不知道是否有快速的方法。 我的尝试是这样的:检查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();

对不起,我的代码很脏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM