HTML帆布/Trix.js根据第二层形状在第一层(由多个形状组成)上应用夹子路径和不透明度

发布于 2025-02-13 03:53:48 字数 637 浏览 2 评论 0 原文

html帆布或三个

。解决方案,很可能是因为我是三分之二/html帆布的新手,这是关于如何接近这一点的建议。

上下文:这是演示文稿网站上的动画,当动画启动层时,在动画结束时,上下旋转并旋转旋转,用户可以悬停在形状的顶部,而该区域徘徊在第一层(一个带有点的)将点推在轴上。

我的问题:

  1. 如何用圆角绘制等边三角形并添加光泽效果?(我搜索了文档并乘以答案但找不到解决方案),
  2. 我设法构建了第一层的功能作为一个平方并整合了悬停效果,但是我找不到使第一层作物/剪辑路径/减少未包含在顶层阴影中的点的不透明度的解决方案。 所以我的问题是,如何使底层点样式取决于顶层的克隆?
  3. 这是正确的方法吗?我计划了:创建顶层三角形,创建底层作为点正方形,克隆在点的底部正方形的顶部三角形,然后将其位置稍微移动以表示阴影,然后循环穿过点,然后检查它们是否在克隆中顶层三角形(在这里,我可以在内部/外部/靠近三角形的克隆的点上使用不透明的夹子和剪贴路径/农作物)。
  4. 对于我需要的东西太多了,我应该尝试使用常规的HTML帆布吗?

谢谢您的时间和友善!一个显示如何开始或概念证明的代码样本将非常有帮助。

HTML Canvas or Three.js experts,

I have a task this is very similar to 1 and I have big difficulties in finding a solution, most probably because I am a newbie in THREE.js/HTML Canvas, a suggestion on how to approach this would be very helpful.

Context: this is an animation on a presentation website, when the animation starts the layers pivot up and down and rotate at the end, when the animation finishes, users can hover on top of the shape and the zone hovered on the first layer (the one with dots) pushes the dots away on the axis.

My questions:

  1. How to draw an equilateral triangle with rounded corners and add that glow effect? (I searched the documentation and multiply answers but could not find a solution)
  2. I managed to build the functionality of the first layer as a square of dots and integrated the hover effect, but I could not find a solution to make the first layer crop/clip-path/reduce the opacity of the dots that are not included in the shadow of the top layer. So my question is, how to make the bottom layer dots style depend on the clone of the top layer?
  3. Is this the right approach? I planned this: Create the top layer triangle, create the bottom layer as a square of dots, clone the top layer triangle on top of the bottom square of dots and move its position a little to represent a shadow, then loop through the dots and check if they are inside the clone of the top layer triangle (here I can play with opacities and clip paths/crops on the dots inside/outside/close to the clone of the triangle).
  4. Is three.js too much for what I need, should I try to use a regular HTML Canvas?

Thank you for your time and kindness! A code sample that shows how to start or a proof of concept would be very helpful.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

李不 2025-02-20 03:53:48

我会说使用三分。一个普通的html < canvas> 元素与它的图形方法结合使用,将正确地做到这一点。

但是 - 开箱即用 CanvasRenderingContext2d 没有内置的方法可以圆角。这是必须使用一些三角学完成的事情。

为了获得更好的图片,可以说我们有一个三角形的要点:

a =(50,50); b =(250,100); C =(50,350)

这不是等边三角形,而是该概念当然适用于任何三角形。
在屏幕上,这将类似于这样的形状:

”“

如果考虑到它,请在点上有一个圆角 b ,必须有一条曲线从侧面 c 到点 b 到侧面 a 。但是在哪里?

让我们在 b 点上覆盖半径20的绿色圆圈。

我们可以看到圆的相交与侧面 c 和side a 应该分别是曲线的起点和终点。由于半径为20,我们需要从点 b 沿点 a 的方向传播20个像素,而同样从点 b 也可以从点方向 c 。该方向由两个特定点之间的角度给出,可以使用 MATH.ATAN2(pointb.x-pointa.x,pointb.y-pointa.y)方法获得。

如果我们计算这两个点 - 并重复三角形的其余两个顶点的过程 - 并使用 bezierCurveto()方法绘制曲线,我们终于有了圆角。

就是您问题的第一部分。

