Javascript 如何在画布上画六条半径对称的线?
我正在尝试在画布上构建一个雪花绘图应用程序,非常类似于此: 基本上,如果你画一个点,它应该在画布上以对称的圆形图案重复5次以上。下面是一个例子: 我知道如何告诉画布多次绘制一些东西,但我的数学技能有限,我想知道如何计算复制的5个点相对于原始点的位置 我在想,我必须找到画布的中间,并计算从中间到原始点的x和y位置的距离。在那之后,我假设如果我要从那个点画一个圆,可能我必须找到它的半径,然后。。。这是我的头开始冒烟的时候 我想知道我是否可以做一些类似于他们在这里所做的事情: 仅作为背景,我最初是从6张剪下来的画布开始的,其中5张是旋转的,并将复制第一张画布,但我意识到这种方法并没有真正起作用,部分原因是画布会稍微重叠(但也存在其他问题) 以下是我目前掌握的代码:Javascript 如何在画布上画六条半径对称的线?,javascript,math,html5-canvas,Javascript,Math,Html5 Canvas,我正在尝试在画布上构建一个雪花绘图应用程序,非常类似于此: 基本上,如果你画一个点,它应该在画布上以对称的圆形图案重复5次以上。下面是一个例子: 我知道如何告诉画布多次绘制一些东西,但我的数学技能有限,我想知道如何计算复制的5个点相对于原始点的位置 我在想,我必须找到画布的中间,并计算从中间到原始点的x和y位置的距离。在那之后,我假设如果我要从那个点画一个圆,可能我必须找到它的半径,然后。。。这是我的头开始冒烟的时候 我想知道我是否可以做一些类似于他们在这里所做的事情: 仅作为背景,我最初是
drawing = false;
startX = 0;
startY = 0;
imageData = null;
const canvas = document.getElementById("canvas");
canvas.addEventListener("mousedown", startPosition());
canvas.addEventListener("mouseup", endPosition());
canvas.addEventListener("mousemove", draw());
function startPosition(e) {
const canvas = this;
const ctx = canvas.getContext("2d");
startX = e.clientX;
startY = e.clientY;
imageData = ctx.getImageData(0,0,canvas.width,canvas.height);
drawing = true;
}
function endPosition(e) {
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
ctx.lineWidth = 4;
ctx.lineCap = "round";
ctx.moveTo(startX, startY);
ctx.lineTo(e.clientX, e.clientY);
ctx.strokeStyle = '#ffffff';
ctx.stroke();
ctx.beginPath();
drawing = false;
}
function draw(e) {
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
if(!drawing) {
return;
}
ctx.putImageData(imageData, 0, 0);
ctx.lineWidth = 4;
ctx.lineCap = "round";
ctx.moveTo(startX, startY);
ctx.lineTo(e.clientX, e.clientY);
ctx.strokeStyle = '#ffffff';
ctx.stroke();
ctx.beginPath();
ctx.moveTo(e.clientX, e.clientY);
//draw line 2
ctx.moveTo(startX - 50, startY - 50);
ctx.lineTo(e.clientX - 50, e.clientY - 50);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(e.clientX - 50, e.clientY - 50);
//draw line 3
ctx.moveTo(startX - 100, startY - 100);
ctx.lineTo(e.clientX - 100, e.clientY - 100);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(e.clientX - 100, e.clientY - 100);
}
围绕另一点旋转点的步骤
const center = {x: 100, y: 100}; // Point to rotate around
const point = {x: ?, y: ?}; // Point to rotate
const rotate = (Math.PI * 2) / 5; // Rotate 1/5th of 360
// Get the vector from center to point
const vx = point.x - center.x;
const vy = point.y - center.y;
// Get the transformation (2D uniform rotate)
const xAx = Math.cos(rotate);
const xAy = Math.sin(rotate);
// Transform the vector (rotates) and translate back to center
const tx = vx * xAx - vy * xAy + center.x;
const ty = vx * xAy + vy * xAx + center.y;
作为一项功能
function rotate(point, center, rotate, result = {}) {
const vx = point.x - center.x;
const vy = point.y - center.y;
const xAx = Math.cos(rotate);
const xAy = Math.sin(rotate);
result.x = vx * xAx - vy * xAy + center.x;
result.y = vx * xAy + vy * xAx + center.y;
return result;
}
使用上述功能从1创建5个点
const slices = 5; // number of rotations
const center = {x: 100, y: 100}; // center point
// Rotates point steps times around center
// Returns array of points
function rotateAll(point, steps, result = []) {
const ang = Math.PI * 2 / steps;
result.push(point); // Add first point
for (let rot = 1; rot < steps; rot++) { // Add remaining points
result.push(rotate(point, center, rot * ang));
}
return result;
}
// Usage
const points = rotateAll({x: 10, y: 20}, slices);
const slices=5;//旋转次数
常数中心={x:100,y:100};//中心点
//围绕中心旋转点步数次
//返回点的数组
函数rotateAll(点、步数、结果=[])){
常数ang=Math.PI*2/步;
result.push(point);//添加第一个点
对于(让rot=1;rot
关于数学:我想你想要12分,而不是6分。看看上面的“尖头”:每个端点有12个“副本”:每个分支的右侧6个,左侧6个。从数学上讲,需要围绕中心旋转60度生成5个点,并使用反射(在链接的雪花中,想象相对于垂直轴的反射,对应于(x,y)(-x,y))生成其他6个点
transformation。如果你只使用6个旋转版本,你会得到这样的结果。你不希望脚只放在每条腿的一侧。谢谢Andreas!是的,我明白你的意思。我的灵感来自Jaquie Lawson降临节日历中的雪花发生器,其中一个有6个部分,但每个部分在你绘制时都会反射自己,所以你以12结尾。你需要5次旋转,旋转六分之一个圆(PI/3
),因为有六个副本(但你已经有了原始点)。@AndrasDeak常量slices
定义了点数。底部片段。顶部片段有(Math.PI*2)/5;//旋转360度的1/5
这不可能是正确的。我不知道JS(?)但在我看来,切片
被作为步骤
传递到rotateAll
,所以你再次传递5
,进入const ang=Math.PI*2/步骤;
。这仍然意味着72度旋转,而不是60度旋转。你需要步骤
循环的迭代,但Math.PI*2/(步骤+1)
作为旋转角度。@AndrasDeak第一个值是任意的,可以是任何值。函数rotateAll
返回一个带有参数步数
点的数组。如果值步数
为5,则在圆周围有5个点等距分布,只有最后4个点是旋转的。太棒了,非常感谢@Blindman67!这个真漂亮!