从圆形创建平面阴影效果

问题描述 投票:0回答:1

我尝试过一些三角函数并使用极坐标到笛卡尔坐标,但最终对如何在 JS 中实现效果有点迷失。目前我一直在使用 p5.js,但对其他选项持开放态度。

本质上,我想在屏幕上有一个圆圈,并且有一个不可见的光在圆圈上投射出阴影。最终我希望“光”和圆圈位置可以移动,但现在我很难创建阴影的形状。

Screenshot of static effect

我已经可以从光标的一点创建圆的切线,但不能在其之外“投射阴影”。

function setup() {
  createCanvas(windowWidth, windowHeight);
}

function draw() {
  background("#9B009D");

  const circleCenterX = width / 2;
  const circleCenterY = height / 2;
  const circleRadius = 200;
  

  if (mouseX !== 0 || mouseY !== 0) {
    drawTangentLines(mouseX, mouseY, circleCenterX, circleCenterY, circleRadius);
    
  fill("#FF7000");
  noStroke;
  ellipse(circleCenterX, circleCenterY, circleRadius * 2);
  }
}

function drawTangentLines(pointX, pointY, centerX, centerY, radius) {
  const dx = pointX - centerX;
  const dy = pointY - centerY;
  const directDistance = sqrt(dx * dx + dy * dy);

  if (directDistance < radius) {
    // If the point is inside the circle, do not draw tangent lines.
    return;
  }

  // Determine angles for the tangent points
  const angleToCenter = atan2(dy, dx);
  const angleFromTangent = acos(radius / directDistance);  // Proper angle to tangent points

  // Calculate tangents
  const angle1 = angleToCenter + angleFromTangent;
  const angle2 = angleToCenter - angleFromTangent;

  // Calculate tangent points on the circle
  const tanPoint1X = centerX + radius * cos(angle1);
  const tanPoint1Y = centerY + radius * sin(angle1);
  const tanPoint2X = centerX + radius * cos(angle2);
  const tanPoint2Y = centerY + radius * sin(angle2);

  // Draw lines from external point to tangent points
  line(pointX, pointY, tanPoint1X, tanPoint1Y);
  line(pointX, pointY, tanPoint2X, tanPoint2Y);
  noStroke();
  fill("white");
  beginShape();
      vertex(pointX, pointY);
      vertex(tanPoint1X, tanPoint1Y);
      vertex(tanPoint2X, tanPoint2Y);
  endShape(CLOSE);
  
  
}

function mouseMoved() {
  redraw();
}
javascript geometry trigonometry p5.js shadow
1个回答
1
投票

最终到达那里,这并不微妙,只是通过一些简单的乘法将点扩展到画布之外并填充该区域!

    function setup() {
  createCanvas(windowWidth, windowHeight);
}

function draw() {
  background("#9B009D");

  const circleCenterX = width / 2;
  const circleCenterY = height / 2;
  const circleRadius = 200;
  

  if (mouseX !== 0 || mouseY !== 0) {
    drawTangentLines(mouseX, mouseY, circleCenterX, circleCenterY, circleRadius);
    
  fill("#FF7000");
  //noStroke;
  ellipse(circleCenterX, circleCenterY, circleRadius * 2);
  }
}

function drawTangentLines(pointX, pointY, centerX, centerY, radius) {
  const dx = pointX - centerX;
  const dy = pointY - centerY;
  const directDistance = sqrt(dx * dx + dy * dy);

  if (directDistance < radius) {
    // If the point is inside the circle, do not draw tangent lines.
    return;
  }

  // Determine angles for the tangent points
  const angleToCenter = atan2(dy, dx);
  const angleFromTangent = acos(radius / directDistance);  // Proper angle to tangent points

  // Calculate tangents
  const angle1 = angleToCenter + angleFromTangent;
  const angle2 = angleToCenter - angleFromTangent;

  // Calculate tangent points on the circle
  const tanPoint1X = centerX + radius * cos(angle1);
  const tanPoint1Y = centerY + radius * sin(angle1);
  const tanPoint2X = centerX + radius * cos(angle2);
  const tanPoint2Y = centerY + radius * sin(angle2);
  const diff1X = tanPoint1X - pointX;
  const diff1Y = tanPoint1Y - pointY;
  const diff2X = tanPoint2X - pointX;
  const diff2Y = tanPoint2Y - pointY;

  // Draw lines from external point to tangent points
  line(pointX, pointY, tanPoint1X, tanPoint1Y);
  line(pointX, pointY, tanPoint2X, tanPoint2Y);
  line(tanPoint1X, tanPoint1Y, tanPoint1X+(1000* diff1X), tanPoint1Y+(1000*diff1Y));
    line(tanPoint2X, tanPoint2Y, tanPoint2X+(1000* diff2X), tanPoint2Y+(1000*diff2Y));
  //noStroke();
  fill("white");
  beginShape();
      vertex(tanPoint1X, tanPoint1Y);
      vertex(tanPoint1X+(1000* diff1X),tanPoint1Y+(1000*diff1Y));
      vertex(tanPoint2X+(1000* diff2X),tanPoint2Y+(1000*diff2Y));
      vertex(tanPoint2X, tanPoint2Y);
  endShape(CLOSE);
  
  
}

function mouseMoved() {
  redraw();
}
© www.soinside.com 2019 - 2024. All rights reserved.