为了使三角形的大纲具有发光的外观,我们可以使用内置的过滤器效果。 blur()过滤器模仿光芒很好。背景中三角形的重复模式也不难。画布上的封闭形状可以通过使用 createpattern()方法创建的自定义模式填充。我们需要做的就是在中间用黑色圆圈绘制一个无缝的瓷砖。为此,我们可以使用 document.createelement(“ Canvas”)创建一个临时< canvas> 均等宽度和高度的要素,并使用绘制一个圆圈arc()方法。

这是一个完整的示例:

let triangle = {
  a: {
    x: 50,
    y: 50
  },
  b: {
    x: 250,
    y: 100
  },
  c: {
    x: 50,
    y: 350
  }
};

let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let cornerRadius = 60;

let corners = [
  [triangle.a, triangle.b, triangle.c],
  [triangle.b, triangle.c, triangle.a],
  [triangle.c, triangle.a, triangle.b]
]

function drawTriangle(offsetX = 0, offsetY = 0) {
  ctx.beginPath();
  let angle, corner, pA, pB;
  let segments = [];

  for (let a = 0; a < corners.length; a++) {
    corner = corners[a];
    angle = Math.atan2(corner[1].x - corner[0].x, corner[1].y - corner[0].y) + Math.PI;
    pA = {
      x: corner[1].x + offsetX + Math.sin(angle) * cornerRadius,
      y: corner[1].y + offsetY + Math.cos(angle) * cornerRadius
    }

    angle = Math.atan2(corner[1].x - corner[2].x, corner[1].y - corner[2].y) + Math.PI;

    pB = {
      x: corner[1].x + offsetX + Math.sin(angle) * cornerRadius,
      y: corner[1].y + offsetY + Math.cos(angle) * cornerRadius
    };
    segments.push(pA)
    segments.push({
      x: corner[1].x + offsetX,
      y: corner[1].y + offsetY
    });
    segments.push(pB);
  }

  let temp;
  ctx.moveTo(segments[0].x, segments[0].y);
  for (let a = 0; a < segments.length; a += 3) {
    temp = a + 3 == segments.length ? 0 : a + 3;
    ctx.bezierCurveTo(segments[a + 1].x, segments[a + 1].y, segments[a + 1].x, segments[a + 1].y, segments[a + 2].x, segments[a + 2].y);
    ctx.lineTo(segments[temp].x, segments[temp].y);
  }

  ctx.closePath();
}

function createPattern() {
  let tempCanvas = document.createElement("canvas");
  let tempContext = tempCanvas.getContext("2d");
  let radius = 3;
  tempCanvas.width = 12;
  tempCanvas.height = 12;
  tempContext.beginPath();
  tempContext.arc(tempCanvas.width / 2, tempCanvas.height / 2, radius, 0, 2 * Math.PI);
  tempContext.fill();
  tempContext.closePath();

  return ctx.createPattern(tempCanvas, 'repeat');
}

let rad = 0;
let radius = 25;
let fillPattern = createPattern();

function animate() {
  ctx.fillStyle = "#ecebcc";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = fillPattern;
  ctx.save();
  ctx.translate(Math.sin(rad) * radius, Math.cos(rad) * radius);
  drawTriangle();
  ctx.fill();
  ctx.restore();
  ctx.lineWidth = 7;
  ctx.strokeStyle = "#378f43"
  ctx.filter = "blur(10px)";
  drawTriangle();
  ctx.stroke();
  ctx.filter = "none";
  ctx.lineWidth = 1;
  drawTriangle();
  ctx.stroke();
  rad += Math.PI / 180;
  requestAnimationFrame(animate);
}

requestAnimationFrame(animate);
<canvas id="canvas" width="400" height="400"></canvas>

I'd say using three.js for this task is a bit too much. A plain HTML <canvas> element in conjunction with it's drawing methods will do it just right.

Nevertheless - out of the box the CanvasRenderingContext2d does not have a built-in method to round corners. This is something that has to be done using a bit of trigonometry.

To get a better picture let's say we have a triangle with the points:

A=(50,50) ; B=(250,100) ; C=(50,350)

This is not an equilateral triangle but the concept applies to any triangle of course.
On screen this will resemble a shape like this:

If we think about it, to have a rounded corner at point B, there must be a curve going somewhere from side c, through point B to side a. But where?

