1
votes

I have the photo and the canvas in the div. The photo takes the whole div and I want to position absolute the canvas to be able to hide some parts of the photo with it.

But I have a problem, the canvas doesn't take the whole width and height (the style that I use is position: absolute;left:0;right:0;top:0;bottom:0)

My code is as follows:

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var rect = {};
var drag = false;
var buttons = false;
var angle = 10;
var rotate_angle = 0;

function init() {
    // imageObj = new Image();
    // imageObj.onload = function () { ctx.drawImage(imageObj, 0, 0); };
    // imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
    canvas.addEventListener('mousedown', mouseDown, false);
    canvas.addEventListener('mouseup', mouseUp, false);
    canvas.addEventListener('mousemove', mouseMove, false);

}

function mouseDown(e) {
    rect.startX = e.pageX - this.offsetLeft;
    rect.startY = e.pageY - this.offsetTop;
    drag = true;
    buttons = false;
    document.getElementById('test').innerHTML = '';
}

function mouseUp() { drag = false; buttons = true; }

function onRemoveSelectionClick(e) {
    ctx.clearRect(0, 0, 500, 500);
    drag = false;
    buttons = false;
    document.getElementById('test').innerHTML = '';
}


function onRotateLeft(){
    rotate_angle = rotate_angle - angle;

    canvas.style.transform = 'rotate(' + rotate_angle + 'deg)';
}

function onRotateRight(){
    rotate_angle = rotate_angle + angle;

    canvas.style.transform = 'rotate(' + rotate_angle + 'deg)';
}

function mouseMove(e) {
    if (drag) {
        ctx.clearRect(0, 0, 500, 500);
        // ctx.drawImage(imageObj, 0, 0);
        rect.w = (e.pageX - this.offsetLeft) - rect.startX;
        rect.h = (e.pageY - this.offsetTop) - rect.startY;
        ctx.strokeStyle = 'black';
        ctx.shadowColor = 'black';
        // ctx.shadowBlur = 5;

        ctx.fillRect(rect.startX, rect.startY, rect.w, rect.h);
        ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);


        // ctx.filter = 'blur(5px)';
        // ctx.filter = 'drop-shadow(16px 16px 20px blue) '
    }else{
        if(buttons){
            if(document.getElementById('test').innerHTML === ''){
                document.getElementById('test').innerHTML = '<button onclick="onRotateLeft()">Rotate Left</button>' +
                                                            '<button onclick="onRotateRight()">Rotate right</button><br />' +
                                                            '<button onclick="onRemoveSelectionClick()">Remove Selection</button>';
            }
        }
    }
}
//
init();
<div style="position: relative; overflow: hidden;display:inline-block;">
    <img src="http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg" style="position: relative;"/>
    <canvas id="canvas" style="position: absolute;left: 0; right: 0; top: 0; bottom: 0;background-color: yellow; display:inline-block;"></canvas>
</div>


<div id="test"></div>

Here is also the fiddle.

If I add width: 100%;height: 100%; to the canvas, than it takes the whole width and height but the rectangle isn't drawn as it should be:

You can see it here:

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var rect = {};
var drag = false;
var buttons = false;
var angle = 10;
var rotate_angle = 0;

function init() {
    // imageObj = new Image();
    // imageObj.onload = function () { ctx.drawImage(imageObj, 0, 0); };
    // imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
    canvas.addEventListener('mousedown', mouseDown, false);
    canvas.addEventListener('mouseup', mouseUp, false);
    canvas.addEventListener('mousemove', mouseMove, false);

}

function mouseDown(e) {
    rect.startX = e.pageX - this.offsetLeft;
    rect.startY = e.pageY - this.offsetTop;
    drag = true;
    buttons = false;
    document.getElementById('test').innerHTML = '';
}

function mouseUp() { drag = false; buttons = true; }

function onRemoveSelectionClick(e) {
    ctx.clearRect(0, 0, 500, 500);
    drag = false;
    buttons = false;
    document.getElementById('test').innerHTML = '';
}


function onRotateLeft(){
    rotate_angle = rotate_angle - angle;

    canvas.style.transform = 'rotate(' + rotate_angle + 'deg)';
}

function onRotateRight(){
    rotate_angle = rotate_angle + angle;

    canvas.style.transform = 'rotate(' + rotate_angle + 'deg)';
}

function mouseMove(e) {
    if (drag) {
        ctx.clearRect(0, 0, 500, 500);
        // ctx.drawImage(imageObj, 0, 0);
        rect.w = (e.pageX - this.offsetLeft) - rect.startX;
        rect.h = (e.pageY - this.offsetTop) - rect.startY;
        ctx.strokeStyle = 'black';
        ctx.shadowColor = 'black';
        // ctx.shadowBlur = 5;

        ctx.fillRect(rect.startX, rect.startY, rect.w, rect.h);
        ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);


        // ctx.filter = 'blur(5px)';
        // ctx.filter = 'drop-shadow(16px 16px 20px blue) '
    }else{
        if(buttons){
            if(document.getElementById('test').innerHTML === ''){
                document.getElementById('test').innerHTML = '<button onclick="onRotateLeft()">Rotate Left</button>' +
                                                            '<button onclick="onRotateRight()">Rotate right</button><br />' +
                                                            '<button onclick="onRemoveSelectionClick()">Remove Selection</button>';
            }
        }
    }
}
//
init();
<div style="position: relative; overflow: hidden;display:inline-block;">
    <img src="http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg" style="position: relative;"/>
    <canvas id="canvas" style="position: absolute;left: 0; right: 0; top: 0; bottom: 0;background-color: yellow; display:inline-block;width:100%;height: 100%;"></canvas>
