• canvas-学写字


    一、逻辑思维

    1. 初始化的时候加入画布,先画田字格,方法很简单,线条画
    2. 四种操作,点击(onmousedown),移开(onmouseup),移走(onmouseout),移动(onmousemove)
    3. 点击的时候进行操作:记录点击区域坐标,可以画
    4. 移开,移走的时候进行操作:不可以画
    5. 移动:记录位置变化,记录速度改变线宽,连接线条,上一次位置,上一次时间,上一次线宽不断更替
    6. 速度算法,自由发挥

    二、代码

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>writeFont</title>
    </head>
    
    <body>
      <canvas id="canvas" width="500" height="500"></canvas>
    
      <script>
        window.onload = function () {
          var canvas = document.getElementById("canvas");
          var context = canvas.getContext('2d');
          var color = 'green';
    
          drawGrid();
    
          // 画田字格
          function drawGrid() {
            context.save();
            context.strokeStyle = "rgb(230,11,9)";
            context.beginPath();
            context.moveTo(3, 3);
            context.lineTo(canvas.width - 3, 3);
            context.lineTo(canvas.width - 3, canvas.height - 3);
            context.lineTo(3, canvas.height - 3);
            context.closePath();
    
            context.lineWidth = 6;
            context.stroke();
    
            context.beginPath();
            context.moveTo(0, 0);
            context.lineTo(canvas.width, canvas.height);
    
            context.moveTo(canvas.width, 0);
            context.lineTo(0, canvas.height);
    
            context.moveTo(canvas.width / 2, 0);
            context.lineTo(canvas.width / 2, canvas.height);
    
            context.moveTo(0, canvas.width / 2);
            context.lineTo(canvas.width, canvas.height / 2);
            context.lineWidth = 1;
            context.stroke();
            context.restore();
          }
    
          var isMouseDown = false; //鼠标是否按下
          var lastLoc = { x: null, y: null };//鼠标上一次所在位置
          var lastTimestamp = 0;//时间戳
          var lastLineWidth = -1;//上一次线条宽度
          //鼠标按下
          canvas.onmousedown = function (e) {
            e.preventDefault();
            initLoc(e.clientX, e.clientY);
            isMouseDown = true;
          }
          //鼠标起来
          canvas.onmouseup = function (e) {
            e.preventDefault();
            isMouseDown = false;
          }
          //鼠标离开
          canvas.onmouseout = function (e) {
            e.preventDefault();
            isMouseDown = false;
          }
          //鼠标移动
          canvas.onmousemove = function (e) {
            e.preventDefault();
            if (isMouseDown) {
              //draw
              var curLoc = windowToCanvas(e.clientX, e.clientY);//获得当前坐标
              var curTimestamp = new Date().getTime();//当前时间
              var s = calcDistance(curLoc, lastLoc);//获得运笔距离
              var t = curTimestamp - lastTimestamp;//运笔时间
              var lineWidth = calcLineWidth(t, s);
    
              context.lineWidth = lineWidth;
    
              context.beginPath();
              context.moveTo(lastLoc.x, lastLoc.y);
              context.lineTo(curLoc.x, curLoc.y);
    
              context.strokeStyle = color;
              context.lineCap = "round"
              context.lineJoin = "round"
              context.stroke();
    
              lastLoc = curLoc;
              lastLineWidth = lineWidth;
              lastTimestamp = curTimestamp;
            }
    
          }
    
          //获得canvas坐标
          function windowToCanvas(x, y) {
            var bbox = canvas.getBoundingClientRect();
            return { x: Math.round(x - bbox.left), y: Math.round(y - bbox.top) };
            if(!lastLoc.x){
              lastLoc = { x: Math.round(x - bbox.left), y: Math.round(y - bbox.top) };
            }
          }
          //初始化上一次loc坐标
          function initLoc(x, y) {
            var bbox = canvas.getBoundingClientRect();
            lastLoc = { x: Math.round(x - bbox.left), y: Math.round(y - bbox.top) };
          }
          //求两点之间距离
          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 <= 0.1) {
              resultLineWidth = 30;
            } else if (v >= 10) {
              resultLineWidth = 1;
            } else {
              resultLineWidth = 30 - (v - 0.1) / (10 - 0.1) * (30 - 1);
            }
            if (lastLineWidth == -1) {
              return resultLineWidth;
            }
            return lastLineWidth * 2 / 3 + resultLineWidth * 1 / 3;
          }
        }
      </script>
    </body>
    
    </html>
    
  • 相关阅读:
    Retrofit/Okhttp API接口加固技术实践(上)
    浅析C#中的结构体和类
    iOS中 支付宝钱包具体解释/第三方支付 韩俊强的博客
    Java并发之volatile二
    dynamic initializer和全局变量
    二叉树转换成森林&amp;森林变成二叉树
    这才是真正的裸眼3D!超级震撼!!
    每一个开发人员都应该有一款自己的App
    Hibernate HQL的使用
    我的Android进阶之旅------&gt;Android 关于arm64-v8a、armeabi-v7a、armeabi、x86下的so文件兼容问题
  • 原文地址:https://www.cnblogs.com/it-cuiyi/p/10978602.html
Copyright © 2020-2023  润新知