如何创建始终打开到固定点的圆弧
How to Create an Arc that always opens to a fixed point
我正在尝试在 canvas 上创建 向日葵效果,带有弧线,但我的几何技能生疏了。
首先,我在 canvas、Origin (X1, Y1) 中间某处创建了一个原点
然后我创建获取鼠标位置 Mp (Xm, Ym)
现在如果我从 Origin 到 Mp 做一条假想线,那么 Mp 应该是用一个新的较小原点平分圆弧的点,该原点位于 Origin 的方向,这将定义具有静态半径(比如 20)的圆弧。所有三个点 Origin、Mp 和较小的 Radius 应该形成一条直线。
我希望它以静态半径(比如 20)穿过圆弧的中心,而不管鼠标离原点有多远。
所以,如果你想象一个时钟。如果手连接的中间部分是Origin。
- 如果鼠标在 3 点钟位置,弧形看起来像一个“)”
- 如果鼠标在 9 点钟位置,弧形看起来像一个“(”
- 如果鼠标在 12 点钟位置,如果旋转 90°,圆弧看起来像一个“(”
- 如果鼠标在 6 点钟位置,如果旋转 270°,圆弧看起来像一个“(”
- 等...
并且鼠标位于该弧形的顶部。
对于我的问题,具体来说,与其说是如何获得积分、鼠标事件或其他任何问题,不如说是假设我有 {X1,Y1} 和 {Xm,Ym},那么制作弧线所需的数学是什么如上所述?
或者对于 JS/jQuery 专家,arc() 参数?
编辑:一个非常糟糕的 photoshop 渲染
右下角添加了一个鼠标,一般显示绘制 arc/curve 时鼠标指针所在的位置。
最简单的方法就是调整圆弧指令的起止角度
你可以画一系列弧线来形成你的花。
提示:如果你想让你的花瓣不那么圆,更弯曲,你可以使用 quadraticCurveTo
而不是弧线来绘制花瓣的外侧。
祝你项目顺利!
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var cx=150;
var cy=150;
var radius=50;
var PI=Math.PI;
var startAngle=0-PI/8;
var sweepAngle=PI/4;
var nextTime=0;
var delay=250;
requestAnimationFrame(animate);
function draw(){
ctx.clearRect(0,0,cw,ch);
ctx.beginPath();
ctx.arc(cx,cy,5,0,PI*2);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(cx,cy,radius,startAngle,startAngle+sweepAngle);
ctx.stroke();
}
function animate(time){
requestAnimationFrame(animate);
if(time>nextTime){
draw();
startAngle+=PI*2/30;
nextTime+=delay;
}
}
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
<canvas id="canvas" width=300 height=300></canvas>
[根据更多信息添加]
是的,我想你明白了!
从鼠标位置开始mcx,mcy
。
定义小圆心与鼠标位置的夹角radianAngle
。
定义小中心点与鼠标中心点的距离radius
。
计算小圆的圆心:
var scx = mcx + radius*Math.cos(radianAngle);
var scy = mcy + radius*Math.sin(radianAngle);
定义小圆的半径smallRadius
。
在较小的圆弧上定义您想要的总扫描角度 sweepAngle
。
定义小圆弧的起点和终点角度。这实际上很容易,因为您希望鼠标点处的小圆弧为 "point"。提示:小圆弧的中心必须始终位于 radianAngle
的中点。因此,startingAngle
= ( radianAngle - sweepAngle/2
.
所以最后你的 "points" 与鼠标的小角度变成了:
ctx.arc( scx,scy, smallRadius, startingAngle, startingAngle+sweepAngle );
干杯!
添加只是因为:
$(document).ready(function() {
var canvas = $('#canvas');
function getPosition(mouseEvent) {
var x, y;
x = mouseEvent.clientX;
y = mouseEvent.clientY;
return {
X: x - canvas.offset().left,
Y: y - canvas.offset().top
};
}
$('#canvas').mousemove(function(e) {
var origin = {
x: 325,
y: 100
};
var posit = getPosition(e)
var degrees = Math.PI /
180;
var plotR = {
X: 0,
Y: 0
};
var radius = 15;
var curveDeg = 65;
var context = $('#canvas').get(0).getContext('2d');
if (posit.X >= origin.x && posit.Y <= origin.y) {
quadrant = 1;
} else if (posit.X >= origin.x && posit.Y >= origin.y) {
quadrant = 2;
} else if (posit.X < origin.x && posit.Y >= origin.y) {
quadrant = 3;
} else {
quadrant = 4;
}
deltaY = posit.Y - origin.y;
deltaX = posit.X - origin.x;
if (deltaX == 0) {
distance = deltaY;
plotR.X = origin.x;
switch (quadrant) {
case 2:
case 3:
plotR.Y = posit.Y - radius;
break;
case 1:
case 4:
default:
plotR.Y = posit.Y + radius;
break;
}
} else {
distance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
slope = deltaY / deltaX;
delta = radius / (Math.sqrt(1 + Math.pow(slope, 2)));
switch (quadrant) {
case 1:
plotR.Y = posit.Y - slope * delta;
plotR.X = posit.X - delta;
break;
case 2:
plotR.Y = posit.Y - slope * delta;
plotR.X = posit.X - delta;
break;
case 3:
plotR.Y = posit.Y + slope * delta;
plotR.X = posit.X + delta;
break;
case 4:
default:
plotR.Y = posit.Y + slope * delta;
plotR.X = posit.X + delta;
break;
}
}
startAngle = Math.acos(deltaX / distance);
if (quadrant == 1 || quadrant == 4) startAngle = -startAngle;
context.clearRect(0, 0, 900, 400);
// Draw Origin Point for reference, but not for production
context.beginPath();
context.lineWidth = 1;
context.fillStyle = "#0000FF";
context.strokeStyle = "#0000FF";
context.arc(origin.x, origin.y, 3, 0, 2 * Math.PI, true);
context.fill();
// Drawn Calculated Origin point offset from Mouse in the direction of Origin Point
context.beginPath();
context.lineWidth = 1;
context.fillStyle = "#00FF00";
context.strokeStyle = "#00FF00";
context.arc(plotR.X, plotR.Y, 3, 0, 2 * Math.PI, true);
context.fill();
// Draw 'Sunflower' Curve
context.beginPath();
context.lineCap = 'round';
context.lineWidth = 3;
context.strokeStyle = "#FF0000";
context.arc(plotR.X, plotR.Y, radius, startAngle - (curveDeg * degrees / 2), startAngle + (curveDeg * degrees / 2), false);
context.stroke();
return;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas" width="650" height="200" style=" border: 1px #000 solid"></canvas>
我正在尝试在 canvas 上创建 向日葵效果,带有弧线,但我的几何技能生疏了。
首先,我在 canvas、Origin (X1, Y1) 中间某处创建了一个原点 然后我创建获取鼠标位置 Mp (Xm, Ym)
现在如果我从 Origin 到 Mp 做一条假想线,那么 Mp 应该是用一个新的较小原点平分圆弧的点,该原点位于 Origin 的方向,这将定义具有静态半径(比如 20)的圆弧。所有三个点 Origin、Mp 和较小的 Radius 应该形成一条直线。
我希望它以静态半径(比如 20)穿过圆弧的中心,而不管鼠标离原点有多远。
所以,如果你想象一个时钟。如果手连接的中间部分是Origin。
- 如果鼠标在 3 点钟位置,弧形看起来像一个“)”
- 如果鼠标在 9 点钟位置,弧形看起来像一个“(”
- 如果鼠标在 12 点钟位置,如果旋转 90°,圆弧看起来像一个“(”
- 如果鼠标在 6 点钟位置,如果旋转 270°,圆弧看起来像一个“(”
- 等...
并且鼠标位于该弧形的顶部。
对于我的问题,具体来说,与其说是如何获得积分、鼠标事件或其他任何问题,不如说是假设我有 {X1,Y1} 和 {Xm,Ym},那么制作弧线所需的数学是什么如上所述?
或者对于 JS/jQuery 专家,arc() 参数?
编辑:一个非常糟糕的 photoshop 渲染
右下角添加了一个鼠标,一般显示绘制 arc/curve 时鼠标指针所在的位置。
最简单的方法就是调整圆弧指令的起止角度
你可以画一系列弧线来形成你的花。
提示:如果你想让你的花瓣不那么圆,更弯曲,你可以使用 quadraticCurveTo
而不是弧线来绘制花瓣的外侧。
祝你项目顺利!
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var cx=150;
var cy=150;
var radius=50;
var PI=Math.PI;
var startAngle=0-PI/8;
var sweepAngle=PI/4;
var nextTime=0;
var delay=250;
requestAnimationFrame(animate);
function draw(){
ctx.clearRect(0,0,cw,ch);
ctx.beginPath();
ctx.arc(cx,cy,5,0,PI*2);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(cx,cy,radius,startAngle,startAngle+sweepAngle);
ctx.stroke();
}
function animate(time){
requestAnimationFrame(animate);
if(time>nextTime){
draw();
startAngle+=PI*2/30;
nextTime+=delay;
}
}
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
<canvas id="canvas" width=300 height=300></canvas>
[根据更多信息添加]
是的,我想你明白了!
从鼠标位置开始mcx,mcy
。
定义小圆心与鼠标位置的夹角radianAngle
。
定义小中心点与鼠标中心点的距离radius
。
计算小圆的圆心:
var scx = mcx + radius*Math.cos(radianAngle);
var scy = mcy + radius*Math.sin(radianAngle);
定义小圆的半径smallRadius
。
在较小的圆弧上定义您想要的总扫描角度 sweepAngle
。
定义小圆弧的起点和终点角度。这实际上很容易,因为您希望鼠标点处的小圆弧为 "point"。提示:小圆弧的中心必须始终位于 radianAngle
的中点。因此,startingAngle
= ( radianAngle - sweepAngle/2
.
所以最后你的 "points" 与鼠标的小角度变成了:
ctx.arc( scx,scy, smallRadius, startingAngle, startingAngle+sweepAngle );
干杯!
添加只是因为:
$(document).ready(function() {
var canvas = $('#canvas');
function getPosition(mouseEvent) {
var x, y;
x = mouseEvent.clientX;
y = mouseEvent.clientY;
return {
X: x - canvas.offset().left,
Y: y - canvas.offset().top
};
}
$('#canvas').mousemove(function(e) {
var origin = {
x: 325,
y: 100
};
var posit = getPosition(e)
var degrees = Math.PI /
180;
var plotR = {
X: 0,
Y: 0
};
var radius = 15;
var curveDeg = 65;
var context = $('#canvas').get(0).getContext('2d');
if (posit.X >= origin.x && posit.Y <= origin.y) {
quadrant = 1;
} else if (posit.X >= origin.x && posit.Y >= origin.y) {
quadrant = 2;
} else if (posit.X < origin.x && posit.Y >= origin.y) {
quadrant = 3;
} else {
quadrant = 4;
}
deltaY = posit.Y - origin.y;
deltaX = posit.X - origin.x;
if (deltaX == 0) {
distance = deltaY;
plotR.X = origin.x;
switch (quadrant) {
case 2:
case 3:
plotR.Y = posit.Y - radius;
break;
case 1:
case 4:
default:
plotR.Y = posit.Y + radius;
break;
}
} else {
distance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
slope = deltaY / deltaX;
delta = radius / (Math.sqrt(1 + Math.pow(slope, 2)));
switch (quadrant) {
case 1:
plotR.Y = posit.Y - slope * delta;
plotR.X = posit.X - delta;
break;
case 2:
plotR.Y = posit.Y - slope * delta;
plotR.X = posit.X - delta;
break;
case 3:
plotR.Y = posit.Y + slope * delta;
plotR.X = posit.X + delta;
break;
case 4:
default:
plotR.Y = posit.Y + slope * delta;
plotR.X = posit.X + delta;
break;
}
}
startAngle = Math.acos(deltaX / distance);
if (quadrant == 1 || quadrant == 4) startAngle = -startAngle;
context.clearRect(0, 0, 900, 400);
// Draw Origin Point for reference, but not for production
context.beginPath();
context.lineWidth = 1;
context.fillStyle = "#0000FF";
context.strokeStyle = "#0000FF";
context.arc(origin.x, origin.y, 3, 0, 2 * Math.PI, true);
context.fill();
// Drawn Calculated Origin point offset from Mouse in the direction of Origin Point
context.beginPath();
context.lineWidth = 1;
context.fillStyle = "#00FF00";
context.strokeStyle = "#00FF00";
context.arc(plotR.X, plotR.Y, 3, 0, 2 * Math.PI, true);
context.fill();
// Draw 'Sunflower' Curve
context.beginPath();
context.lineCap = 'round';
context.lineWidth = 3;
context.strokeStyle = "#FF0000";
context.arc(plotR.X, plotR.Y, radius, startAngle - (curveDeg * degrees / 2), startAngle + (curveDeg * degrees / 2), false);
context.stroke();
return;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas" width="650" height="200" style=" border: 1px #000 solid"></canvas>