David
David

Reputation: 276

resize canvas and paint on right place

I have a canvas and I have loaded an Image on canvas. I can paint on the canvas but in small browser size, some part of canvas will be hidden. So i have used jQuery resize and it resize the canvas and show full image inside it and this is fine . It resize canvas and full image is displayed. However, If I now paint on it , it paints/draws far away the actual place. It happens only in resizing canvas but not on the full width of browser. Is there any way to solve this issue. I am looking for a ways to resize canvas and show full image on small device and should paint on actual place not far away. Initially I want to show abit bigger canvas of width alteast 800px and height 400px

  <canvas data-fieldid="1" id="can-1"class="image-canvas"></canvas>
       
      

Below is the js code that allows user to draw on image of canvas

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
sdsdfds
<script>
        var  flag = false,
        prevX = 0,
        currX = 0,
        prevY = 0,
        currY = 0,
        dot_flag = false;

    var x = "red",
        y = 3;

    function init(fieldId) {
        //fieldId are multiple Ids, but I get here one at a time 
        let canvas = document.getElementById('can-' + fieldId);
        let ctx = canvas.getContext("2d");

        ratio = 400 / 800;
        canvas.width =
        document.body.clientWidth < 800 ? document.body.clientWidth : 800;
        canvas.height = canvas.width * ratio;


        let base_image = new Image();
        base_image.crossOrigin = "anonymous"
        base_image.src = document.getElementById('image_' + fieldId).src
        base_image.onload = function() {
            ctx.drawImage(base_image,0,0,canvas.width, canvas.height);

        };
        canvas.addEventListener("mousemove", function(e) {
            findxy('move', e, this)
        }, false);
        canvas.addEventListener("mousedown", function(e) {
            findxy('down', e, this)

        }, false);
        canvas.addEventListener("mouseup", function(e) {
            findxy('up', e, this)

        }, false);
        canvas.addEventListener("mouseout", function(e) {
            findxy('out', e, this)

        }, false);
    }
    function draw(ctx) {
        ctx.beginPath();
        ctx.moveTo(prevX, prevY);
        ctx.lineTo(currX, currY);
        ctx.strokeStyle = x;
        ctx.lineWidth = y;
        ctx.stroke();
        ctx.closePath();
    }

    function findxy(res, e,c) {
        let ctx = c.getContext('2d');
        if (res == 'down') {
            prevX = currX;
            prevY = currY;
            currX = e.clientX - c.getBoundingClientRect().left;
            currY = e.clientY - c.getBoundingClientRect().top;

            flag = true;
            dot_flag = true;
            if (dot_flag) {
                ctx.beginPath();
                ctx.fillStyle = x;
                ctx.fillRect(currX, currY, 2, 2);
                ctx.closePath();
                dot_flag = false;
            }
        }
        if (res == 'up' || res == "out") {
            flag = false;
        }
        if (res == 'move') {
            if (flag) {
                prevX = currX;
                prevY = currY;
                currX = e.clientX - c.getBoundingClientRect().left;
                currY = e.clientY - c.getBoundingClientRect().top;
                draw(ctx);
            }
        }
    }

    

    $(document).ready(function() {
        $(".image-canvas").each(function(canvas) {
       
            init($(this).data("fieldid"));
        });
       
    });

</script>

Upvotes: 0

Views: 564

Answers (1)

Justin
Justin

Reputation: 2958

The issue is CSS. When using 100% width and heights you will have issues. You can set the image width to the clientWidth and use the image ratio to maintain aspect. Use an event listener for resize to have the canvas change size is a browser is resized. Using an if statment we can have a max width of 800 and anything less is the clientWidth.

You mouse position should now be accurate without CSS.

var flag = false,
  prevX = 0,
  currX = 0,
  prevY = 0,
  currY = 0,
  dot_flag = false,
  ratio;

var x = "red",
  y = 3;

function init(fieldId) {
  //fieldId are multiple Ids, but I get here one at a time
  let canvas = document.getElementById("can-" + fieldId);
  let ctx = canvas.getContext("2d");

  ratio = 400 / 800;
  canvas.width =
    document.body.clientWidth < 800 ? document.body.clientWidth : 800;
  canvas.height = canvas.width * ratio;

  let base_image = new Image();
  base_image.crossOrigin = "anonymous";
  base_image.src = document.getElementById("image_" + fieldId).src;
  base_image.onload = function () {
    ctx.drawImage(base_image, 0, 0, canvas.width, canvas.height);
  };
  canvas.addEventListener(
    "mousemove",
    function (e) {
      findxy("move", e, this);
    },
    false
  );
  canvas.addEventListener(
    "mousedown",
    function (e) {
      findxy("down", e, this);
    },
    false
  );
  canvas.addEventListener(
    "mouseup",
    function (e) {
      findxy("up", e, this);
    },
    false
  );
  canvas.addEventListener(
    "mouseout",
    function (e) {
      findxy("out", e, this);
    },
    false
  );
  
  window.addEventListener("resize", () => {
    resizeCanvas(canvas)
    ctx.drawImage(base_image, 0, 0, canvas.width, canvas.height);
  })
}
function draw(ctx) {
  ctx.beginPath();
  ctx.moveTo(prevX, prevY);
  ctx.lineTo(currX, currY);
  ctx.strokeStyle = x;
  ctx.lineWidth = y;
  ctx.stroke();
  ctx.closePath();
}

function findxy(res, e, c) {
  let ctx = c.getContext("2d");
  if (res == "down") {
    prevX = currX;
    prevY = currY;
    currX = e.clientX - c.getBoundingClientRect().left;
    currY = e.clientY - c.getBoundingClientRect().top;

    flag = true;
    dot_flag = true;
    if (dot_flag) {
      ctx.beginPath();
      ctx.fillStyle = x;
      ctx.fillRect(currX, currY, 2, 2);
      ctx.closePath();
      dot_flag = false;
    }
  }
  if (res == "up" || res == "out") {
    flag = false;
  }
  if (res == "move") {
    if (flag) {
      prevX = currX;
      prevY = currY;
      currX = e.clientX - c.getBoundingClientRect().left;
      currY = e.clientY - c.getBoundingClientRect().top;
      draw(ctx);
    }
  }
}

$(document).ready(function () {
  $(".image-canvas").each(function (canvas) {
    //console.log($(this).data("fieldid"))
    init($(this).data("fieldid"));
  });
});

function resizeCanvas(canvas) {
    ratio = 400 / 800;
  canvas.width =
    document.body.clientWidth < 800 ? document.body.clientWidth : 800;
  canvas.height = canvas.width * ratio;
}
img {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<canvas data-fieldid='1'  
id="can-1"
class="image-canvas"
style="position:absolute;top:10px;border:1px dotted;">
</canvas>
<canvas data-fieldid='2'  
id="can-2"
class="image-canvas"
style="position:absolute;top:450px;border:1px dotted;">
</canvas>
<img src="https://images.unsplash.com/photo-1494548162494-384bba4ab999?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8c3VucmlzZXxlbnwwfHwwfHw%3D&ixlib=rb-1.2.1&w=1000&q=80" alt='view' id="image_1" class="images" />
<img src="https://media.istockphoto.com/photos/colored-powder-explosion-abstract-closeup-dust-on-backdrop-colorful-picture-id1072093690?k=6&m=1072093690&s=612x612&w=0&h=Eyk67XBt4sr3Bk1MubM6dHpvEVNICX4L7FumWhcTwuY=" alt='view' id="image_2" class="images" />

Upvotes: 2

Related Questions