H5 canvas 手写功能

支持手指和鼠标写字,直接上代码:
HTML:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <link rel="stylesheet" type="text/css" href="css/reset.css" />
        <link rel="stylesheet" type="text/css" href="css/index.css" />
    </head>
    <body>
    <canvas id='canvas'></canvas>  
    <div id="canvas-btn">  
        <div id="clear_btn" class="op_btn">重画</div>  
        <div class="cleaerfix"></div>  
    </div>  
    <script type="text/javascript" src="js/flexible.js"></script>
    <script type="text/javascript" src="js/zepto.min.js"></script>
    <script type="text/javascript" src="js/touch.js"></script>
    <script type="text/javascript" src="js/index.js"></script>
    </body>
</html>

css:

body,html{  
    margin: 0;  
    padding: 0;  
    height: 100%;  
} 
 #canvas {
    border:0.01rem solid #f30;
 }
#canvas-btn{  
    display: block;  
    margin: 0;  
    padding: 0.13rem;  
}  
#clear_btn{  
    width: 80%;  
    background: #ca4341;  
    margin: auto;  
    text-align: center;  
    line-height: 1rem;  
    margin-top: 0.27rem;  
    color: #fff;  
    border-radius: 1.31rem;   
    clear: both;  
}  

js:


    //获取页面尺寸  
    var canvasWidth = document.body.clientWidth;  
    var canvasHeight = canvasWidth;  
    //声明canvas  
    var canvas = document.getElementById('canvas');  
    var context = canvas.getContext('2d');  
    //设置canvas尺寸  
    canvas.width = canvasWidth * 0.98;  
    canvas.height = canvasHeight;  
    //画笔颜色  
    var strokeColor = "#f30";  
    //鼠标  
    isMouseDown = false;  
    //上一次绘制的的坐标  
    var lastLoc = {x:0,y:0};  
    //初始记录事件  
    var lastTimestamp = 0;  
    //上一次线条宽度  
    var lastLineWidth = -1;  
    //var   
    var maxV = 10;  
    var minV = 0.1;  
    var maxLineWidth = 10;  
    var minLineWidth = 1;  
      
    //点击色块切换画笔颜色  
    $(".colorBtn").on("click",function (e){  
        $(".colorBtn").removeClass('colorBtnBorder');  
        $(this).addClass("colorBtnBorder");  
        strokeColor = $(this).css("background-color");  
    })  
    //清除  
    $('#clear_btn').on('click',function (e){  
        context.clearRect( 0, 0, canvasWidth,canvasHeight);    
    })  
    //获取canvas 坐标 x,y 分别代表相对window内的xy  
    function windowToCanvas(x,y){  
        //canvas提供的方法返回canvas 距 他外围包围盒子的距离left,top值  
        var bbox = canvas.getBoundingClientRect();  
        //返回的就是canvas 内的坐标值  
        return {x : Math.round(x - bbox.left),y : Math.round(y - bbox.top)}  
    }   
    //封装 事件  
    function beginStroke(point){  
        isMouseDown = true;  
        //第一次用户画的坐标初始值  
        lastLoc = windowToCanvas(point.x,point.y);  
        //获取首次点击鼠标 事件戳  
        lastTimestamp = new Date().getTime();  
    }  
    function endStroke(){  
        isMouseDown = false;  
    }  
    function moveStroke(point){  
        //开始绘制直线  
        var curLoc = windowToCanvas(point.x , point.y);  
        //路程  
        var s = calcDistance( curLoc, lastLoc);  
        //结束时间  
        var curTimestamp = new Date().getTime();  
        //时间差  
        var t = curTimestamp - lastTimestamp;  
        //绘制线条粗细  
        var lineWidth = calcLineWidth(t,s);  
      
        //绘制  
        context.beginPath();  
        context.moveTo(lastLoc.x ,lastLoc.y);  
        context.lineTo(curLoc.x , curLoc.y);  
        context.strokeStyle = strokeColor;  
        context.lineWidth = lineWidth;  
        context.lineCap = "round";  
        context.lineJoin = "round";  
        context.stroke();     
        //给lastLoc赋值维护  
        lastLoc = curLoc;  
        //时间更新  
        lastTimestamp = curTimestamp;  
        lastLineWidth = lineWidth;    
    }  
    //pc鼠标事件  
    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("touchend",function(e){  
        e.preventDefault();  
        endStroke();  
    });  
    canvas.addEventListener("touchmove",function(e){  
        e.preventDefault();  
        if( isMouseDown){  
            touch = e.touches[0];  
            moveStroke({x: touch.pageX , y:touch.pageY});     
        }  
    });  
    //速度 = 路程 / 时间     用来计算书写速度来改变线条粗细  
    function calcDistance (loc1,loc2){  
        //返回 数的平方根  
        return Math.sqrt((loc1.x - loc2.x) * (loc1.x - loc2.x) + (loc1.y - loc2.y) * (loc1.y - loc2.y) );  
    }  
    //线条宽度  
    function calcLineWidth(t,s){  
        var v = s/t;  
        var resultLineWidth;  
        if(v <= minV){  
            resultLineWidth = maxLineWidth;  
        }else if(v >= maxV){  
            resultLineWidth = minLineWidth;  
        }else{  
            resultLineWidth = maxLineWidth - (v-minV)/(maxV-minV)*(maxLineWidth-minLineWidth);  
        }  
        if( lastLineWidth == -1){  
            return resultLineWidth;  
        }else{  
            return lastLineWidth*2/3 + resultLineWidth*1/3;  
        }  
    }  

github:https://github.com/wangruirui007/H5-Write

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • afinalAfinal是一个android的ioc,orm框架 https://github.com/yangf...
    passiontim阅读 15,360评论 2 44
  • 看我是演说家,越看越有感受。 比如,你要不断突破自己的舒适圈,你才能变得更优秀! 比如,父与子的战争。 比如,全职...
    水中的云采阅读 349评论 1 0
  • 这样 弄雨生思的夜 闭上眼 细聆听 雨点奏响的天籁 让心 随之雀跃 让魂 追风伴雨 来吧 朋友 抛开 烦恼 栖在一...
    藉的百味阅读 235评论 0 0
  • openssl file not find 解决方法: 小技巧:可以先拖拽支付宝SDK下的小.h文件到Header...
    wonderstruck阅读 197评论 0 0
  • 今天我们聊一聊34-36章说话之道。 34.别人赞美你一句,你就回一句赞美 别人骂你一句,你回骂他一句,这叫吵架;...
    易小六阅读 867评论 0 3