1

私は3つのアリを持っています:

 clickX = [],
    clickY = [],
    clickDrag = [];

クリックするとこうなります。

$('#canvasCursor').mousedown(function (e) {
    console.log('down');
    mouseX = e.pageX - this.offsetLeft;
    mouseY = e.pageY - this.offsetTop;
    paint = true;
    addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);
    redraw();
});

ここでは、クリックを配列に追加して描画します。

function redraw() { ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); // キャンバスをクリア

    ctx.strokeStyle = "green";
    ctx.lineJoin = "round";
    ctx.lineWidth = brushSize*2;

    for (var i = 0; i < clickX.length; i++) {
        ctx.beginPath();
        if (clickDrag[i] && i) {
            ctx.moveTo(clickX[i - 1], clickY[i - 1]);
        } else {
            ctx.moveTo(clickX[i] - 1, clickY[i]);
        }
        ctx.lineTo(clickX[i], clickY[i]);
        ctx.closePath();
        ctx.stroke();
    }
}

スライダーを使用して var brushSize を動的に変更すると、当時のサイズではなく新しいサイズで画像全体が再描画されるため、配列の方法を取り除こうとしています。特定のオブジェクトのサイズを配列に保存してから個別にペイントする方法がわかりません。

ブラシサイズの変更を修正できる限り、この方法で得られる元に戻す機能を実装できなくてもかまいません。ここで、私がとりとめのないことを見ることができます!http://www.taffatech.com/Paint.html

-また、配列から描画しているため、遅く見え、推測しています

4

4 に答える 4

1

キャンバスを使用してペイントのように描画する方法は次のとおりです

元に戻す機能が必要な場合は、ユーザーが描いたすべての線分を記録することをお勧めします。

これは、ユーザーが描画したすべてのポイント (ポリライン) を含むポイント配列で行われます。

ブラシのサイズとブラシの色を追跡するには、この情報も配列に含める必要があります。

したがって、配列の各要素には、各線分に関する次の情報が含まれます。

  • x: この線分の終わりの x 座標
  • y: 終了 y 座標
  • size: ブラシのサイズ (lineWidth)
  • color: ブラシの色 (strokeStyle)
  • mode: 「begin」は新しい行の始まりを示し、「end」はこの行の終わりを示します。

それはどのように機能しますか?

ユーザーが線分をドラッグして描いているとき、各 mousemove イベントは と で現在の線分を拡張していcontext.lineToますcontext.stroke

ユーザーが新しい BrushSize または BrushColor を選択すると、context.beginPath が開始されcontext.beginPathます。

ユーザーが [元に戻す] ボタンを押したままにすると、最後の線分の最後の点が点配列からポップされます。次に、生き残ったすべての線分が再描画されます。元に戻すボタンは、押したままにすると 1/10 秒ごとに起動します。

ここにコードとフィドルがあります: http://jsfiddle.net/m1erickson/AEYYq/

<!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>
<!--[if lt IE 9]><script type="text/javascript" src="../excanvas.js"></script><![endif]-->

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

