如何绘制.javascript中的arcs



如何在javascript中实现圆角?

以下是C#中用于绘制圆角的代码。

某些带有Paint的几何体:


0.你有一个角落:
![角][1]

1.你知道角点的坐标,让它是P1,P2和P:
![角点][2]

2。现在,您可以从点和向量之间的角度获取向量:
![矢量和角度][3]

角度=atan(PY-P1Y,PX-P1X)-atan(PY-P2Y/sub>,PX-P2X)

3。获取角点与圆交点之间的线段长度
!【分段】[4]
segment=PC1=PC2=半径/|tan(角度/2)|

4。在这里,您需要从PP1和PP2检查段的长度和最小长度:
![最小长度][5]
PP的长度1
PP1=sqrt((PX-P1X)2+
PP2=sqrt((PX-P2X)2+;PP1或segment>PP2则需要减小半径:
min=min(PP1,PP2)(对于多边形,最好将该值除以2)分段>最小值?分段=最小半径=线段*|tan(角度/2)|

5。获取PO的长度:
PO=sqrt(半径2+段2)

6。根据向量的坐标、向量的长度和线段的长度之间的比例,得到C1X和C1Y
![PC1坐标][6]

比例:

(PX-C1X)/
C1X=PX-
C1Y=PY-(PY-P1Y)*PC1/PP2
7。通过相同的方法获得C2X和C2Y
C2X=PX-2

8。现在,您可以使用向量PC1和PC2的加法,以相同的方式按比例找到圆心:
!【矢量添加】[7]
(PX-OX)/(PY-OY)/(PY-CY/sub>)=PO/PC

此处:

CX=C1X+C2X--PXCY1Y+C2Y-PYPC=sqrt PY-CY)2)

设:

dx=PX-CX=PX*2-C1X-C2X/sub>dy=PY-CY=2-CY因此:
PC=sqrt(dx2+dy2)OX=PX-dx*PO/PCOY=PY-dy*PO/PC

