【问题标题】:How to apply position absolute to canvas如何将绝对位置应用于画布
【发布时间】:2018-02-02 08:57:26
【问题描述】:

我在 div 中有照片和画布。照片占据了整个 div,我想绝对定位画布,以便能够用它隐藏照片的某些部分。

但是我有一个问题,画布没有占用整个宽度和高度(我使用的样式是position: absolute;left:0;right:0;top:0;bottom:0

我的代码如下:

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.

如果我将width: 100%;height: 100%; 添加到画布,它会占用整个宽度和高度,但矩形不会按应有的方式绘制:

你可以在这里看到它:

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.

知道怎么解决吗?

【问题讨论】:

  • “能够用它隐藏照片的某些部分” - 哪些部分,这是如何确定的?我不确定您在这里尝试实现的实际最终结果是什么。
  • 这不是这里的问题,它有效。唯一的问题是画布没有占据整个高度和宽度。
  • 你在自相矛盾 - 如果那 实际上 是“唯一的问题”,那么指定宽度和高度 100% 会解决它,但正如你自己所说,它没有吨。这里的实际问题是画布的像素尺寸由宽度和高度 attributes 指定 - 如果您通过 CSS 在画布上应用宽度和高度,那么您实际上是在拉伸它,但是画布内的像素坐标系保持不变。
  • 其他人都明白了。

标签: javascript jquery html css canvas


【解决方案1】:

&lt;canvas&gt; 元素的高度和宽度完全独立于用于显示它的 CSS。您没有明确设置这些,因此画布默认为 300 像素 x 150 像素。在 CSS 中使用 height: 100%; width: 100%; 只会将 300x150 的画布拉伸到更大的区域。您在画布中绘制的所有内容仍将使用 300x150 坐标空间。

如果canvas应该和图片一样大小,但是你事先不知道图片有多大,可以在图片加载后改变canvas的大小:

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>

【讨论】:

  • 完美。我刚刚添加了var img = document.getElementById('photo'); var original_source = img.src; img.src = original_source;。因为如果图像在缓存中load 不起作用。
【解决方案2】:

我知道这不是一个理想的解决方案,但是如果您需要一些快速的东西并且图像的尺寸是已知的,那么现在可能还可以。您的图像是 438x300,因此您可以为 canvas 提供 heightwidth 属性,而不是指定 height: 100%; width: 100% 的样式。

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

如果我找到不依赖于事先知道图像尺寸的解决方案,我会更新答案。

【讨论】:

  • 谢谢。我知道。但我图片的尺寸并不总是一样的。
  • 还可以使用 javascript 加载图像 - 在加载图像时读取其宽度和高度并相应地调整画布大小。
  • 如果我将属性 widthheight 添加到画布 &lt;canvas width=438 height=300&gt;&lt;/canvas&gt; 它工作正常,但如果我使用 css 它不会 &lt;canvas id="canvas" style="position: absolute;left: 0; right: 0; top: 0; bottom: 0;background-color: yellow;width:438px; height: 300px"&gt;&lt;/canvas&gt;
  • 你忘了px,但无论如何height和width属性与css的高度和宽度无关。
  • 我只知道用javascript加载图片怎么解决,这是你要找的吗?
【解决方案3】:

我遇到了这个问题,这个 javascript 工作正常:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-24
    • 1970-01-01
    • 2016-04-05
    • 2012-01-11
    • 2021-03-16
    • 1970-01-01
    相关资源
    最近更新 更多