HTML5 canvas 画逼真的简单铅笔

HTML5 canvas paint realistic simple pencil

我如何创建逼真的简单铅笔工具,而不像在 MS windows 绘图程序中那样。我需要这样的结果:

如果我尝试不透明的纯色,我会像在 MS 中一样 windows 绘画程序不是逼真的铅笔,如果我尝试添加不透明度,我会看到圆圈,这太不现实了:

如何获得第一张图片中的铅笔工具?我的尝试示例:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var previousMouseX = null;
var previousMouse = null;
var isDrawing = false;

var lineWidth = 10;
var brush = 1;
var myColor = "#FF0000";

function getMousePosition(canvas, evt) {
    
    var rect = canvas.getBoundingClientRect();
    
    if (evt.clientX !== undefined && evt.clientY !== undefined) {
        return {
            x: evt.clientX - rect.left,
            y: evt.clientY - rect.top
        };   
    } 
}

/* BUTTONS */
$("#btn1").on("click", function() {
    ctx.globalAlpha = "0.2";
});

$("#btn2").on("click", function() {
    ctx.globalAlpha = "1";
});

$("#change-color").on("click", function() {
    ctx.strokeStyle = "#009933";
});

$("#canvas").on("mousedown", function(e) {
    isDrawing = true;
    var pos = getMousePosition(canvas, e);
    move(pos.x, pos.y);

});

$("#canvas").on("mousemove", function(e) {
    if(isDrawing) {
        var pos = getMousePosition(canvas, e);
        stroke(pos.x, pos.y);   
    }
});

$("#canvas").on("mouseup", function() {
    isDrawing = false;
});

function stroke(mouseX, mouseY) {
        ctx.globalCompositeOperation = "source-over";
        ctx.lineJoin = ctx.lineCap = "round";
        ctx.lineWidth = 10;
        ctx.beginPath();
        ctx.moveTo(previousMouseX, previousMouseY);
        ctx.lineTo(mouseX, mouseY);
        ctx.closePath();
        ctx.stroke();
        move(mouseX, mouseY);
}

