ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

javascript – 如何使用start和endAngle呈现svg圈

2019-06-08 08:29:07  阅读:583  来源: 互联网

标签:javascript path svg circle angle


我使用start和endAngle渲染了svg圈.它工作得很好.但是当我渲染完整的圆圈(startAngle为70,endAngle为70)时,输出差别很大(0,90,180,270除外).我为这段代码做错了什么?

            function getPathArc(center, start, end, radius) {
                end -= this.isCompleteAngle(start, end) ? 0.0001 : 0;
                var degree = end - start;
                degree = degree < 0 ? (degree + 360) : degree;
                return this.getCirclePath(
                    center, getLocationFromAngle(start, radius, center),
                    getLocationFromAngle(end, radius, center), radius, (degree < 180) ? 0 : 1
                );
            }

            function getCirclePath(center, start, end, radius, clockWise) {
                return 'M ' + start.x + ' ' + start.y + ' A ' + radius + ' ' +
                    radius + ' 0 ' + clockWise + ' 1 ' + end.x + ' ' + end.y;
            }

            function getLocationFromAngle(degree, radius, center) {
                var radian = (degree * Math.PI) / 180;
                return {
                    x : Math.cos(radian) * radius + center.x,
                    y : Math.sin(radian) * radius + center.y
                }
            }

            function isCompleteAngle(startAngle, endAngle) {
                var totalAngle = endAngle - startAngle;
                totalAngle = totalAngle <= 0 ? (totalAngle + 360) : totalAngle;
                return Math.floor(totalAngle / 360) !== 0;
            }

示例链接:https://jsfiddle.net/fNPvf/43106/

enter image description here

绿色圆圈正确渲染,因为start和endAngle为90,即使我将角度更改为0,180,270和360也可以.但实际的问题是我使用70的红色圆圈甚至问题将会出现,除了那些角度(0,90,180,270,360).

如何清除这个问题?

解决方法:

圆之间的这种差异是由于数值精度的影响.由于SVG弧和浮点算法的工作方式,起点和终点的微小变化在最终弧中可能会被夸大.弧的角度越大,效果就越大.

要绘制圆弧,渲染器需要首先确定圆的中心.如果你试图制作一个360度的弧度,你的起点和终点几乎是一样的.

请考虑以下插图:

enter image description here

绿点和红点是弧的起点和终点.灰点是渲染计算以绘制圆弧的圆的中心.

图中的弧度大约为359度.现在想象一下将红色和绿色点移近.确定中心点所需的计算将越来越容易受到起点和终点坐标以及浮点算术函数的不准确性的影响.

除此之外,sin()和cos()函数只是sin和cos曲线的近似值.请记住,浏览器Javascript引擎必须平衡速度和准确性.

然后添加大多数(如果不是全部)SVG渲染引擎使用贝塞尔曲线逼近弧的事实.但是,beziers不能完美地代表圆弧.

希望你现在可以看到为什么你得到你的结果.尝试用单个弧表示大角度是一个坏主意.我的个人建议是使用至少三个或四个圆弧进行整圈.

function getPathArc(center, start, end, radius) {
  if (end == start) end += 360;
  var degree = end - start;
  degree = degree < 0 ? (degree + 360) : degree;
  var points = [];
  points.push( getLocationFromAngle(start, radius, center) );
  points.push( getLocationFromAngle(start+degree/3, radius, center) );
  points.push( getLocationFromAngle(start+degree*2/3, radius, center) );
  points.push( getLocationFromAngle(end, radius, center) );
  return this.getCirclePath(points, radius, (degree < 180) ? 0 : 1);
}
			
function getCirclePath(points, radius, clockWise) {
  return ['M', points[0].x, points[0].y,
          'A', radius, radius, 0, 0, clockWise, points[1].x, points[1].y,
          'A', radius, radius, 0, 0, clockWise, points[2].x, points[2].y,
          'A', radius, radius, 0, 0, clockWise, points[3].x, points[3].y
         ].join(' ');
}
			
function getLocationFromAngle(degree, radius, center) {
  var radian = (degree * Math.PI) / 180;
  return {
    x : Math.cos(radian) * radius + center.x,
    y : Math.sin(radian) * radius + center.y
  }
}
			
document.getElementById("arc1").setAttribute("d", getPathArc({x:250,y:250}, 90, 90, 200));
document.getElementById("arc2").setAttribute("d", getPathArc({x:250,y:250}, 70, 70, 200));
<svg width="500" height="500">
  <path id="arc1" fill="none" stroke="green" stroke-width="8" />
  <path id="arc2" fill="none" stroke="red" stroke-width="3" />
</svg>

标签:javascript,path,svg,circle,angle
来源: https://codeday.me/bug/20190608/1196551.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有