Let's overlay a green circle of radius 20 at point B.

We can see that the intersection of the circle with side c and side a should be the start and respectively the end point of the curve. As the radius is 20, we need to travel 20 pixels from point B in the direction of point A and likewise 20 pixels from point B in direction of point C. The direction is given by the angle in between two particular points and can be obtained using the Math.atan2(pointB.x-pointA.x, pointB.y-pointA.y) method.

If we calculate those two points - and repeat the process for the remaining two vertices of the triangle - and draw the curves using the bezierCurveTo() method we finally have rounded corners.

That's it for the first part of your question.

To give the outlines of the triangle a glowing look, we can use the built-in filter effects. A blur() filter mimics a glow just fine. The repeating pattern of the triangle in the background isn't that hard to do either. A closed shape on the canvas can be filled by a custom pattern, created using the createPattern() method. All we need to do is draw a seamless tile with a black circle in the middle. To do this we can create a temporary <canvas> element of equal width and height using document.createElement("canvas") and draw a circle using the arc() method.

Here is the complete example:

let triangle = {
  a: {
    x: 50,
    y: 50
  },
  b: {
    x: 250,
    y: 100
  },
  c: {
    x: 50,
    y: 350
  }
};

let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let cornerRadius = 60;

let corners = [
  [triangle.a, triangle.b, triangle.c],
  [triangle.b, triangle.c, triangle.a],
  [triangle.c, triangle.a, triangle.b]
]

function drawTriangle(offsetX = 0, offsetY = 0) {
  ctx.beginPath();
  let angle, corner, pA, pB;
  let segments = [];

  for (let a = 0; a < corners.length; a++) {
    corner = corners[a];
    angle = Math.atan2(corner[1].x - corner[0].x, corner[1].y - corner[0].y) + Math.PI;
    pA = {
      x: corner[1].x + offsetX + Math.sin(angle) * cornerRadius,
      y: corner[1].y + offsetY + Math.cos(angle) * cornerRadius
    }

    angle = Math.atan2(corner[1].x - corner[2].x, corner[1].y - corner[2].y) + Math.PI;

    pB = {
      x: corner[1].x + offsetX + Math.sin(angle) * cornerRadius,
      y: corner[1].y + offsetY + Math.cos(angle) * cornerRadius
    };
    segments.push(pA)
    segments.push({
      x: corner[1].x + offsetX,
      y: corner[1].y + offsetY
    });
    segments.push(pB);
  }

  let temp;
  ctx.moveTo(segments[0].x, segments[0].y);
  for (let a = 0; a < segments.length; a += 3) {
    temp = a + 3 == segments.length ? 0 : a + 3;
    ctx.bezierCurveTo(segments[a + 1].x, segments[a + 1].y, segments[a + 1].x, segments[a + 1].y, segments[a + 2].x, segments[a + 2].y);
    ctx.lineTo(segments[temp].x, segments[temp].y);
  }

  ctx.closePath();
}

function createPattern() {
  let tempCanvas = document.createElement("canvas");
  let tempContext = tempCanvas.getContext("2d");
  let radius = 3;
  tempCanvas.width = 12;
  tempCanvas.height = 12;
  tempContext.beginPath();
  tempContext.arc(tempCanvas.width / 2, tempCanvas.height / 2, radius, 0, 2 * Math.PI);
  tempContext.fill();
  tempContext.closePath();

  return ctx.createPattern(tempCanvas, 'repeat');
}

let rad = 0;
let radius = 25;
let fillPattern = createPattern();

function animate() {
  ctx.fillStyle = "#ecebcc";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = fillPattern;
  ctx.save();
  ctx.translate(Math.sin(rad) * radius, Math.cos(rad) * radius);
  drawTriangle();
  ctx.fill();
  ctx.restore();
  ctx.lineWidth = 7;
  ctx.strokeStyle = "#378f43"
  ctx.filter = "blur(10px)";
  drawTriangle();
  ctx.stroke();
  ctx.filter = "none";
  ctx.lineWidth = 1;
  drawTriangle();
  ctx.stroke();
  rad += Math.PI / 180;
  requestAnimationFrame(animate);
}

requestAnimationFrame(animate);
<canvas id="canvas" width="400" height="400"></canvas>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文