Boky
Boky

Reputation: 12054

How to apply position absolute to canvas

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?

Upvotes: 1

Views: 4799

Answers (3)

zoha atarodi
zoha atarodi

Reputation: 11

I had this Issue and this javascript worked:

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

Upvotes: 0

AuxTaco
AuxTaco

Reputation: 5171

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>

Upvotes: 2

Tomasz Bubała
Tomasz Bubała

Reputation: 2153

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.

Upvotes: 0

Related Questions