Html 在保留图像的同时在 HTML5 Canvas 中绘制图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19966912/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 15:18:31  来源:igfitidea点击:

drawing over an Image in HTML5 Canvas while preserving the image

javascripthtmlcanvasdrawing

提问by Asaf Bartov

In HTML5 Canvas, what's the simplest way to draw and movea line over an Image (already on the canvas), preserving the image underneath? (e.g. have a vertical line track the mouse X position)

在 HTML5 Canvas 中,在图像(已经在画布上)上绘制和移动一条线并保留下面的图像的最简单方法是什么?(例如有一条垂直线跟踪鼠标 X 位置)

My current canvas:

我目前的画布:

$(document).ready(function() {
  canvas = document.getElementById("myCanvas");
  context = canvas.getContext("2d");
  imageObj = new Image();

    imageObj.onload = function() { 
    context.drawImage(imageObj, 0,0);  
  }
  imageObj.src = "http://example.com/some_image.png";
  $('#myCanvas').click(doSomething);
});

P.S. I'm racing you against my Facebook network. May the best Lazyweb win (my gratitude) :)

PS 我正在与我的 Facebook 网络比赛。愿最好的 Lazyweb 获胜(我的感激之情):)

回答by

You will have to do most of the ground-work with canvas which in this case you will have to implement the functionality to move the line and then redraw everything.

您将不得不使用画布完成大部分基础工作,在这种情况下,您将必须实现移动线条然后重绘所有内容的功能。

The steps can be:

步骤可以是:

  • Keep the line as an object which can self-render (method on the object)
  • Listen to mousemove (in this case) in order to move the line
  • For each move, redraw background (image) then render the line at its new position
  • 保持线作为可以自我渲染的对象(对象上的方法)
  • 听 mousemove(在这种情况下)以移动线
  • 对于每次移动,重新绘制背景(图像)然后在新位置渲染线

You can redraw the background as a whole or you can optimize it to just draw over the last line.

您可以重新绘制整个背景,也可以优化它以仅绘制最后一行。

Here is some example code of this and a live demo here:

这是一些示例代码和现场演示

var canvas = document.getElementById('demo'), /// canvas element
    ctx = canvas.getContext('2d'),            /// context
    line = new Line(ctx),                     /// our custom line object
    img = new Image;                          /// the image for bg

ctx.strokeStyle = '#fff';                     /// white line for demo

/// start image loading, when done draw and setup 
img.onload = start;
img.src = 'http://i.imgur.com/O712qpO.jpg';

function start() {
    /// initial draw of image
    ctx.drawImage(img, 0, 0, demo.width, demo.height);

    /// listen to mouse move (or use jQuery on('mousemove') instead)
    canvas.onmousemove = updateLine;
}

Now all we need to do is to have a mechnism to update the background and the line for each move:

现在我们需要做的就是有一个机制来更新每个移动的背景和线条:

/// updates the line on each mouse move    
function updateLine(e) {

    /// correct mouse position so it's relative to canvas
    var r = canvas.getBoundingClientRect(),
        x = e.clientX - r.left,
        y = e.clientY - r.top;

    /// draw background image to clear previous line
    ctx.drawImage(img, 0, 0, canvas.width, canvas.height);

    /// update line object and draw it
    line.x1 = x;
    line.y1 = 0;
    line.x2 = x;
    line.y2 = canvas.height;
    line.draw();
}

The custom line object is in this demo very simple:

自定义线对象在这个演示中非常简单:

/// This lets us define a custom line object which self-draws
function Line(ctx) {

    var me = this;

    this.x1 = 0;
    this.x2 = 0;
    this.y1 = 0;
    this.y2 = 0;

    /// call this method to update line        
    this.draw = function() {
        ctx.beginPath();
        ctx.moveTo(me.x1, me.y1);
        ctx.lineTo(me.x2, me.y2);
        ctx.stroke();
    }
}

If you are not gonna do anything specific with the image itself you can also set it as a background-image using CSS. You will still need to clear the canvas before redrawing the line though.

如果你不打算对图像本身做任何特定的事情,你也可以使用 CSS 将其设置为背景图像。不过,在重新绘制线条之前,您仍然需要清除画布。

回答by markE

You can get your "crosshairs" by listening to mousemove events and then:

您可以通过侦听 mousemove 事件来获得“十字准线”,然后:

  • clear the canvas
  • draw the image
  • draw your line at the mouse position
  • 清除画布
  • 绘制图像
  • 在鼠标位置画线

Here is code and a Fiddle: http://jsfiddle.net/m1erickson/jEc7N/

这是代码和小提琴:http: //jsfiddle.net/m1erickson/jEc7N/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; padding:20px; }
    #canvas{border:1px solid red;}
</style>

<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    ctx.lineWidth=2;

    var canvasOffset=$("#canvas").offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;

    var img=new Image();
    img.onload=function(){
        canvas.width=img.width;
        canvas.height=img.height;
        ctx.drawImage(img,0,0);

    }
    img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/KoolAidMan.png";

    function handleMouseMove(e){
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);

      ctx.clearRect(0,0,canvas.width,canvas.height);
      ctx.drawImage(img,0,0);
      ctx.beginPath();
      ctx.moveTo(mouseX,0);
      ctx.lineTo(mouseX,canvas.height);
      ctx.moveTo(0,mouseY);
      ctx.lineTo(canvas.width,mouseY);
      ctx.stroke();


    }

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


}); // end $(function(){});
</script>

</head>

<body>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

回答by Shinigamae

May this is not an actual answer, just in case you need it (in the future). Working with canvas would be better (and easier) with some library. I have tried EaselJS of CreateJS and find myself loving it. You can have a look at it EaselJS(I have done an example allow drawing and dragging image using EaselJS long time before)

可能这不是一个实际的答案,以防万一你需要它(将来)。使用一些库使用画布会更好(也更容易)。我尝试过 CreateJS 的 EaselJS 并发现自己喜欢它。你可以看看它EaselJS(我很久以前做过一个例子,允许使用 EaselJS 绘制和拖动图像)

回答by ViliusL

or just use 2 layers:

或者只使用2 层

  1. background layer has image and do not change,
  2. top layer has line, what you can clear and redraw it lots of time without affecting background layer.
  1. 背景层有图像并且不会改变,
  2. 顶层有线条,您可以在不影响背景层的情况下多次清除和重绘它。