<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var lastX;
    var lastY;
    var mouseX;
    var mouseY;
    var canvasOffset=$("#canvas").offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;
    var isMouseDown=false;
    var brushSize=20;
    var brushColor="#ff0000";
    var points=[];


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

      // Put your mousedown stuff here
      ctx.beginPath();
      if(ctx.lineWidth!=brushSize){ctx.lineWidth=brushSize;}
      if(ctx.strokeStyle!=brushColor){ctx.strokeStyle=brushColor;}
      ctx.moveTo(mouseX,mouseY);
      points.push({x:mouseX,y:mouseY,size:brushSize,color:brushColor,mode:"begin"});
      lastX=mouseX;
      lastY=mouseY;
      isMouseDown=true;
    }

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

      // Put your mouseup stuff here
      isMouseDown=false;
      points.push({x:mouseX,y:mouseY,size:brushSize,color:brushColor,mode:"end"});
    }


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

      // Put your mousemove stuff here
      if(isMouseDown){
          ctx.lineTo(mouseX,mouseY);
          ctx.stroke();     
          lastX=mouseX;
          lastY=mouseY;
          // command pattern stuff
          points.push({x:mouseX,y:mouseY,size:brushSize,color:brushColor,mode:"draw"});
      }
    }


    function redrawAll(){

        if(points.length==0){return;}

        ctx.clearRect(0,0,canvas.width,canvas.height);

        for(var i=0;i<points.length;i++){

          var pt=points[i];

          var begin=false;

          if(ctx.lineWidth!=pt.size){
              ctx.lineWidth=pt.size;
              begin=true;
          }
          if(ctx.strokeStyle!=pt.color){
              ctx.strokeStyle=pt.color;
              begin=true;
          }
          if(pt.mode=="begin" || begin){
              ctx.beginPath();
              ctx.moveTo(pt.x,pt.y);
          }
          ctx.lineTo(pt.x,pt.y);
          if(pt.mode=="end" || (i==points.length-1)){
              ctx.stroke();
          }
        }
        ctx.stroke();
    }

    function undoLast(){
        points.pop();
        redrawAll();
    }

    ctx.lineJoin = "round";
    ctx.fillStyle=brushColor;
    ctx.lineWidth=brushSize;

    $("#brush5").click(function(){ brushSize=5; });
    $("#brush10").click(function(){ brushSize=10; });
    // Important!  Brush colors must be defined in 6-digit hex format only
    $("#brushRed").click(function(){ brushColor="#ff0000"; });
    $("#brushBlue").click(function(){ brushColor="#0000ff"; });

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

    // hold down the undo button to erase the last line segment
    var interval;
    $("#undo").mousedown(function() {
      interval = setInterval(undoLast, 100);
    }).mouseup(function() {
      clearInterval(interval);
    });


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

</head>

<body>
    <p>Drag to draw. Use buttons to change lineWidth/color</p>
    <canvas id="canvas" width=300 height=300></canvas><br>
    <button id="undo">Hold this button down to Undo</button><br><br>
    <button id="brush5">5px Brush</button>
    <button id="brush10">10px Brush</button>
    <button id="brushRed">Red Brush</button>
    <button id="brushBlue">Blue Brush</button>
</body>
</html>
于 2013-06-16T05:46:11.557 に答える
1

編集:申し訳ありませんが、いくつかのタイプミスを修正 しました編集2:そしてまた。テストするのは少し難しいです。

毎回各ポイントを再描画する理由はありません。これを行うようにリスナーを変更できます。

var prevMouseX=null,prevMouseY=null;
$('#canvasCursor').mousedown(function (e) {
    paint = true;

    console.log('down');
    //get current mouse coords
    mouseX = e.pageX - this.offsetLeft;
    mouseY = e.pageY - this.offsetTop;

    if (prevMouseX==null) {
        //store these coordinates for next time if they haven't been defined yet
        prevMouseX = mouseX;
        prevMouseY = mouseY;
    }
});

$('#canvasCursor').mousemove(function (e) {
    //get current mouse coords
    mouseX = e.pageX - this.offsetLeft;
    mouseY = e.pageY - this.offsetTop;

    if (prevMouseX==null) {
        //store these coordinates for next time if they haven't been defined yet
        prevMouseX = mouseX;
        prevMouseY = mouseY;
    }

    if (paint) {drawline(mouseX,mouseY,prevMouseX,prevMouseY);}

    //store these coordinates for next time
    prevMouseX = mouseX;
    prevMouseY = mouseY;
});

関数 drawLine は次のように定義されています。

function drawline(x1,y1,x2,y2) {
ctx.strokeStyle = "green";
    ctx.lineJoin = "round";
    ctx.lineWidth = brushSize*2;

    ctx.beginPath();
    ctx.moveTo(x1,y1);
    ctx.lineTo(x2,y2);
    ctx.closePath();
    ctx.stroke();
}
于 2013-06-15T23:37:16.823 に答える
1

ペイントを配列に保存しないでください
。描画が非常に遅くなります。キャンバスをクリアせずに最新の線を引くだけです。そうすれば、線の太さの変更は描画前には影響しません。したがって、削除ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);してforループします。関数を実行するたびにではなく、変更が発生したときにのみコンテキストスタイル (lineWidth など)を変更することもできredraw()ます。

元に戻すのサポート
マウス ダウン セッションごとに異なるキャンバスを作成し、それらを一緒に描画することで、元に戻す機能を簡単に作成できます。元に戻すを押すと、キャンバス配列から最新のキャンバスが単純に接合されます。一時キャンバスへの描画の詳細については、Google を参照してください。

于 2013-06-15T23:45:32.570 に答える