0

I'm completely lost, any ideas would be much appreciated!

So I have a canvas with an image inside which can be dragged around by the user. The initial code worked, but would re-center the image onto the mouses reticle instead of being dragged from the portion of the image the user clicks on. So I revised the math to the point where that problem is fixed, but another one popped up.

This code will execute properly except for about a third of the frames it's drawn down and too the right. It actually looks as if the amount that it's drawn to the right corresponds with the images width, and the same with the height.

  ctx.clearRect(0,0,canvasWidth,canvasHeight);
  imageX = e.clientX * 2 - imageX;
  imageY = e.clientY * 2 - imageY;
  drawImage(imageX, imageY);

This is the code which triggers it:

   $("#editor").mousemove(function(e){handleMouseMove(e);});

Initially I thought maybe it was an issue with the image not being "loaded" in time, but I attached limit.js and throttled the event down to 100 milliseconds, same result.

Here the whole file:

<html>
    <head>
        <link rel="stylesheet" type="text/css" href="../../frameworks/foundation-6.3.1-complete/css/foundation.min.css"></link>
        <script src="../../frameworks/foundation-6.3.1-complete/js//vendor/jquery.js"></script>
        <script src="../../frameworks/foundation-6.3.1-complete/js//vendor/foundation.min.js"></script>
        <script src="../../frameworks/handlebars-v4.0.5.js"></script>
        <script src="./limit.js"></script>
    </head>
    <style>
        #editor{
            background-color:#626262;
            margin:auto;
            display:block;
        }
        .dragme{
            position:relative;
        }
    </style>
    <body>
        <div class="row">
            <div class='small-12 medium-12 large-12 columns'>
                <ul>
                    <li id="marquee">Marquee</li>
                    <li id="pointer">Pointer</li>
                    <li id="pencil">Pencil</li>
                </ul>
            </div>
        </div>

        <div id="viewportBackground">
            <canvas id="editor" width="1000" height="800" style="border:1px solid #d3d3d3;">
        </div>

        <div class="row">
            <div class='small-12 medium-10 large-10 columns'>

            </div>
            <div class='small-12 medium-2 large-2 columns'>

            </div>
        </div>

<script>
$(function(){
    var email = "mhill601@gmail.com";
    var mediaID = "9";
    var activeTool = "marquee";
    var img; 
    var imageX = 10;
    var imageY = 10;

    getMedia(mediaID);

    function displayImage(imageURI){
        img = new Image;
        img.onload = function(){
            var c = document.getElementById("editor");
            var ctx = c.getContext("2d");
            ctx.drawImage(img, 10, 10); 
        }
        img.src = imageURI;
    }

    var canvas=document.getElementById("editor");
    var ctx=canvas.getContext("2d");
    var canvasOffset=$("#editor").offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;
    var canvasWidth=canvas.width;
    var canvasHeight=canvas.height;
    var isDragging=false;



    function handleMouseDown(e){
      canMouseX=parseInt(e.clientX-offsetX);
      canMouseY=parseInt(e.clientY-offsetY);
      // set the drag flag
      isDragging=true;

      console.log("ImageY: " + imageY);
      console.log("ImageX: " + imageX);

    }

    function handleMouseUp(e){
      canMouseX=parseInt(e.clientX-offsetX);
      canMouseY=parseInt(e.clientY-offsetY);
      // clear the drag flag
      isDragging=false;
    }

    function handleMouseOut(e){
      canMouseX=parseInt(e.clientX-offsetX);
      canMouseY=parseInt(e.clientY-offsetY);
      // user has left the canvas, so clear the drag flag
      //isDragging=false;
    }

    function handleMouseMove(e){
      canMouseX=parseInt(e.clientX-offsetX);
      canMouseY=parseInt(e.clientY-offsetY);



      // if the drag flag is set, clear the canvas and draw the image
      if(isDragging){
          ctx.clearRect(0,0,canvasWidth,canvasHeight);
          //ctx.drawImage(img,canMouseX-128/2,canMouseY-120/2,128,120);
          //ctx.drawImage(img,canMouseX- img.naturalWidth/2,canMouseY- img.naturalHeight/2,img.naturalWidth,img.naturalHeight);

          //imageX = canMouseX - img.naturalWidth/2;
          //imageY = canMouseY - img.naturalHeight/2;
          //ctx.drawImage(img,(canMouseX - img.naturalWidth/2), (canMouseY - img.naturalHeight/2),img.naturalWidth,img.naturalHeight);


          //imageX = canMouseX + (imageX + ((e.clientX - offsetX) * -1));
          //imageY = canMouseY + (imageY + ((e.clientY - offsetY) * -1));





          imageX = e.clientX * 2 - imageX;
          imageY = e.clientY * 2 - imageY;


          drawImage(imageX, imageY);
          //ctx.drawImage(img, imageX, imageY, img.naturalWidth, img.naturalHeight);
      }
    }
    function drawImage(imageX, imageY){
        ctx.drawImage(img, imageX, imageY, img.naturalWidth, img.naturalHeight);
    }

    function getMedia(mediaID){
    $.ajax({
       type: "POST",
       url: "../../php/media/GetMediaByID.php",
       data: {
            mediaID : mediaID
       },
       success: function(result)
       {
            var image = JSON.parse(result);
            displayImage(image.uri);
            //document.getElementById("mediaItem").src = image.uri;
       }
     });
    }

    $("#editor").mousedown(function(e){handleMouseDown(e);});
    $("#editor").mousemove(function(e){handleMouseMove(e);});

    $("#editor").mouseup(function(e){handleMouseUp(e);});
    $("#editor").mouseout(function(e){handleMouseOut(e);});

});
</script>

    </body>
