如何在画布上绘制线条 [英] How to draw the line in canvas

查看:193
本文介绍了如何在画布上绘制线条的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在画布上的一个圆圈内绘制一些线条,如下所示。



我不知道如何绘制线条,如下所示。但我有基本的知识,在画布上画线和弧。如何处理?



/ p>

解决方案

您可以使用控制点的注释中建议的贝塞尔曲线,但是,这些可能变得难以控制没有双关语),因为他们没有通过你定义的点,你总是需要定义两个控制点。



为了实现一个通过点使用<

没有内置的 支持这些,但一会儿我做了一个JavaScript和画布的实现(代码可以下载:





生成上述曲线(没有显示点坐标的红点):

  ctx.beginPath 
ctx.curve(pts);
ctx.stroke();

现在,这只是移动点(特别是中心点)将采用。为用户添加张力滑块可以是一个优势:



到例如0.3会降低平滑度到这个:

  ctx.curve(pts,0.3); 



还有其他参数(请参阅上面的链接,了解文档),您可以在点数组中有无限点数



实现扩展了画布上下文,但是如果你心情很模糊,你可以提取方法并单独使用它。 : - )



为圆圈实现此操作



我希望我在此处正确解释您的绘图...要使用上面的圆圈,您只需执行以下操作:




  • 定义范围,

  • 定义步骤,即。


  • 假设你想在-70°之间绘制线条,和70℃。和最多5行,你可以这样做:

      var ctx = canvas.getContext('2d'),
    cx = canvas.width * 0.5,
    cy = canvas.height * 0.5,
    pts,
    startAngle = -70,
    endAngle = 70,
    lines = 5,
    angle,
    range,
    steps,
    radius = 90,
    delta = 15,
    x,y,
    i;

    ctx.lineWidth = 3;
    ctx.strokeStyle ='#059';

    /// draw arc
    ctx.beginPath();
    ctx.arc(cx,cy,radius,0,2 * Math.PI);
    ctx.stroke();

    ///计算归一化为0度的角度范围
    startAngle = startAngle * Math.PI / 180;
    endAngle = endAngle * Math.PI / 180;

    range = endAngle - startAngle;
    steps = range /(lines + 1);

    ///在圆圈上计算点(仅垂直)
    for(i = 1; i <= lines; i ++){
    pts = []
    /// right side
    x = cx + radius * Math.cos(startAngle + steps * i);
    y = cy + radius * Math.sin(startAngle + steps * i);

    pts.push(x,y);

    /// center
    pts.push(cx,y + delta *((y-cy)/ cy));

    ///左侧的翻转
    x = cx - (x - cx);

    pts.push(x,y);

    ///绘制曲线
    ctx.beginPath();
    ctx.curve(pts,0.8);
    ctx.stroke();
    }

    这将导致:







    我的代码 - OCD踢了:-P,但你至少应该有几个选择。研究代码,看看如何计算垂直线,并采用水平线。



    希望这有助于!


    I want to draw some lines inside a circle on a canvas, in the following manner.

    I have no idea how to draw the lines as showed below. But I have the basic knowledge to draw line and arcs on a canvas. How to proceed?

    解决方案

    You can use a bezier curve as suggested in comments with control points, however, these can turn out to be hard to control (no pun) as they do not pass through the points you have defined and you always need to define two control points.

    In order to achieve a line through points using the actual points you need to use cardinal splines.

    There is no built-in support for these but a while back I made an implementation of this for JavaScript and canvas (code can be downloaded from here, MIT license).

    With this you can simply define three points as a minimum (to get a simple curve) and the function will take care of drawing a smooth curve between the points with a set tension value.

    If you for example defined the following three points:

    var pts = [10,100, 200,50, 390,100];
    

    You would obviously just get a simple poly-line like this if we wanted to illustrate the points (for comparison):

    Using a cardinal spline with the same three points would give you this:

    The following code generates the above curve (without the red dots showing the point coordinates):

    ctx.beginPath();
    ctx.curve(pts);
    ctx.stroke();
    

    Now it is simply a matter of moving the points around (in particular the center point) and the curve will adopt. Adding a tension slider for the user can be an advantage:

    Increasing the tension to for example 0.8 give you this result:

    ctx.curve(pts, 0.8);
    

    and lowering it to for example 0.3 will reduce the smoothness to this:

    ctx.curve(pts, 0.3);
    

    There are also other parameters (see the link at top for documentation) and you can have "unlimited" number of points in the point array in case you want to add super-fine control.

    The implementation extends the canvas context but you can extract the method and use it separately if you are faint at heart. :-)

    Implementing this for a circle

    I hope I am interpreting your drawing correctly here... to use the above for a circle you would simply need to do the following:

    • Define the range, the side of the circle you want the lines to be drawn into.
    • Define the steps, ie. the space between each line.

    Lets say you wanted to draw lines between -70° and 70° and maximum 5 lines you could do something like this:

    var ctx = canvas.getContext('2d'),
        cx = canvas.width * 0.5,
        cy = canvas.height * 0.5,
        pts,
        startAngle = -70,
        endAngle = 70,
        lines = 5,
        angle,
        range,
        steps,
        radius = 90,
        delta = 15,
        x, y,
        i;
    
    ctx.lineWidth = 3;
    ctx.strokeStyle = '#059';
    
    /// draw arc
    ctx.beginPath();
    ctx.arc(cx, cy, radius, 0, 2 * Math.PI);
    ctx.stroke();
    
    /// calculate angle range normalized to 0 degrees
    startAngle = startAngle * Math.PI / 180;
    endAngle = endAngle * Math.PI / 180;
    
    range = endAngle  - startAngle;
    steps = range / (lines + 1);
    
    /// calculate point at circle (vertical only)
    for(i = 1; i <= lines; i++) {
        pts = [];
        /// right side
        x = cx + radius * Math.cos(startAngle + steps * i);
        y = cy + radius * Math.sin(startAngle + steps * i);
    
        pts.push(x, y);
    
        /// center
        pts.push(cx, y + delta * ((y - cy)/ cy));
    
        /// flip for left side
        x = cx - (x - cx);
    
        pts.push(x, y);
    
        ///  draw curve
        ctx.beginPath();
        ctx.curve(pts, 0.8);
        ctx.stroke();
    }
    

    Which would result in this:

    Fiddle here

    It's now just a matter of playing around with the values (delta for example) and to calculate the horizontal row - I'll leave that as an exercise for the OP:

    Using ellipse side to draw the lines

    That being said - if you intended the globe to be more um, circular :-S, you could also have used a function to calculate part of an ellipse and draw that as lines instead. If would be about the same implementation as above here but with a sub function to calculate the ellipse between left and right side using the difference between the line and middle point as radius.

    For example:

    /// calculate point at circle (vertical only)
    for(i = 1; i <= lines; i++) {
        pts = [];
        /// right side
        x = cx + radius * Math.cos(startAngle + steps * i);
        y = cy + radius * Math.sin(startAngle + steps * i);
    
        pts.push(cx - radius, cy);
        pts.push(cx, y);   
        pts.push(cx + radius, cy);
    
        ///  draw ellipse side
        ctx.beginPath();
        drawEllipseSide(pts, true);
        ctx.stroke();
    }
    

    Then in the method (only vertical shown):

    function drawEllipseSide(pts, horizontal) {
    
        var radiusX,
            radiusY,
            cx, cy,
            x, y,
            startAngle,
            endAngle,
            steps = Math.PI * 0.01,
            i = 0;
    
        if (horizontal) {
    
            radiusX = Math.abs(pts[4] - pts[0]) * 0.5;
            radiusY = pts[3] - pts[1];
            cx = pts[2];
            cy = pts[1];
            startAngle = 0;
            endAngle = Math.PI;
    
            x = cx + radiusX * Math.cos(startAngle);
            y = cy + radiusY * Math.sin(startAngle);
    
            ctx.moveTo(x, y);
    
            for(i = startAngle + steps; i < endAngle; i += steps) {
                x = cx + radiusX * Math.cos(i);
                y = cy + radiusY * Math.sin(i);
                ctx.lineTo(x, y);
            }
        }
    }
    

    Resulting in this (I cheat a bit in the final drawing to give a more clear picture (no pun) of what the end result will be if you continue down these lines (no pun either, I am pun-cursed) given here):

    Fiddle here

    My code-OCD kicked in :-P but you should at least have a few options here to go with. Study the code to see how the vertical lines are calculated and adopt that for horizontal ones.

    Hope this helps!

    这篇关于如何在画布上绘制线条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