Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/371.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 画布-有时使用lineTo()的笔划会生成边_Javascript_Html_Canvas - Fatal编程技术网

Javascript 画布-有时使用lineTo()的笔划会生成边

Javascript 画布-有时使用lineTo()的笔划会生成边,javascript,html,canvas,Javascript,Html,Canvas,我有一个简单的画布绘图应用程序有时lineTo()命令会生成坐标较少的直线,并且图形有许多边: 我使用的是最新的firefox,是因为连接不好还是我的电脑有问题?附近有工作吗? 这是我的密码: 它正在尽可能快地作出反应。您的浏览器将以最快的速度发送事件,但不能保证能够跟踪您移动鼠标。这与客户端机器上的负载有很大关系 编辑-演示一些可能使其更好的方法。该版本保留一个单独的“点”队列,每50毫秒绘制一次新点。这使得“mousemove”处理程序只需记录事件中的点坐标,并且当鼠标快速移动时,绘图代码

我有一个简单的画布绘图应用程序有时lineTo()命令会生成坐标较少的直线,并且图形有许多边:

我使用的是最新的firefox,是因为连接不好还是我的电脑有问题?附近有工作吗? 这是我的密码:


它正在尽可能快地作出反应。您的浏览器将以最快的速度发送事件,但不能保证能够跟踪您移动鼠标。这与客户端机器上的负载有很大关系

编辑-演示一些可能使其更好的方法。该版本保留一个单独的“点”队列,每50毫秒绘制一次新点。这使得“mousemove”处理程序只需记录事件中的点坐标,并且当鼠标快速移动时,绘图代码可以通过一次画布更新完成一系列点。它仍然不完美

 var canvas = document.getElementById('canvas');
        var ctx = canvas.getContext('2d');
        var width  = window.innerWidth;
        var height = window.innerHeight;
        canvas.height = height;
        canvas.width = width;
        canvas.addEventListener('mousedown', function(e) {
            this.down = true;
            points.setStart(e.pageX, e.pageY);
        }, 0);
        canvas.addEventListener('mouseup', function() {
            this.down = false;          
        }, 0);
        canvas.addEventListener('mousemove', function(e) {          
            if (this.down) {
                points.newPoint(e.pageX, e.pageY);
            }
        }, 0);

