使用 HTML5 Canvas 为绘画应用创建逼真的铅笔工具
首先我想说的是,我做了很多研究并尝试了自己,但没有任何成功.
First I want to say that I made a lot of research and tries myself without any success.
我正在使用 Canvas 开发类似 MSPaint 的应用程序,并且我想创建一个看起来像手工绘图一样逼真的铅笔工具...这是下面链接中的示例默认工具:http://www.onemotion.com/flash/sketch-paint/
I am working on a MSPaint-like application using Canvas, and I would like to create a pencil tool which looks realistic like handmade drawings... Here is an example in the link below with the default tool : http://www.onemotion.com/flash/sketch-paint/
我尝试使用 mousespeed 和 linewidth 属性,但效果不佳(当我移动鼠标时,整条线会放大和缩小).我不知道对像素原始数据起作用的算法.
I tried to play with mousespeed and linewidth properties but it is not working well (the entire line enlarge and shrink as I move the mouse). I have no idea of an algorithm acting on pixel raw data.
您知道现有的东西或适合应用的算法吗?非常感谢您的帮助
Do you know something existing or a suitable algorithm to apply ? Thank you very much for your help
编辑
我决定添加我选择的解决方案,因为它似乎引起了很多人的兴趣.所以,到目前为止我发现的最好的事情是使用这里解释的技术在画布上绘制图像:http://css.dzone.com/articles/sketching-html5-canvas-and.它就像一个魅力,结果非常令人信服,这很容易实现.在这里试试:http://tricedesigns.com/portfolio/sketch/brush.html#
I decided to add the solution I've chosen because it seems to interest lot of people. So, the best thing I found so far is to draw an image onto the canvas, using the technique explained here : http://css.dzone.com/articles/sketching-html5-canvas-and. It works like a charm, the result is really convincing and this is quite easy to implement. Try it out here : http://tricedesigns.com/portfolio/sketch/brush.html#
推荐答案
你可以试试下面的演示
现场演示
您最有可能使用 moveTo
和 lineTo
来创建路径,如果您这样做,那么在您关闭路径之前,这些属性将为路径共享.所以每次你改变粗细都需要调用closePath
,然后再次调用beginPath
.
Your most likely using moveTo
and lineTo
to create the paths, if you do it that way the properties will be shared for the path until you close the path. So everytime you change the thickness youd need to call closePath
and then beginPath
again.
在我的示例中,我使用 Bresenham 的线算法 来绘制点.基本上 onmousedown 它开始绘画.然后 onmousemove 它将当前坐标与最后一个坐标进行比较,并绘制它们之间的所有点.它也使用 fillRect
来绘画.根据您移动的速度有多快,线条会变粗还是变细.
In my example I use Bresenham's line algorithm to plot the points. Basically onmousedown it starts painting. Then onmousemove it compares the current coordinates with the last coordinates and plots all of the points between. Its also using fillRect
to paint. Based on how fast your moving the line will be thicker or thinner.
这是绘图功能的代码
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;
}
}
相关文章