</div>


<div id="test"></div>

Here is the fiddle for the second case.

Any idea how to solve it?

3
“to be able to hide some parts of the photo with it” - which parts, how is that determined? I am not sure what the actual end result is that you are trying to achieve here.CBroe
That is not the problem here, that works. The only problem is that the canvas doesn't take the whole height and width.Boky
You are contradicting yourself - if that actually was “the only problem”, then specifying width and height 100% would solve it, but as you said yourself, it doesn’t. The actual problem here is that the pixel dimension of the canvas is specified by the width and height attributes - and if you apply width and height via CSS on your canvas, then you are effectively stretching it, but the pixel coordinate system inside the canvas stays the same.CBroe
The other guys understood it.Boky

3 Answers

2
votes

The <canvas> element has a height and width entirely independent of the CSS used to display it. You haven't set those explicitly, so the canvas defaults to 300px by 150px. Using height: 100%; width: 100%; in the CSS just stretches the 300x150 canvas over a larger area. Everything you draw in the canvas will still use the 300x150 coordinate space.

If the canvas is supposed to be the same size as the image, but you don't know how big the image is in advance, you can change the canvas's size after the image loads:

var canvas = document.getElementById('canvas');

const img = document.querySelector('img');
img.addEventListener('load', () => {
  canvas.width = img.width;
  canvas.height = img.height;
});

// the rest is your original code, except using MouseEvent.offsetX and
// .offsetY to get the mouse coordinates, and using the canvas's
// height and width instead of 500 for ctx.clearRect
var ctx = canvas.getContext('2d');
var rect = {};
var drag = false;
var buttons = false;
var angle = 10;
var rotate_angle = 0;

function init() {
  // imageObj = new Image();
  // imageObj.onload = function () { ctx.drawImage(imageObj, 0, 0); };
  // imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
  canvas.addEventListener('mousedown', mouseDown, false);
  canvas.addEventListener('mouseup', mouseUp, false);
  canvas.addEventListener('mousemove', mouseMove, false);

}

function mouseDown(e) {
  rect.startX = e.offsetX;
  rect.startY = e.offsetY;
  drag = true;
  buttons = false;
  document.getElementById('test').innerHTML = '';
}

function mouseUp() {
  drag = false;
  buttons = true;
}

function onRemoveSelectionClick(e) {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  drag = false;
  buttons = false;
  document.getElementById('test').innerHTML = '';
}


function onRotateLeft() {
  rotate_angle = rotate_angle - angle;

  canvas.style.transform = 'rotate(' + rotate_angle + 'deg)';
}

function onRotateRight() {
  rotate_angle = rotate_angle + angle;

  canvas.style.transform = 'rotate(' + rotate_angle + 'deg)';
}

function mouseMove(e) {
  if (drag) {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    // ctx.drawImage(imageObj, 0, 0);
    rect.w = e.offsetX - rect.startX;
    rect.h = e.offsetY - rect.startY;
    ctx.strokeStyle = 'black';
    ctx.shadowColor = 'black';
    // ctx.shadowBlur = 5;

    ctx.fillRect(rect.startX, rect.startY, rect.w, rect.h);
    ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);


    // ctx.filter = 'blur(5px)';
    // ctx.filter = 'drop-shadow(16px 16px 20px blue) '
  } else {
    if (buttons) {
      if (document.getElementById('test').innerHTML === '') {
        document.getElementById('test').innerHTML = '<button onclick="onRotateLeft()">Rotate Left</button>' +
          '<button onclick="onRotateRight()">Rotate right</button><br />' +
          '<button onclick="onRemoveSelectionClick()">Remove Selection</button>';
      }
    }
  }
}
//
init();
#container {
  position: relative;
  overflow: hidden;
  display: inline-block;
}

canvas {
  position: absolute;
  left: 0;
  top: 0;
  background-color: yellow;
}
<div id="container">
  <img src="http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg">
  <canvas id="canvas"></canvas>
</div>


<div id="test"></div>
0
votes

I'm aware it's not an ideal solution, but if you need something quick and the dimensions of image are known, it might be ok for now. Your image is 438x300, so instead of specifying style of height: 100%; width: 100% you can provide height and width attribute for canvas.

    <canvas width=438 height=300></canvas>

I will update the answer if i find a solution non reliant on knowing image dimensions beforehand.

0
votes

I had this Issue and this javascript worked:

var element = document.getElementsByClassName('canvasjs-chart-canvas')[0];
element.style.removeProperty("position");