</html>
Mark Hill
  • 161
  • 2
  • 9
  • Possible duplicate of [redrawing canvas html5 without flickering](http://stackoverflow.com/questions/18423950/redrawing-canvas-html5-without-flickering) – Kaiido May 07 '17 at 05:38

1 Answers1

0

The issue was actually a logical problem, took me a long while to hone in on it. I'd give a more expanded answer, but I'm not eintirelly sure what the particular problem was. Something with how I was storing and then overwriting variables. Below is the working code (restructured a bit) in case it's useful to anyone else.

var nav = (function () {
    var imageX = 10;
    var imageY = 10;
    var lastXCoord = 10;
    var lastYCoord = 10;
    var zoom = 1;
    var isMouseDownQued = false;

    var isDragging = false;

    var img;

    return{
        setZoom: function(zoomIncrement){
            zoom += zoomIncrement;
        },
        getZoom: function(){
            return zoom;
        },
        getLastXCoord: function(){
            return lastXCoord;
        },
        getLastYCoord: function(){
            return lastYCoord;
        },
        getImg: function(){
            return img;
        },
        setDrag: function(dragStatus){
            isDragging = dragStatus;
        },
        displayImage: function (imageURI){
            img = new Image;
            img.onload = function(){
                var c = document.getElementById("editor");
                var ctx = c.getContext("2d");
                ctx.drawImage(img, 10, 10, img.naturalWidth * zoom, img.naturalHeight * zoom);  
            }
            img.src = imageURI;
        },
        handleMouseDown: function (e)
        {
            canMouseX=parseInt(e.clientX-offsetX);
            canMouseY=parseInt(e.clientY-offsetY);
            imageX = e.clientX - imageX;
            imageY = e.clientY - imageY;
        },
        handleMouseUp: function (e)
        {
          canMouseX=parseInt(e.clientX-offsetX);
          canMouseY=parseInt(e.clientY-offsetY);

          imageX = lastXCoord;
          imageY = lastYCoord;
        },
        handleMouseOut: function (e)
        {
          canMouseX=parseInt(e.clientX-offsetX);
          canMouseY=parseInt(e.clientY-offsetY);
          // user has left the canvas, so clear the drag flag
          isDragging=false;

          imageX = lastXCoord;
          imageY = lastYCoord;
        },
        handleMouseMove: function (e){
          canMouseX=parseInt(e.clientX-offsetX);
          canMouseY=parseInt(e.clientY-offsetY);

          if(isDragging){
              ctx.clearRect(0,0,canvasWidth,canvasHeight);
              ctx.drawImage(img, e.clientX - imageX, e.clientY - imageY, img.naturalWidth * zoom, img.naturalHeight * zoom);
              lastXCoord = e.clientX - imageX;
              lastYCoord = e.clientY - imageY;
          }
        }

    }


}());

$( "#zoomIn" ).click(function() {
    if(nav.getZoom() <= 2.9){
        nav.setZoom(0.2);
        reDraw();
    }
});
$( "#zoomOut" ).click(function() {
    if(nav.getZoom() >= -2.9){
        nav.setZoom(-0.2);
        reDraw();
    }
});
$("#editor").mousedown(function(e){
    if(tool.getName() == "move"){
        e.preventDefault();
        nav.setDrag(true);
        nav.handleMouseDown(e);
    }
});
$("#editor").mouseup(function(e){
    if(tool.getName() == "move"){
        nav.setDrag(false);
        nav.handleMouseUp(e);
    }
});
$("#editor").mousemove(function(e){
    if(tool.getName() == "move"){
        nav.handleMouseMove(e);
    }
});
$("#editor").mouseout(function(e){
    if(tool.getName() == "move"){
        nav.handleMouseOut(e);
    }
});
Mark Hill
  • 161
  • 2
  • 9