【问题标题】:JS drawing a line from the edge of a circle to another circle edgeJS从一个圆的边缘画一条线到另一个圆的边缘
【发布时间】:2014-04-23 00:59:37
【问题描述】:

我正在尝试从 HTML5 画布中两个圆圈的边缘绘制一条线。所以,我知道两个圆心的坐标和它们的半径。

  1. 随机绘制的圆圈。
  2. 线应该从一个圆的边缘移动到另一个圆。

请帮忙!

附:对不起我的英语:)

更新:

我正在尝试这个,但是如何知道角度?

from_line_x = circle1.x + circle1.radius * Math.cos(Math.PI * angle);
from_line_y = circle1.y + cirlce1.radius * Math.sin(Math.PI * angle);
to_line_x = circle2.x - circle2.radius * Math.cos(Math.PI * angle);
to_line_y = circle2.y - circle2.radius * Math.sin(Math.PI * angle);

更新2:

我想我找到了如何找到角度。但是作为一个随机绘制的圆,绘制的线并不总是正确的。那么算法应该怎么看呢?

再次对不起我的英语。

【问题讨论】:

  • 圆的边是什么?一张小图会有所帮助。
  • 像这样:sayakhov.ru/media/uploads/example.png 和这个,但使用 HTML5 画布:jsfiddle.net/5YmJv
  • 响应您的更新,您不需要知道角度来计算线的端点。想象一条从一个中心延伸到另一个中心的线。这条线与线的每个端点相交。规范化这个向量,你可以使用它、圆的半径和圆心来计算线段的端点。请参阅我对@Tamura 解决方案的评论。
  • 我看到了你的评论,但我不明白如何为此编写代码:) 谢谢!

标签: javascript html canvas html5-canvas


【解决方案1】:

这是一个可以实现您所要求的解决方案。

我已经声明了 3 个“类”以使内容更清晰易读。首先,我定义了一个通用形状类。接下来,我定义了一个基本的圆形类。最后,我定义了一个 vec2 类。您可以像我所做的那样轻松扩展它,并添加从形状类继承的其他形状 - 即正方形三角形等。

我在随机位置和半径处创建 10 个圆。然后我在每个圆圈和它后面的圆圈之间画一条线。我没有为“环绕”的情况而烦恼,所以我画了 10 圈和 9 条线(我不从圈 9 画到圈 0)

我使用了一些 Tamura 留下的代码,因此熟悉的画布尺寸和 id。

<!doctype html>
<html>
<head>
<script>
function byId(e){return document.getElementById(e)}
window.addEventListener('load', onDocLoaded, false);

var shapeList = [];

function onDocLoaded()
{
    var i, n=10;
    var canvas = byId('myCanvas');

    for (i=0; i<n; i++)
    {
        shapeList[i] = new circle_t(Math.random()*578, Math.random()*400, Math.random()*30 + 20);
        shapeList[i].draw(canvas);
    }

    for (i=0; i<n-1; i++)
        draw_line2(shapeList[i].origX, shapeList[i].origY, shapeList[i].radius, shapeList[i+1].origX, shapeList[i+1].origY, shapeList[i+1].radius);
}   

var shape_t = function(x,y)
{
    this.origX = (x==undefined ? 0 : x);
    this.origY = (y==undefined ? 0 : y);
}
shape_t.prototype =
{
    origX:0, origY:0, typeString:'shape',
    setPos: function(x,y){this.x=x;this.y=y;},
    setType: function(typeString){this.typeString = typeString;},
    toString: function(){return this.typeString + " - " + this.origX + "," + this.origY;},
    draw: function(canElem){},
};

function circle_t(x,y,radius)
{
    this.origX = (x==undefined ? 0 : x);
    this.origY = (y==undefined ? 0 : y);
    this.radius = (radius==undefined ? 10 : radius);
    this.setType("circle");
}
circle_t.prototype = new shape_t();
circle_t.prototype.constructor = circle_t;
circle_t.prototype.draw = function(canElem, color)
{
    var ctx = canElem.getContext('2d');
    var col = 'black';
    if (color != undefined)
        col = color;
    drawCircle(this.origX, this.origY, this.radius, ctx, col);
}

circle_t.prototype.setRadius = function(radius)
{
    if (radius != undefined)
        this.radius = radius;
}

function drawCircle(x, y, radius, ctx, col)
{
    ctx.save();
    if (col == undefined)
        col = 'black';
    ctx.strokeStyle = col;
    ctx.lineWidth = 1;
    ctx.beginPath();
    ctx.arc(x,y,radius,(Math.PI/180)*0, (Math.PI/180)*360, false);
    ctx.stroke();
    ctx.closePath();
    ctx.restore();
}