var points = function() {
    var queue = [], qi = 0;
    var ctx = canvas.getContext('2d');

    function clear() {
        queue = [];
        qi = 0;
    }

    function setStart(x, y) {
        clear();
        newPoint(x, y);
    }

    function newPoint(x, y) {
        queue.push([x, y]);
    }

    function tick() {

        var k = 20; // adjust to limit points drawn per cycle

        if (queue.length - qi > 1) {
            ctx.beginPath();
            if (qi === 0)
                ctx.moveTo(queue[0][0], queue[0][1]);
            else
                ctx.moveTo(queue[qi - 1][0], queue[qi - 1][1]);

            for (++qi; --k >= 0 && qi < queue.length; ++qi) {
                ctx.lineTo(queue[qi][0], queue[qi][1]);
            }

            ctx.strokeStyle = "rgb(0,0,0)";
            ctx.lineWidth = 3;
            ctx.stroke();
        }
    }

    setInterval(tick, 50); // adjust cycle time

    return {
        setStart: setStart,
        newPoint: newPoint
    };
}();
var canvas=document.getElementById('canvas');
var ctx=canvas.getContext('2d');
变量宽度=window.innerWidth;
var height=window.innerHeight;
canvas.height=高度;
画布宽度=宽度;
canvas.addEventListener('mousedown',函数(e){
this.down=true;
点。设置开始(e.pageX,e.pageY);
}, 0);
addEventListener('mouseup',function(){
this.down=false;
}, 0);
addEventListener('mousemove',函数(e){
如果(这个向下){
新点(e.pageX,e.pageY);
}
}, 0);
变量点=函数(){
var queue=[],qi=0;
var ctx=canvas.getContext('2d');
函数clear(){
队列=[];
qi=0;
}
函数setStart(x,y){
清除();
新点(x,y);
}
函数newPoint(x,y){
push([x,y]);
}
函数tick(){
var k=20;//调整到每个周期绘制的极限点
如果(queue.length-qi>1){
ctx.beginPath();
如果(qi==0)
ctx.moveTo(队列[0][0],队列[0][1]);
其他的
移动到(队列[qi-1][0],队列[qi-1][1]);
对于(++qi;--k>=0&&qi
您可以使用基数样条曲线平滑线条,如下所示:

原因已解释为@Pointy,因为浏览器能够以多快的速度响应事件(
mousemove
)。有一个叫做API的API可能会在将来帮助解决这个问题,因为它更低级,但是现在我们需要使用算法来平滑由于这个原因而出现的分段线

除平滑外,还有细节平滑、点减少、锥度和其他可用于改善结果的功能

但是在这个特殊的例子中,您可以使用下面的函数,我将其作为画布的扩展。就叫它:

ctx.curve(myPointArray, tension, segments);
ctx.stroke();
该数组包含按顺序排列的x和y点,如
[x1,y1,x2,y2,…xn,yn

张力
的典型值为0.5。
(默认值16)是可选的

张力越大,曲线就越圆。线段是数组中每个点之间的分辨率。对于绘图应用程序,值5可以很好地工作(结果点越少)

为了使其更好地工作,您可以在一个单独的画布上注册您的点,在这里您可以绘制原始线。在鼠标悬停时,使用此功能处理该线,并将其绘制到主画布,然后清除绘制画布

此函数经过高度优化-它还返回已处理的点,因此您可以存储结果,而不是每次重新处理

/**
 *  curve() by Ken Fyrstenberg (c) 2013 Epistemex
 *  See Code Project for full source:
 *  http://www.codeproject.com/Tips/562175/Draw-Smooth-Lines-on-HTML5-Canvas
*/
CanvasRenderingContext2D.prototype.curve = function(pts, ts, nos) {

    nos = (typeof numOfSegments === 'undefined') ? 16 : nos;

    var _pts = [], res = [],        // clone array
        x, y,                       // our x,y coords
        t1x, t2x, t1y, t2y,         // tension vectors
        c1, c2, c3, c4,             // cardinal points
        st, st2, st3, st23, st32,   // steps
        t, i, l = pts.length,
        pt1, pt2, pt3, pt4;

    _pts.push(pts[0]);          //copy 1. point and insert at beginning
    _pts.push(pts[1]);

    _pts = _pts.concat(pts);

    _pts.push(pts[l - 2]);  //copy last point and append
    _pts.push(pts[l - 1]);

    this.moveTo(pts[0], pts[1])

    for (i = 2; i < l; i+=2) {

        pt1 = _pts[i];
        pt2 = _pts[i+1];
        pt3 = _pts[i+2];
        pt4 = _pts[i+3];

        // calc tension vectors
        t1x = (pt3 - _pts[i-2]) * ts;
        t2x = (_pts[i+4] - pt1) * ts;

        t1y = (pt4 - _pts[i-1]) * ts;
        t2y = (_pts[i+5] - pt2) * ts;

        for (t = 0; t <= nos; t++) {

            // pre-calc steps
            st = t / nos;
            st2 = st * st;
            st3 = st2 * st;
            st23 = st3 * 2;
            st32 = st2 * 3;

            // calc cardinals
            c1 = st23 - st32 + 1; 
            c2 = st32 - st23;
            c3 = st3 - 2 * st2 + st; 
            c4 = st3 - st2;

            res.push(c1 * pt1 + c2 * pt3 + c3 * t1x + c4 * t2x);
            res.push(c1 * pt2 + c2 * pt4 + c3 * t1y + c4 * t2y);

        } //for t
    } //for i

    l = res.length;
    for(i=0;i<l;i+=2) this.lineTo(res[i], res[i+1]);

    return res;

} //func ext
/**
*曲线()由Ken Fyrstenberg(c)于2013年出版
*有关完整源代码,请参见代码项目:
*  http://www.codeproject.com/Tips/562175/Draw-Smooth-Lines-on-HTML5-Canvas
*/
CanvasRenderingContext2D.prototype.curve=函数(pts、ts、nos){
nos=(numOfSegments的类型==‘未定义’)?16:个;
var _pts=[],res=[],//克隆数组
x、 y,//我们的x,y坐标
t1x,t2x,t1y,t2y,//张力向量
c1,c2,c3,c4,//基点
st,st2,st3,st23,st32,//步骤
t、 i,l=点长度,
pt1、pt2、pt3、pt4;
_pts.push(pts[0]);//复制1.点并在开始处插入
_点推(点[1]);
_pts=_pts.concat(pts);
_push(pts[l-2]);//复制最后一点并追加
_点推(点[l-1]);
this.moveTo(pts[0],pts[1])
对于(i=2;i对于(t=0;t),您可以尝试使用鼠标移动点(上面屏幕截图中显示的顶点)来绘制曲线,而不是直线(但不确定这是否可行)。对于直线,您将取决于浏览器重新渲染画布的速度(加上浏览器或操作系统忙着做其他事情时的偶尔打嗝)是的,这是一个好主意-你可以使用Bezier或Catmull Rom样条线来平滑它,尽管有时会产生一些奇怪的效果。是的,但是笔划不会像我的鼠标移动一样,它只是一种插值。要计算曲线,需要额外的时间尝试在P中快速拖动鼠标
/**
 *  curve() by Ken Fyrstenberg (c) 2013 Epistemex
 *  See Code Project for full source:
 *  http://www.codeproject.com/Tips/562175/Draw-Smooth-Lines-on-HTML5-Canvas
*/
CanvasRenderingContext2D.prototype.curve = function(pts, ts, nos) {

    nos = (typeof numOfSegments === 'undefined') ? 16 : nos;

    var _pts = [], res = [],        // clone array
        x, y,                       // our x,y coords
        t1x, t2x, t1y, t2y,         // tension vectors
        c1, c2, c3, c4,             // cardinal points
        st, st2, st3, st23, st32,   // steps
        t, i, l = pts.length,
        pt1, pt2, pt3, pt4;

    _pts.push(pts[0]);          //copy 1. point and insert at beginning
    _pts.push(pts[1]);

    _pts = _pts.concat(pts);

    _pts.push(pts[l - 2]);  //copy last point and append
    _pts.push(pts[l - 1]);

    this.moveTo(pts[0], pts[1])

    for (i = 2; i < l; i+=2) {

        pt1 = _pts[i];
        pt2 = _pts[i+1];
        pt3 = _pts[i+2];
        pt4 = _pts[i+3];

        // calc tension vectors
        t1x = (pt3 - _pts[i-2]) * ts;
        t2x = (_pts[i+4] - pt1) * ts;

        t1y = (pt4 - _pts[i-1]) * ts;
        t2y = (_pts[i+5] - pt2) * ts;

        for (t = 0; t <= nos; t++) {

            // pre-calc steps
            st = t / nos;
            st2 = st * st;
            st3 = st2 * st;
            st23 = st3 * 2;
            st32 = st2 * 3;

            // calc cardinals
            c1 = st23 - st32 + 1; 
            c2 = st32 - st23;
            c3 = st3 - 2 * st2 + st; 
            c4 = st3 - st2;

            res.push(c1 * pt1 + c2 * pt3 + c3 * t1x + c4 * t2x);
            res.push(c1 * pt2 + c2 * pt4 + c3 * t1y + c4 * t2y);

        } //for t
    } //for i

    l = res.length;
    for(i=0;i<l;i+=2) this.lineTo(res[i], res[i+1]);

    return res;

} //func ext