我正在尝试使用画布创建绘图区域。我在绘制曲线时让线条看起来很光滑时遇到了麻烦,而且我的算法中的线条粗细也有变化,看起来很糟糕,因为尺寸跳跃也很多,你可以看到尺寸变化的地方。我确实找到了这个link on stackoverflow,但这是一个原生的iPhone应用程序,我无法弄明白。
这是我目前的JS代码。这是运行on 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;
}
提前谢谢大家。
如果你画画,这就是现在的样子。
......这就是我想要实现的目标:
答案 0 :(得分:21)
我刚才做了类似的东西,把它变成了一个jquery插件。 看看这里,如果它是你的,我会发布一个更详细的答案,并从我的档案中挖出简化的jquery版本:
修改强>
好的,对不起昨天我不能这样做:
最初上面的代码是从Doob先生的'和谐'草图上划过来的: http://mrdoob.com/projects/harmony/#ribbon
(我认为这是最好的解决方案)。 但我有点打破了它并在另一个项目上为了我自己的目的重新制作它。我已经破解了我自己的插件,使它在这里更容易一些:
您唯一想要改变的是将其更改为mousedown / mouseup,这应该很容易看看插件底部的设置,你应该能够得到你想要的效果玩刷子大小,颜色,alpha(rgba)等。
希望有所帮助
答案 1 :(得分:9)
看一下这段代码:
我正在做的是在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()
}
答案 2 :(得分:5)
答案 3 :(得分:2)
似乎您需要在画布中使用一些画笔。很难说你需要什么样的画笔,但是有许多JS库已经实现了画笔技术。
例如你看过这个库吗?
在网络上的Laso,您可以在Doob先生Harmony项目中找到许多画笔。例如,github上的stringy或Harmony-Brushes项目。
答案 4 :(得分:2)
建议使用一系列贝塞尔曲线完成渲染,这些曲线环绕曲线,因此填充曲线。 (即以ctx.fill结尾) 还有很多工作要做,但希望这会有所帮助。
为bezier曲线改编了一个漂亮的演示应用
将它添加到你的小提琴的叉子里 http://jsfiddle.net/d3zFU/1/
代码是
/*
* Canvas curves example
*
* By Craig Buckler, http://twitter.com/craigbuckler
* of OptimalWorks.net http://optimalworks.net/
* for SitePoint.com http://sitepoint.com/
*
* Refer to:
* http://blogs.sitepoint.com/html5-canvas-draw-quadratic-curves/
* http://blogs.sitepoint.com/html5-canvas-draw-bezier-curves/
*
* This code can be used without restriction.
*/
(function(){
var canvas, ctx, code, point, style, drag = null, dPoint;
// define initial points
function Init(quadratic) {
point = {
p1: { x:100, y:250 },
p2: { x:400, y:250 }
};
if (quadratic) {
point.cp1 = { x: 250, y: 100 };
}
else {
point.cp1 = { x: 150, y: 100 };
point.cp2 = { x: 350, y: 100 };
}
// default styles
style = {
curve: { width: 6, color: "#333" },
cpline: { width: 1, color: "#C00" },
point: { radius: 10, width: 2, color: "#900", fill: "rgba(200,200,200,0.5)", arc1: 0, arc2: 2 * Math.PI }
}
// line style defaults
ctx.lineCap = "round";
ctx.lineJoin = "round";
// event handlers
canvas.onmousedown = DragStart;
canvas.onmousemove = Dragging;
canvas.onmouseup = canvas.onmouseout = DragEnd;
DrawCanvas();
}
// draw canvas
function DrawCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// control lines
ctx.lineWidth = style.cpline.width;
ctx.strokeStyle = style.cpline.color;
ctx.fillStyle = style.cpline.color;
ctx.beginPath();
ctx.moveTo(point.p1.x, point.p1.y);
ctx.lineTo(point.cp1.x, point.cp1.y);
if (point.cp2) {
ctx.moveTo(point.p2.x, point.p2.y);
ctx.lineTo(point.cp2.x, point.cp2.y);
}
else {
ctx.lineTo(point.p2.x, point.p2.y);
}
ctx.stroke();
// curve
ctx.lineWidth = 1 ; //style.curve.width;
ctx.strokeStyle = style.curve.color;
ctx.beginPath();
ctx.moveTo(point.p1.x, point.p1.y);
if (point.cp2) {
ctx.bezierCurveTo(point.cp1.x, point.cp1.y, point.cp2.x, point.cp2.y, point.p2.x, point.p2.y);
ctx.bezierCurveTo(point.cp2.x, point.cp2.y+12, point.cp1.x, point.cp1.y+12, point.p1.x, point.p1.y);
}
else {
ctx.quadraticCurveTo(point.cp1.x, point.cp1.y, point.p2.x, point.p2.y);
}
//ctx.stroke();
ctx.fill();
// control points
for (var p in point) {
ctx.lineWidth = style.point.width;
ctx.strokeStyle = style.point.color;
ctx.fillStyle = style.point.fill;
ctx.beginPath();
ctx.arc(point[p].x, point[p].y, style.point.radius, style.point.arc1, style.point.arc2, true);
ctx.fill();
ctx.stroke();
}
ShowCode();
}
// show canvas code
function ShowCode() {
if (code) {
code.firstChild.nodeValue =
"canvas = document.getElementById(\"canvas\");\n"+
"ctx = canvas.getContext(\"2d\")\n"+
"ctx.lineWidth = " + style.curve.width +
";\nctx.strokeStyle = \"" + style.curve.color +
"\";\nctx.beginPath();\n" +
"ctx.moveTo(" + point.p1.x + ", " + point.p1.y +");\n" +
(point.cp2 ?
"ctx.bezierCurveTo("+point.cp1.x+", "+point.cp1.y+", "+point.cp2.x+", "+point.cp2.y+", "+point.p2.x+", "+point.p2.y+");" :
"ctx.quadraticCurveTo("+point.cp1.x+", "+point.cp1.y+", "+point.p2.x+", "+point.p2.y+");"
) +
"\nctx.stroke();"
;
}
}
// start dragging
function DragStart(e) {
e = MousePos(e);
var dx, dy;
for (var p in point) {
dx = point[p].x - e.x;
dy = point[p].y - e.y;
if ((dx * dx) + (dy * dy) < style.point.radius * style.point.radius) {
drag = p;
dPoint = e;
canvas.style.cursor = "move";
return;
}
}
}
// dragging
function Dragging(e) {
if (drag) {
e = MousePos(e);
point[drag].x += e.x - dPoint.x;
point[drag].y += e.y - dPoint.y;
dPoint = e;
DrawCanvas();
}
}
// end dragging
function DragEnd(e) {
drag = null;
canvas.style.cursor = "default";
DrawCanvas();
}
// event parser
function MousePos(event) {
event = (event ? event : window.event);
return {
x: event.pageX - canvas.offsetLeft,
y: event.pageY - canvas.offsetTop
}
}
// start
canvas = document.getElementById("canvas");
code = document.getElementById("code");
if (canvas.getContext) {
ctx = canvas.getContext("2d");
Init(canvas.className == "quadratic");
}
})();
答案 5 :(得分:2)
对于那些对@Alex提供的代码的点击版本感兴趣的人,我在这里重写了他的脚本:
答案 6 :(得分:-1)
重要!
我收集了一些必要的零件,并将其全部附在这里!
<canvas id="paint_board" width="500" height="800" style="border: 1px solid;"></canvas>
<script>
var el = document.getElementById('paint_board');
// rect gets the cavas left top value in browser
var rect = el.getBoundingClientRect();
var ctx = el.getContext('2d');
ctx.lineJoin = ctx.lineCap = 'round';
ctx.lineWidth = 1;
var isDrawing, pen_type=1;
var screenWidth=500, screenHeight=500; //set canvas width and height
var strokes=20; //how many strokes to draw
var color = [0, 0, 0]; // color val RGB 0-255, 0-255, 0-255
var painters = [], unpainters = [], timers = [];
var brushPressure=1; // brush Opacity
var easing = 0.7; // kind of "how loopy" higher= bigger loops
var refreshRate = 30; // set this higher if performace is an issue directly affects easing
var mouseX = screenWidth / 2, mouseY = screenHeight / 2;
var testinterval;
pen_init();
function pen_init(){
for(var i = 0; i < strokes; i++) {
var ease = Math.random() * 0.05 + easing;
painters.push({
dx : screenWidth / 2,
dy : screenHeight / 2,
ax : 0,
ay : 0,
div : 0.1,
ease : ease
});
}
testinterval = setInterval(update, refreshRate);
function update() {
var i;
ctx.strokeStyle = "rgba(" + color[0] + ", " + color[1] + ", " + color[2] + ", " + brushPressure + ")";
for( i = 0; i < painters.length; i++) {
ctx.beginPath();
var dx = painters[i].dx;
var dy = painters[i].dy;
ctx.moveTo(dx, dy);
var dx1 = painters[i].ax = (painters[i].ax + (painters[i].dx - mouseX) * painters[i].div) * painters[i].ease;
painters[i].dx -= dx1;
var dx2 = painters[i].dx;
var dy1 = painters[i].ay = (painters[i].ay + (painters[i].dy - mouseY) * painters[i].div) * painters[i].ease;
painters[i].dy -= dy1;
var dy2 = painters[i].dy;
ctx.lineTo(dx2, dy2);
ctx.stroke();
}
}
}
el.onmousedown = function(e) {
isDrawing = true;
mouseX = e.clientX+window.scrollX-rect.left;
mouseY = e.clientY+window.scrollY-rect.top;
var i = 0, paintersLen = painters.length;
for(i; i < paintersLen; i++) {
painters[i].dx = mouseX;
painters[i].dy = mouseY;
}
};
el.onmousemove = function(e) {
if (!isDrawing) return;
mouseX = e.clientX+window.scrollX-rect.left;
mouseY = e.clientY+window.scrollY-rect.top;
};
el.onmouseup = function() {
isDrawing = false;
};
</script>
只需复制所有内容并将其粘贴到您的代码中即可。而且不要忘了点击投票!