Canvas 写字板

输入法的手写功能,就是用手在屏幕上写字,大家是否觉得特别有意思呢?今天就给大家介绍一下如何用Canvas实现写字板功能……

废话不多说,先上效果图:

演示地址:点我(支持各种PC和各种移动终端设备哦!)

JS代码:(本Demo中HTML和CSS代码比较简单,故只列出JS代码,有疑问的小伙伴可进入演示地址查看源码)

var canvasWidth=canvasHeight=Math.min(400,$(window).width()-20),
    canvas=document.getElementById("canvas"),
    context=canvas.getContext("2d"),
    isMouseDown=false,
    lastloc={x:0,y:0},
    lastTimeTamp= 0,
    lastLineWidth=-1,
    strokeColor="#1e7dd2";
    canvas.width=canvasWidth;
    canvas.height=canvasHeight;
 
$(".control").width(canvasWidth);
 
drawGrid();
 
$(".op_btn").click(function(){
    context.clearRect(0,0,canvasWidth,canvasHeight);
    drawGrid();
});
$(".color_btn").click(function(){
    $(".color_btn").removeClass('on');
    $(this).addClass('on');
    strokeColor=$(this).css('backgroundColor');
});
 
function beginStroke(point){
    isMouseDown=true;
    lastloc=windowToCanvas(point.x,point.y);
    lastTimeTamp=new Date().getTime();
}
function endStroke(){
    isMouseDown=false;
}
function moveStroke(point){
    var curloc=windowToCanvas(point.x,point.y);
    var curTimeTamp=new Date().getTime();
    var s=calDistance(curloc,lastloc);
    var t=curTimeTamp-lastTimeTamp;
    var lineWidth=calclientWidth(t,s);
    context.beginPath();
    context.moveTo(lastloc.x,lastloc.y);
    context.lineTo(curloc.x,curloc.y);
    context.lineWidth=lineWidth;
    context.lineCap="round";
    context.lineJoin="round";
    context.strokeStyle=strokeColor;
    context.stroke();
    lastloc=curloc;
    lastTimeTamp=curTimeTamp;
    lastLineWidth=lineWidth;
}
 
canvas.onmousedown=function(e){
    e.preventDefault();
    beginStroke({x: e.clientX,y: e.clientY});
};
canvas.onmouseup=function(e){
    e.preventDefault();
    endStroke();
};
canvas.onmouseout=function(e){
    e.preventDefault();
    endStroke();
};
canvas.onmousemove=function(e){
    e.preventDefault();
    if(isMouseDown){
    moveStroke({x: e.clientX,y: e.clientY});
    }
};
 
canvas.addEventListener('touchstart',function(e){
    e.preventDefault();
    touch= e.touches[0];
    beginStroke({x: touch.pageX,y: touch.pageY});
});
canvas.addEventListener('touchmove',function(e){
    e.preventDefault();
    if(isMouseDown){
    touch= e.touches[0];
    moveStroke({x: touch.pageX,y: touch.pageY});
    }
});
canvas.addEventListener('touchend',function(e){
    e.preventDefault();
    endStroke();
});
 
function calclientWidth(t,s){
    var v=s/t;
    var resultLineWidth;
    if(v<=0.1) resultLineWidth=16;
    else if(v>=5) resultLineWidth=1;
    else resultLineWidth=16-(v-0.1)/(5-0.1)*(16-1);
 
    if(lastLineWidth==-1) return resultLineWidth;
    return resultLineWidth*1/3+lastLineWidth*2/3;
}
 
function calDistance(loc1,loc2){
    return Math.sqrt((loc1.x-loc2.x)*(loc1.x-loc2.x)+(loc1.y-loc2.y)*(loc1.y-loc2.y));
}
 
function windowToCanvas(x,y){
    var bBox=canvas.getBoundingClientRect();
    return{x:Math.round(x-bBox.left),y:Math.round(y-bBox.top)};
}
 
function drawGrid(){
    drawDashedLine(0,0,canvasWidth,canvasHeight,4);
    drawDashedLine(0,canvasHeight,canvasWidth,0,4);
    drawDashedLine(0,canvasHeight/2,canvasWidth,canvasHeight/2,4);
    drawDashedLine(canvasWidth/2,0,canvasWidth/2,canvasHeight,4);
 
    context.save();
    context.beginPath();
    context.strokeStyle="#ed0a2b";
    context.moveTo(2,2);
    context.lineTo(canvasWidth-2,2);
    context.lineTo(canvasWidth-2,canvasHeight-2);
    context.lineTo(2,canvasHeight-2);
    context.lineWidth=4;
    context.closePath();
    context.stroke();
    context.restore();
}
 
function drawDashedLine(x1,y1,x2,y2,dashLength){
    dashLength = dashLength===undefined ? 5 : dashLength;
    var deltaX = x2 – x1;
    var deltaY = y2 – y1;
    var numDashed = Math.floor(Math.sqrt(deltaX*deltaX+deltaY*deltaY)/dashLength);
 
    context.save();
    context.beginPath();
    context.strokeStyle="#ff0025";
    for(var i=0; i<numDashed;i++){
    context[i%2==0 ? “moveTo”:”lineTo”](x1+(deltaX/numDashed)*i,y1+(deltaY/numDashed)*i);
    }
    context.lineWidth=1;
    context.closePath();
    context.stroke();
    context.restore();
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注