在<canvas>元素上实现平滑的草图绘制和绘图

ryu*_*suo 29 javascript html5 drawing canvas paint

我正在尝试使用画布创建绘图区域.我在绘制曲线时让线条看起来很光滑时遇到了麻烦,而且我的算法中的线条粗细也有变化,看起来很糟糕,因为尺寸跳跃也很多,你可以看到尺寸变化的地方.我确实在stackoverflow上找到了这个链接,但这是一个原生的iPhone应用程序,我无法搞清楚.

这是我目前的JS代码.这是在jsFiddle上运行的

var xStart,
xEnd,
yStart,
yEnd,
paint,
ctx;
$(document).ready(function (){

   ctx = $('canvas')[0].getContext("2d");
   ctx.strokeStyle = '#000';
   ctx.lineJoin="round";
   ctx.lineCap="round";
   ctx.lineWidth = 1;


   $('canvas').bind('mousedown mousemove mouseup mouseleave touchstart touchmove touchend', function(e){
        var orig = e.originalEvent;

        if(e.type == 'mousedown'){
            e.preventDefault(); e.stopPropagation();

            xStart = e.clientX - $(this).offset().left;
            yStart = e.clientY - $(this).offset().top;
            xEnd = xStart;
            yEnd = yStart;

            paint = true;
            draw(e.type);

        }else if(e.type == 'mousemove'){
            if(paint==true){
                xEnd = e.clientX - $(this).offset().left;
                yEnd = e.clientY - $(this).offset().top;


               lineThickness = 1 + Math.sqrt((xStart - xEnd) *(xStart-xEnd) + (yStart - yEnd) * (yStart-yEnd))/5;

               if(lineThickness > 10){
                    lineThickness = 10;   
               }

                ctx.lineWidth = lineThickness;
                draw(e.type);
            }
        }else if(e.type == 'mouseup'){
            paint = false;
        }else if(e.type == 'mouseleave'){
            paint = false;
        }else if(e.type == 'touchstart'){
            if(orig.touches.length == 1){
                e.preventDefault(); e.stopPropagation();

                xStart = orig.changedTouches[0].pageX - $(this).offset().left;
                yStart = orig.changedTouches[0].pageY - $(this).offset().top;
                xEnd = xStart;
                yEnd = yStart; 

                paint = true;
                draw(e.type);
            }
        }else if(e.type == 'touchmove'){
            if(orig.touches.length == 1){
                if(paint==true){
                    xEnd = orig.changedTouches[0].pageX - $(this).offset().left;
                    yEnd = orig.changedTouches[0].pageY - $(this).offset().top;


                            lineThickness = 1 + Math.sqrt((xStart - xEnd) *(xStart-xEnd) + (yStart - yEnd) * (yStart-yEnd))/6;
                       if(lineThickness > 10){
                          lineThickness = 10;   
                       }


                      ctx.lineWidth = lineThickness;


                    draw(e.type);
                }
            }
        }else if(e.type == 'touchend'){
            paint = false;
        }

      });
    });


    function draw(event){

    if(event == 'mousedown'){
        ctx.beginPath();
        ctx.moveTo(xStart, yStart);
        ctx.lineTo(xEnd, yEnd);
        ctx.stroke();
    }else if(event == 'mousemove'){
        ctx.beginPath();
        ctx.moveTo(xStart, yStart);
        ctx.lineTo(xEnd, yEnd);
        ctx.stroke();
    }else if(event == 'touchstart'){
        ctx.beginPath();
        ctx.moveTo(xStart, yStart);
        ctx.lineTo(xEnd, yEnd);
        ctx.stroke();
    }else if(event == 'touchmove'){
        ctx.beginPath();
        ctx.moveTo(xStart, yStart);
        ctx.lineTo(xEnd, yEnd);
        ctx.stroke();
    }
    xStart = xEnd;
    yStart = yEnd;                  
}
Run Code Online (Sandbox Code Playgroud)

谢谢大家.

如果你画画的话,这就是它现在的样子. 当前(锯齿状)实施

......这就是我想要实现的目标:

顺利的笔触

Ale*_*lex 21

我刚才做了类似的东西,把它变成了一个jquery插件.看看这里,如果你发现了什么,我会发布一个更详细的答案,并从我的档案中挖出简化的jquery版本:

http://jsfiddle.net/95tft/

编辑

好的,对不起昨天我做不到这个:

最初上面的代码是从Doob先生的"和谐"草图上划过来的:http: //mrdoob.com/projects/harmony/#ribbon

(我认为这是最好的解决方案).但我有点打破了它并在另一个项目上为了我自己的目的重新制作它.我已经破解了我自己的插件,使其在这里更容易一些:

http://jsfiddle.net/dh3bj/

你可能想要改变的唯一一件事就是改变它以便在mousedown/mouseup上工作,这应该很容易看看插件底部的设置,你应该能够通过玩耍来获得你想要的效果刷子大小,颜色,alpha(rgba)等

希望有所帮助


Sim*_*ris 9

看看这段代码:

http://jsfiddle.net/aMmVQ/

我正在做的是在mouseDown上开始一个新的点列表,然后为每个mousemove我添加一个点到列表.一旦我得到足够的点数(大约6个),我就开始绘制二次曲线,曲线的控制点是当前点和下一个点的平均值.

drawPoints 是有效的神奇:

function drawPoints(ctx, points) {
    // draw a basic circle instead
    if (points.length < 6) {
        var b = points[0];
        ctx.beginPath(), ctx.arc(b.x, b.y, ctx.lineWidth / 2, 0, Math.PI * 2, !0), ctx.closePath(), ctx.fill();
        return
    }
    ctx.beginPath(), ctx.moveTo(points[0].x, points[0].y);
    // draw a bunch of quadratics, using the average of two points as the control point
    for (i = 1; i < points.length - 2; i++) {
        var c = (points[i].x + points[i + 1].x) / 2,
            d = (points[i].y + points[i + 1].y) / 2;
        ctx.quadraticCurveTo(points[i].x, points[i].y, c, d)
    }
    ctx.quadraticCurveTo(points[i].x, points[i].y, points[i + 1].x, points[i + 1].y), ctx.stroke()
}
Run Code Online (Sandbox Code Playgroud)


Jon*_*hoi 5

你为什么不用croquis.js

像Photoshop一样整洁的刷子实现 :)

这里是演示其使用croquis.js.

刷预览