以编程方式操作手绘线的最佳方法

时间:2013-12-17 12:16:02

标签: html canvas graphics bitmap 2d

请注意,我没有数学或计算机图形学的背景知识。

如果有可能的话,我想知道程序化操作手绘线的最佳方法。

绘制操作必须在html页面中完成。 (可能无关紧要)

我坚持的方法:

  1. 在画布上画一条线(上下有手绘线) - >转换为位图 - > somewhow intepret line on bitmap并操纵它的形式(这可能吗?)

  2. 而不是从位图解释,在绘图时刻有一种按钮来切换捕获开/关和捕获后,生成某种我能够操作的数学函数,并从中生成新的位图

2 个答案:

答案 0 :(得分:2)

是的,你可以。

这并不困难,但要学习很多小编码方面。

如果您处于“绘图”模式,则会收集用户点击的鼠标点,并从所有这些点开始划线。

如果您处于“编辑”模式,您可以让用户将其中一个收集点拖动到新坐标,并从所有编辑点中划线。

以下是您可以查看和学习的起始代码以及小提琴:http://jsfiddle.net/m1erickson/J5PrN/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    #canvas{border:1px solid red;}
</style>

<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    ctx.lineCap = "round";
    ctx.lineJoin = "round";
    ctx.lineWidth=3;

    var canvasOffset=$("#canvas").offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;
    var isDown=false;
    var startX;
    var startY;

    var points=[];
    var selected=-1;
    var mode="draw";

    function draw(){
        ctx.clearRect(0,0,canvas.width,canvas.height);
        ctx.beginPath();
        ctx.moveTo(points[0].x,points[0].y);
        for(var i=1;i<points.length;i++){
            ctx.lineTo(points[i].x,points[i].y);
        }
        ctx.stroke();
        if(mode=="edit"){
            for(var i=0;i<points.length;i++){
                ctx.beginPath();
                ctx.arc(points[i].x,points[i].y,10,0,Math.PI*2);
                ctx.closePath();
                ctx.fill();
            }
        }
    }

    function handleMouseDown(e){
      startX=parseInt(e.clientX-offsetX);
      startY=parseInt(e.clientY-offsetY);

      if(mode=="draw"){
          points.push({x:startX,y:startY});
          draw();
      }else if(mode=="edit"){
          for(var i=0;i<points.length;i++){
              var pt=points[i];
              var dx=startX-pt.x;
              var dy=startY-pt.y;
              if(dx*dx+dy*dy<100){
                  selected=i;
                  return;
              }
          }
      }

    }

    function handleMouseUp(e){
        selected=-1;
    }

    function handleMouseOut(e){
        selected=-1;
    }

    function handleMouseMove(e){
      if(selected<0){return;}

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

      // Put your mousemove stuff here
      if(selected<0){return;}
      var dx=mouseX-startX;
      var dy=mouseY-startY;
      startX=mouseX;
      startY=mouseY;
      var pt=points[selected];
      points[selected]={x:pt.x+dx,y:pt.y+dy};
      draw();
    }

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

    $("#draw").click(function(){ 
        mode="draw"; 
        draw(); 
        $instructions.text("Click points to draw a line");
    });
    $("#edit").click(function(){ 
        mode="edit"; 
        draw(); 
        $instructions.text("Drag points to move the line");
    });
    $instructions=$("#instructions");


}); // end $(function(){});
</script>

</head>

<body>
    <button id="draw">Add to Line</button>
    <button id="edit">Change Line</button><br>
    <p id="instructions">Click points to draw a line</p>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

答案 1 :(得分:1)

我无法与HTML交谈,但在大多数应用程序中,我看到(such as this one),手绘线条被分成小的直线段。这是因为传感系统(触摸或鼠标)为您的应用程序提供了(有点)连续的点流;它没有给出实际的线。然后使用各个段来执行应用程序的目标。

在绘制线条的情况下,绘制线条时,应用程序采用点并平滑它们(三次样条,最小二乘多项式拟合,b样条等),然后将平滑的线条绘制到屏幕上。颜色和样式(钢笔,铅笔,粉笔等)。这为用户提供了关于他们的手移动位置的即时反馈等。

在手势控制的情况下,可以绘制一些覆盖线以给予用户反馈,但是以不同方式处理片段以确定手势(这可能非常复杂)。

将线条缓存为一系列手势,为您提供撤消/重做选项。您还可以将绘图存储为一系列手势而不是固定位图。

这有用吗?