function move(mouseX, mouseY) {
        previousMouseX = mouseX;
        previousMouseY = mouseY;
}
canvas  {
    border: 1px solid #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type="button" id="btn1" value="Transparent">
<input type="button" id="btn2" value="Solid">
<input type="button" id="change-color" value="Green color"><br />
<canvas id="canvas" width="500" height="500">

这是否接近您想要的效果?

使用透明的铅笔绘制,线宽 10,然后使用较小的线宽 (8) 在实线上绘制。也许您可以通过在 7、8 和 9 之间随机改变第二条线宽来获得更多变化?

EDIT 还可以在 1 和 0.8 之间随机设置第二行的不透明度!

在第一行永久设置不透明度并将此代码添加到函数 stroke()

    ctx.globalAlpha = "1";
    ctx.lineWidth = 6;
    ctx.beginPath();
    ctx.moveTo(previousMouseX, previousMouseY);
    ctx.lineTo(mouseX, mouseY);
    ctx.closePath();
    ctx.stroke();

已更改代码段

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var previousMouseX = null;
var previousMouse = null;
var isDrawing = false;

var lineWidth = 10;
var brush = 1;
var myColor = "#FF0000";

function getMousePosition(canvas, evt) {
    
    var rect = canvas.getBoundingClientRect();
    
    if (evt.clientX !== undefined && evt.clientY !== undefined) {
        return {
            x: evt.clientX - rect.left,
            y: evt.clientY - rect.top
        };   
    } 
}

/* BUTTONS */
$("#btn1").on("click", function() {
    ctx.globalAlpha = "0.2";
});

$("#btn2").on("click", function() {
    ctx.globalAlpha = "1";
});

$("#change-color").on("click", function() {
    ctx.strokeStyle = "#009933";
});

$("#canvas").on("mousedown", function(e) {
    isDrawing = true;
    var pos = getMousePosition(canvas, e);
    move(pos.x, pos.y);

});

$("#canvas").on("mousemove", function(e) {
    if(isDrawing) {
        var pos = getMousePosition(canvas, e);
        stroke(pos.x, pos.y);   
    }
});

$("#canvas").on("mouseup", function() {
    isDrawing = false;
});

function stroke(mouseX, mouseY) {
        ctx.globalCompositeOperation = "source-over";
        ctx.lineJoin = ctx.lineCap = "round";
        ctx.lineWidth = 10;
        ctx.globalAlpha = "0.2";  //NOTE ALWAYS SET TO 'TRANSPARENT' needs variable if you want to switch to solid.
        ctx.beginPath();
        ctx.moveTo(previousMouseX, previousMouseY);
        ctx.lineTo(mouseX, mouseY);
        ctx.closePath();
        ctx.stroke();

        ctx.globalAlpha = "1";
        ctx.lineWidth = 6;
        ctx.beginPath();
        ctx.moveTo(previousMouseX, previousMouseY);
        ctx.lineTo(mouseX, mouseY);
        ctx.closePath();
        ctx.stroke();

        move(mouseX, mouseY);
}

function move(mouseX, mouseY) {
        previousMouseX = mouseX;
        previousMouseY = mouseY;
}
canvas  {
    border: 1px solid #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type="button" id="btn1" value="Transparent">
<input type="button" id="btn2" value="Solid">
<input type="button" id="change-color" value="Green color"><br />
<canvas id="canvas" width="500" height="500">

这是铅笔效果。

改编自 Mohamed Moustafa 制作的精美粉笔效果:http://codepen.io/mmoustafa/pen/gmEdk

示例代码和演示:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw,ch;
var $canvas=$("#canvas");
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var scrollX=$canvas.scrollLeft();
var scrollY=$canvas.scrollTop();

var isDown=false;
var startX,startY,mouseX,mouseY;


var xLast = 0;
var yLast = 0;
var brushDiameter=2;
var fill1='rgba(255,255,255,0.5)';

var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/pad.jpg";
function start(){

  cw=canvas.width=img.width;
  ch=canvas.height=img.height;

  ctx.fillStyle = fill1; 
  ctx.strokeStyle = fill1; 
  ctx.lineWidth = brushDiameter;
  ctx.lineCap = 'round';

  ctx.drawImage(img,0,0);

  $("#canvas").mousedown(function(e){handleMouseDown(e);});
  $("#canvas").mousemove(function(e){handleMouseMove(e);});
  $("#canvas").mouseup(function(e){handleMouseUp(e);});
  $("#canvas").mouseout(function(e){handleMouseOut(e);});

}

function handleMouseDown(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();

  getOffset();
  xLast=mouseX=parseInt(e.clientX-offsetX);
  yLast=mouseY=parseInt(e.clientY-offsetY);

  isDown=true;

  draw(mouseX+1, mouseY+1);
}

function handleMouseUp(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();

  isDown=false;
}

function handleMouseOut(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();

  isDown=false;
}

function handleMouseMove(e){
  if(!isDown){return;}
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();

  getOffset();
  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);

  draw(mouseX,mouseY);
}

//252,254,171        
function draw(x,y){
  ctx.strokeStyle = 'rgba(0,0,0,'+(0.4+Math.random()*0.2)+')';
  ctx.beginPath();
  ctx.moveTo(xLast, yLast);  
  ctx.lineTo(x, y);
  ctx.stroke();

  // Chalk Effect
  var length = Math.round(Math.sqrt(Math.pow(x-xLast,2)+Math.pow(y-yLast,2))/(5/brushDiameter));
  var xUnit = (x-xLast)/length;
  var yUnit = (y-yLast)/length;
  for(var i=0; i<length; i++ ){
    var xCurrent = xLast+(i*xUnit); 
    var yCurrent = yLast+(i*yUnit);
    var xRandom = xCurrent+(Math.random()-0.5)*brushDiameter*1.2;   
    var yRandom = yCurrent+(Math.random()-0.5)*brushDiameter*1.2;
    ctx.clearRect( xRandom, yRandom, Math.random()*2+2, Math.random()+1);
  }
  xLast = x;
  yLast = y; 
}

function getOffset(){
  var BB=canvas.getBoundingClientRect();
  offsetX=BB.left;
  offsetY=BB.top;
}
body{ background-color:ivory; }
#canvas{border:1px solid red; background:white;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Drag to draw pencil line on the pad</h4>
<canvas id="canvas" width=300 height=300></canvas>