使用HTML5 Canvas为绘画应用创建逼真的铅笔工具

时间:2012-04-12 11:23:23

标签: javascript image-processing canvas html5-canvas

首先,我想说我做了很多研究,并试着自己没有任何成功。

我正在使用Canvas开发类似MSPaint的应用程序,我想创建一个像手工绘图一样逼真的铅笔工具 ...这是以下链接中的示例默认工具: http://www.onemotion.com/flash/sketch-paint/

我尝试使用mousespeed和linewidth属性但它运行不正常(整个行在我移动鼠标时放大和缩小)。我不知道算法会对像素原始数据起作用。

您是否知道现有的内容或适用的算法?非常感谢你的帮助

修改

我决定添加我选择的解决方案,因为它似乎让很多人感兴趣。 所以,到目前为止我发现的最好的事情是使用这里解释的技术在画布上绘制图像:http://css.dzone.com/articles/sketching-html5-canvas-and。 它就像一个魅力,结果真的很有说服力,这很容易实现。在这里试试:http://tricedesigns.com/portfolio/sketch/brush.html#

1 个答案:

答案 0 :(得分:23)

你可以尝试类似下面的演示

<强> Live Demo

您最有可能使用moveTolineTo来创建路径,如果您这样做,则在您关闭路径之前将为路径共享属性。因此,每当您更改厚度时,您需要再次调用closePath然后再调用beginPath

在我的示例中,我使用Bresenham's line algorithm绘制点。基本上,它开始绘画。然后onmousemove它将当前坐标与最后一个坐标进行比较,并绘制其间的所有点。它也使用fillRect来绘画。根据您移动线条的速度有多快或更薄。

下面是绘图函数的代码

var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d"),
    painting = false,
    lastX = 0,
    lastY = 0,
    lineThickness = 1;

canvas.width = canvas.height = 600;
ctx.fillRect(0, 0, 600, 600);

canvas.onmousedown = function(e) {
    painting = true;
    ctx.fillStyle = "#ffffff";
    lastX = e.pageX - this.offsetLeft;
    lastY = e.pageY - this.offsetTop;
};

canvas.onmouseup = function(e){
    painting = false;
}

canvas.onmousemove = function(e) {
    if (painting) {
        mouseX = e.pageX - this.offsetLeft;
        mouseY = e.pageY - this.offsetTop;

        // find all points between        
        var x1 = mouseX,
            x2 = lastX,
            y1 = mouseY,
            y2 = lastY;


        var steep = (Math.abs(y2 - y1) > Math.abs(x2 - x1));
        if (steep){
            var x = x1;
            x1 = y1;
            y1 = x;

            var y = y2;
            y2 = x2;
            x2 = y;
        }
        if (x1 > x2) {
            var x = x1;
            x1 = x2;
            x2 = x;

            var y = y1;
            y1 = y2;
            y2 = y;
        }

        var dx = x2 - x1,
            dy = Math.abs(y2 - y1),
            error = 0,
            de = dy / dx,
            yStep = -1,
            y = y1;

        if (y1 < y2) {
            yStep = 1;
        }

        lineThickness = 5 - Math.sqrt((x2 - x1) *(x2-x1) + (y2 - y1) * (y2-y1))/10;
        if(lineThickness < 1){
            lineThickness = 1;   
        }

        for (var x = x1; x < x2; x++) {
            if (steep) {
                ctx.fillRect(y, x, lineThickness , lineThickness );
            } else {
                ctx.fillRect(x, y, lineThickness , lineThickness );
            }

            error += de;
            if (error >= 0.5) {
                y += yStep;
                error -= 1.0;
            }
        }



        lastX = mouseX;
        lastY = mouseY;

    }
}