9。在这里你可以画一条弧。为此,你需要得到弧的起始角和终止角:
![Arc][8]
找到它[在这里][9]:
startAngle=atan((C1Y-OY/sub>)/(C1X-OX)endAngle=atan((C2Y-OY/sub>)/(C2X-OX))

10。最后你需要得到一个扫掠角并进行一些检查:
![扫描角度][10]
sweepAngle = endAngle - startAngle

如果后掠角<0,然后交换startAngle和endAngle,并反转后掠角:

sweepAngle < 0 ?    
sweepAngle = - sweepAngle
startAngle = endAngle

检查后掠角>180度:

sweepAngle > 180 ?    
sweepAngle = 180 - sweepAngle

11.现在你可以画一个圆角了:
![结果][11]

一些带有c#的几何:

private void DrawRoundedCorner(Graphics graphics, PointF angularPoint, 
PointF p1, PointF p2, float radius)
{
//Vector 1
double dx1 = angularPoint.X - p1.X;
double dy1 = angularPoint.Y - p1.Y;
//Vector 2
double dx2 = angularPoint.X - p2.X;
double dy2 = angularPoint.Y - p2.Y;
//Angle between vector 1 and vector 2 divided by 2
double angle = (Math.Atan2(dy1, dx1) - Math.Atan2(dy2, dx2)) / 2;
// The length of segment between angular point and the
// points of intersection with the circle of a given radius
double tan = Math.Abs(Math.Tan(angle));
double segment = radius / tan;
//Check the segment
double length1 = GetLength(dx1, dy1);
double length2 = GetLength(dx2, dy2);
double length = Math.Min(length1, length2);
if (segment > length)
{
segment = length;
radius = (float)(length * tan);
}
// Points of intersection are calculated by the proportion between 
// the coordinates of the vector, length of vector and the length of the segment.
var p1Cross = GetProportionPoint(angularPoint, segment, length1, dx1, dy1);
var p2Cross = GetProportionPoint(angularPoint, segment, length2, dx2, dy2);
// Calculation of the coordinates of the circle 
// center by the addition of angular vectors.
double dx = angularPoint.X * 2 - p1Cross.X - p2Cross.X;
double dy = angularPoint.Y * 2 - p1Cross.Y - p2Cross.Y;
double L = GetLength(dx, dy);
double d = GetLength(segment, radius);
var circlePoint = GetProportionPoint(angularPoint, d, L, dx, dy);
//StartAngle and EndAngle of arc
var startAngle = Math.Atan2(p1Cross.Y - circlePoint.Y, p1Cross.X - circlePoint.X);
var endAngle = Math.Atan2(p2Cross.Y - circlePoint.Y, p2Cross.X - circlePoint.X);
//Sweep angle
var sweepAngle = endAngle - startAngle;
//Some additional checks
if (sweepAngle < 0)
{
startAngle = endAngle;
sweepAngle = -sweepAngle;
}
if (sweepAngle > Math.PI)
sweepAngle = Math.PI - sweepAngle;
//Draw result using graphics
var pen = new Pen(Color.Black);
graphics.Clear(Color.White);
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.DrawLine(pen, p1, p1Cross);
graphics.DrawLine(pen, p2, p2Cross);
var left = circlePoint.X - radius;
var top = circlePoint.Y - radius;
var diameter = 2 * radius;
var degreeFactor = 180 / Math.PI;
graphics.DrawArc(pen, left, top, diameter, diameter, 
(float)(startAngle * degreeFactor), 
(float)(sweepAngle * degreeFactor));
}
private double GetLength(double dx, double dy)
{
return Math.Sqrt(dx * dx + dy * dy);
}
private PointF GetProportionPoint(PointF point, double segment, 
double length, double dx, double dy)
{
double factor = segment / length;
return new PointF((float)(point.X - dx * factor), 
(float)(point.Y - dy * factor));
}

要获得弧点,可以使用以下方法:

//One point for each degree. But in some cases it will be necessary 
// to use more points. Just change a degreeFactor.
int pointsCount = (int)Math.Abs(sweepAngle * degreeFactor);
int sign = Math.Sign(sweepAngle);
PointF[] points = new PointF[pointsCount];
for (int i = 0; i < pointsCount; ++i)
{
var pointX = 
(float)(circlePoint.X  
+ Math.Cos(startAngle + sign * (double)i / degreeFactor)  
* radius);
var pointY = 
(float)(circlePoint.Y 
+ Math.Sin(startAngle + sign * (double)i / degreeFactor) 
* radius);
points[i] = new PointF(pointX, pointY);
}

我已经实现了javascript:

let radius = 10;
const angle =
Math.atan(p.x - p1.x, p.x - p1.x) - Math.atan(p.y - p2.y, p.x - p2.x);
let segment = radius / Math.abs(Math.tan(angle / 2));
const pp1 = Math.sqrt(Math.pow(p.x - p1.x, 2) + Math.pow(p.y - p1.y, 2));
const pp2 = Math.sqrt(Math.pow(p.x - p2.x, 2) + Math.pow(p.y - p2.y, 2));
const min = Math.min(pp1, pp2);
if (segment > min) {
segment = min;
radius = segment * Math.abs(Math.tan(angle / 2));
}
const po = Math.sqrt(Math.pow(radius, 2) + Math.pow(segment, 2));
const r = 10;
const c1x = p.x - ((p.x - p1.x) * segment) / pp1;
const c1y = p.y - ((p.y - p1.y) * segment) / pp1;
const c2x = p.x - ((p.x - p2.x) * segment) / pp2;
const c2y = p.y - ((p.y - p2.y) * segment) / pp2;
const dx = p.x * 2 - c1x - c2x;
const dy = p.y * 2 - c1y - c2y;
const pc = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
const ox = p.x - (dx * po) / pc;
const oy = p.y - (dy * po) / pc;
let startAngle = Math.atan((c1y - oy) / (c1x - ox));
let endAngle = Math.atan((c2y - oy) / (c2x - ox));
let sweepAngle = endAngle - startAngle;
if (sweepAngle < 0) {
sweepAngle = -sweepAngle;
startAngle = endAngle;
}
if (sweepAngle > 180) sweepAngle = 180 - sweepAngle;

但问题是圆角并没有像预期的那样画出来!

c中的arc绘制不同于html画布arc。

那么我如何使用上面的数据在html5画布中绘制它呢?

要在html5画布中绘制圆弧,可以使用ctx.arc(xPos, yPos, radius, startAngle, endAngle, (optional boolean, defaults to false) counterClockwise);

文档可在W3Schools.com 上找到

更多通用的html5画布文档也可以在W3Schools.com 上找到

最新更新