zoukankan      html  css  js  c++  java
  • 适应web端和移动端的canvas写字板(初版)

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="height=device-height
    width=device-width,
    initial-scale = 1.0,
    minimum-scale = 1.0,
    maximum-scale = 1.0,
    user-scalable = no"/>
    <title>Title</title>
    </head>
    <style>
    #canvas{
    display:block;
    margin:0 auto;
    /*border:1px solid #aaa;*/
    }
    </style>
    <body>
    <canvas id="canvas"></canvas>
    </body>
    <script>
    var canvasWidth=Math.min(800,window.innerWidth-20);
    var canvasHeight=canvasWidth;
    var canvas=document.querySelector("#canvas");
    canvas.width=canvasWidth;
    canvas.height=canvasHeight;
    var cx=canvas.getContext("2d");
    var isMouseDown=false;
    var lastLoc={x:0,y:0};
    var lastTimestamp = 0;
    var lastLineWidth = -1;

    drawGrid();


    //写字开始函数
    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 curTimestamp = new Date().getTime();
    var s = calcDistance(curLoc,lastLoc);
    var t = curTimestamp - lastTimestamp;

    var lineWidth = calcLineWidth(t,s);

    // draw
    cx.beginPath();
    cx.moveTo(lastLoc.x,lastLoc.y);
    cx.lineTo(curLoc.x,curLoc.y);

    cx.strokeStyle="black";
    cx.lineWidth=lineWidth;
    cx.lineCap="round";
    cx.lineJoin="round";
    cx.stroke();

    lastLoc = curLoc;
    lastTimestamp=curTimestamp;
    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();
    // 触碰事件没有client,用e.touches.pageX取代;
    touch = e.touches[0];//第一个手指
    beginStroke({x:touch.pageX,y:touch.pageY})
    });
    canvas.addEventListener('touchmove',function (e) {
    e.preventDefault();
    touch = e.touches[0];
    moveStroke({x:touch.pageX,y:touch.pageY})
    });
    canvas.addEventListener('touchend',function (e) {
    e.preventDefault();
    endStroke();
    });


    var maxLineWidth = 30;
    var minLineWidth = 1;
    var maxStrokeV = 10;
    var minStrokeV = 0.1;
    //速度快慢改变笔画粗细函数(毛笔字效果,还不完善),以上参数可调配,这个效果需要一定的数学技巧,可以不用这个函数,写的字也能看。
    function calcLineWidth(t,s){
    var v = s/t;
    var resultLineWidth;

    if(v<=minStrokeV)
    resultLineWidth=maxLineWidth;
    else if(v>=maxStrokeV)
    resultLineWidth=minLineWidth;
    else
    resultLineWidth=maxLineWidth-(v-minStrokeV)/(maxStrokeV-minStrokeV)*(maxLineWidth-minLineWidth);

    if(lastLineWidth == -1)
    return resultLineWidth;
    //改变resultLineWidth和lastLineWidth的比例可改变笔画平滑度
    return resultLineWidth*1/3 + lastLineWidth*2/3;

    }
    //move时当前的点与上一个点的距离函数
    function calcDistance(loc1,loc2) {
    return Math.sqrt((loc1.x-loc2.x)*(loc1.x-loc2.x)+(loc1.y-loc2.y)*(loc1.y-loc2.y));
    }
    //鼠标在canvas上的坐标函数
    function windowToCanvas(x,y){
    var bbox=canvas.getBoundingClientRect();
    return {x:Math.round(x-bbox.left),y:Math.round(y-bbox.top)}
    }
    //画网格函数
    function drawGrid() {
    cx.save();

    cx.strokeStyle = "red";
    cx.beginPath();
    cx.moveTo(3, 3);
    cx.lineTo(canvas.width - 3, 3);
    cx.lineTo(canvas.width - 3, canvas.height - 3);
    cx.lineTo(3, canvas.height - 3);
    cx.closePath();

    cx.lineWidth = 6;
    cx.stroke();

    cx.beginPath();
    cx.moveTo(0, 0);
    cx.lineTo(canvas.width, canvas.height);

    cx.moveTo(canvas.width, 0);
    cx.lineTo(0, canvas.height);

    cx.moveTo(canvas.width / 2, 0);
    cx.lineTo(canvas.width / 2, canvas.height);

    cx.moveTo(0, canvas.height / 2);
    cx.lineTo(canvas.width, canvas.height / 2);

    cx.lineWidth = 1;
    cx.stroke();

    cx.restore();
    }

    </script>
    </html>
  • 相关阅读:
    6.让代码更具可读性
    5构造函数和析构函数
    4面向对象之类的继承
    3隐形的指针
    2面向对象之类的封装
    od快捷键
    1.纠结的c++
    101宏定义的其他用法
    100解剖宏定义函数
    99,printf scanf手动功能实现
  • 原文地址:https://www.cnblogs.com/wabxl/p/6056280.html
Copyright © 2011-2022 走看看