javascript - 如何在圆内画三 Angular 形指针

标签 javascript html canvas trigonometry

我意识到这是一个简单的三 Angular 函数问题,但我的高中现在让我不及格。

给定一个 Angular ,我已将其转换为弧度以获得第一个点。如何计算要在 Canvas 上绘制的三 Angular 形的接下来的两个点,以便使小三 Angular 形始终指向圆之外。假设我已经画了一个给定半径的圆。现在我想要一个函数来绘制一个三 Angular 形,该三 Angular 形位于其内部圆的边缘,无论 Angular 如何,该三 Angular 形都指向外部。 (可以这么说,沿着边缘)

function drawPointerTriangle(ctx, angle){
    var radians = angle * (Math.PI/180)
    var startX = this.radius + this.radius/1.34 * Math.cos(radians)
    var startY = this.radius - this.radius/1.34 * Math.sin(radians)
    // This gives me my starting point on the outer edge of the circle, plotted at the angle I need    
    ctx.moveTo(startX, startY);

   // HOW DO I THEN CALCULATE x1,y1 and x2, y2.  So that no matter what angle I enter into this function, the arrow/triangle always points outwards to the circle.
    ctx.lineTo(x1, y1);
    ctx.lineTo(x2, y2);


}

示例 enter image description here

最佳答案

你没有说你想画什么类型的三 Angular 形,所以我认为它是一个等边三 Angular 形。

看看这张图片(来源 here )

enter image description here

我将从右上角到右下角逆时针方向调用 3 个点 p1、p2、p3。

可以很容易地计算出三 Angular 形三点在原点与三 Angular 形质心重合的坐标系中的坐标。

给定一个属于圆边缘的点和我们刚刚计算的点 p1,我们可以计算从主坐标系到三 Angular 形坐标系的平移参数。然后,我们只需将另外两个点的坐标平移回我们的主坐标系即可。即 (x1,y1) 和 (x2,y2)。

您可以查看下面基于您的代码的演示。

const w = 300;
const h = 300;

function calculateTrianglePoints(angle, width) {
  let r = width / Math.sqrt(3);
  let firstPoint = [
    r * Math.cos(angle),
    r * Math.sin(angle),
  ]

  let secondPoint = [
    r * Math.cos(angle + 2 * Math.PI / 3),
    r * Math.sin(angle + 2 * Math.PI / 3),
  ]

  let thirdPoint = [
    r * Math.cos(angle + 4 * Math.PI / 3),
    r * Math.sin(angle + 4 * Math.PI / 3),
  ]

  return [firstPoint, secondPoint, thirdPoint]
}

const radius = 100
const triangleWidth = 20;

function drawPointerTriangle(ctx, angle) {
  var radians = angle * (Math.PI / 180)
  var startX = radius * Math.cos(radians)
  var startY = radius * Math.sin(radians)
  var [pt0, pt1, pt2] = calculateTrianglePoints(radians, triangleWidth);
  var delta = [
    startX - pt0[0],
    startY - pt0[1],
  ]

  pt1[0] = pt1[0] + delta[0]
  pt1[1] = pt1[1] + delta[1]
  pt2[0] = pt2[0] + delta[0]
  pt2[1] = pt2[1] + delta[1]
  ctx.beginPath();
  // This gives me my starting point on the outer edge of the circle, plotted at the angle I need    
  ctx.moveTo(startX, startY);

  [x1, y1] = pt1;
  [x2, y2] = pt2;
  // HOW DO I THEN CALCULATE x1,y1 and x2, y2.  So that no matter what angle I enter into this function, the arrow/triangle always points outwards to the circle.
  ctx.lineTo(x1, y1);
  ctx.lineTo(x2, y2);
  ctx.closePath();
  ctx.fillStyle = '#FF0000';
  ctx.fill();
}

function drawCircle(ctx, radius) {
  ctx.beginPath();
  ctx.arc(0, 0, radius, 0, 2 * Math.PI);
  ctx.closePath();
  ctx.fillStyle = '#000';
  ctx.fill();
}

function clear(ctx) {
  ctx.fillStyle = '#fff';
  ctx.fillRect(-w / 2, -h / 2, w, h);
}

function normalizeAngle(pointCoordinate, angle) {
  const [x, y] = pointCoordinate;
  if (x > 0 && y > 0) return angle;
  else if (x > 0 && y < 0) return 360 + angle;
  else if (x < 0 && y < 0) return 180 - angle;
  else if (x < 0 && y > 0) return 180 - angle;
}

function getAngleFromPoint(point) {
  const [x, y] = point;
  if (x == 0 && y == 0) return 0;
  else if (x == 0) return 90 * (y > 0 ? 1 : -1);
  else if (y == 0) return 180 * (x >= 0 ? 0: 1);
  const radians = Math.asin(y / Math.sqrt(
    x ** 2 + y ** 2
  ))

  return normalizeAngle(point, radians / (Math.PI / 180))
}

document.addEventListener('DOMContentLoaded', function() {
  const canvas = document.querySelector('canvas');
  const angleText = document.querySelector('.angle');
  const ctx = canvas.getContext('2d');
  ctx.translate(w / 2, h / 2);
  drawCircle(ctx, radius);
  drawPointerTriangle(ctx, 0);
  canvas.addEventListener('mousemove', _.throttle(function(ev) {
    let mouseCoordinate = [
      ev.clientX - w / 2,
      ev.clientY - h / 2
    ]
    
    let degAngle = getAngleFromPoint(mouseCoordinate)

    clear(ctx);
    drawCircle(ctx, radius);
    drawPointerTriangle(ctx, degAngle)
    angleText.innerText = Math.floor((360 - degAngle)*100)/100;
  }, 15))
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>
<canvas width=300 height=300></canvas>
<div class="angle">0</div>

关于javascript - 如何在圆内画三 Angular 形指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61024053/

相关文章:

Jquery 表单,nnlimited 字段和每行验证

android - 凸路径 - 如何?

javascript - Angular4 - 如何使用 Karma 和 Jasmine 对指令进行单元测试

javascript - 通过 jquery 查找控件 ID 并将其传递给函数以切换它

javascript - 关闭控制流程

javascript - 使用 fabric.js 的 Canvas 全屏模式

javascript - 带有选项卡的 Twitter Bootstrap Modal 默认为第一个选项卡

javascript - 打印 Javascript 为空白,显示 : block/none

javascript - Canvas - 无法获取图像数据

javascript - mousedown 事件仅适用于第二次点击