[英]Center a bezierCurve html5 canvas drawing?
因此,我使用html5画布制作了基本图形,可以创建的基本形状具有用于定位整个形状的参数,在我下面,通过取窗口大小并除以2,将圆心centerX
和centerY
。
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.