如何在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 上找到