// define a vec2 class to make vector maths easier (simpler to read)
function vec2(x,y)
{
    this.length = function()
    {
        return Math.sqrt((this.x * this.x) + (this.y*this.y));
    }
    this.normalize = function()
    {
        var scale = this.length();
        this.x /= scale;
        this.y /= scale;
    }
    this.x = x;
    this.y = y;
}

function draw_line2(center1_x, center1_y, radius1, center2_x, center2_y, radius2)
{
    var betweenVec = new vec2(center2_x - center1_x, center2_y - center1_y);
    betweenVec.normalize();

    var p1x = center1_x + (radius1 * betweenVec.x);
    var p1y = center1_y + (radius1 * betweenVec.y);

    var p2x = center2_x - (radius2 * betweenVec.x);
    var p2y = center2_y - (radius2 * betweenVec.y);

    var canvas = document.getElementById('myCanvas');
    var context = canvas.getContext('2d');
    context.beginPath();
        context.moveTo(p1x,p1y);
        context.lineTo(p2x,p2y);
    context.stroke();
}
</script>
</head>
<body>
    <canvas id="myCanvas" width="578" height="400"></canvas>
</body>
</html>

现场演示请看这里:http://jsfiddle.net/YYjYL/

【讨论】:

  • 非常感谢!这就是我所需要的。
  • 非常感谢,enhzflep,我大学已经很久没有代数了,懒得理清逻辑。你的代码帮助了我。
【解决方案2】:

3 步解决方案:
- 构建所有随机圆坐标 (x,y,r)。
- 在它们的中心之间画出你认为合适的所有线条。
- 画出所有的圆圈。

(!)

代码很简单:

http://jsbin.com/qutahatu/1/edit?js,output

var circles = [];

function createCircles(cnt) {
  circles = [];
  for (var i=0; i<cnt; i++) {
    var x = 5+ Math.random() *300;
    var y = 5+ Math.random() *300;
    var r = 20  + Math.random() *6;    
    circles.push({x:x,y:y,r:r});
  }
}

function drawLines() {
  var cnt= circles.length;
   ctx.strokeStyle = '#000';
  ctx.lineWidth = 2;
  ctx.beginPath();
  ctx.moveTo(circles[0].x, circles[0].y);
  for (var i=1; i<cnt; i++) {
     ctx.lineTo(circles[i].x, circles[i].y);
  }
  ctx.stroke(); 
}

function drawCircles() {
  var cnt= circles.length;
   ctx.fillStyle = '#4A8';
  for (var i=0; i<cnt; i++) {
     ctx.beginPath();
     ctx.arc(circles[i].x, circles[i].y, circles[i].r, 0, 6.282);
     ctx.fill();
  }
}

createCircles(4);
drawLines();
drawCircles();

【讨论】:

  • 另一种方式?我的意思是,我想要的是从圆的边缘开始的一条线,而不是从中心开始。
  • 就可以做到这一点,因为圆圈会隐藏圆圈下方的线部分。
  • @learning:这与问题关系不大! :-) 为避免矩形之间的碰撞,您必须测试这些碰撞并解决它们。如果您想正确处理多次碰撞的情况,这不是那么容易的问题。我做了一个简单的小演示让你开始,看看updateUsersjsbin.com/tomuzawusu/1/edit?js,output 祝你的项目好运!
  • @Learning:我在这里写了一篇关于动画的文章:codepen.io/gamealchemist/post/animationcanvas1
  • @Learning:谢谢。没时间看,不好意思。缩小您的问题范围并在 S.O. 上发布问题。如果你被卡住了。祝你好运。
【解决方案3】:

这里是 JSFIDDLE 链接:http://jsfiddle.net/WfF3v/1/。 这就是你想要的吗?

下面是JS代码:

function draw_circle(center_x, center_y){
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var centerX = center_x;
var centerY = center_y;
var radius = 70;

context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
}

function draw_line(center1_x, center1_y, center2_x, center2_y) {
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');

context.beginPath();
context.moveTo(center1_x, center1_y);
context.lineTo(center2_x, center2_y);
context.stroke();
}

draw_circle(100,100);
draw_circle(300,200);
draw_line(100,100,300,200);

【讨论】:

  • 我的 +1。很好的解决方案,尽管我注意到原始问题指出“edge of circle to another circle's edge”。如果你计算它们每个原点之间的单位向量,你可以用它来计算与轮廓的交点。在您的示例中,如果单位向量沿从 c1 的原点到 c2 的原点的方向延伸:lineEndpoint1 = circle1_origin + (unit_vector_between_origins * circle1_radius)lineEndpoint2 = circle2_origin - (unit_vector_between_origins * circle2_radius) 然后您可以使用在这两个计算出的 坐标之间画线。
  • 不,不是。我需要从圆圈的边缘,而不是从中心。从中心,我得到了 :) 但感谢您的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多