3

Good afternoon,

I am new to Canvas in HTML 5 and in using it with Javascript. But I can see how powerful this really is and I needed help. I have done a search and could not find a clear answer to this. Perhaps someone here can help.

I have created a context on the Canvas with a background image in place. Now, I want crop or copy a part of that image which is contained in Polygon Data and place it else where on the screen. I know how to create the background image. I know how to create a polygon over that image and I know how to copy image data to another part of the screen.

So how would I copy all the image data/pixels within that polygon? Is there a simple way to this? Thanks in advance for your help. It is much appreciated.

EDIT: This is an example of what I am trying to do: http://jsfiddle.net/MFELx/

//I have no code, but it wouldn't let me post link. Hope this is allowed.

Only I am trying to do it without an external library or without JQUERY. I hope that makes a little more sense. Thanks for your help again!

EDIT AGAIN: SOLUTION:

OK So Mark E's Solution worked. I edited it this way for those who are interested without JQUERY:

HTML: Copy the polygon
Original background

CSS:

body{ background-color: ivory; }
#canvas{border:1px solid red;}

JS:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var polygonData=[];
polygonData.push({x:125,y:75});
polygonData.push({x:100,y:118});
polygonData.push({x:50,y:118});
polygonData.push({x:25,y:75});
polygonData.push({x:49,y:31});
polygonData.push({x:100,y:31});
polygonData.push({x:125,y:75});


var img=new Image();
img.onload=start;
img.src='https://dl.dropboxusercontent.com/u/139992952/multple/stars1.png';
function start(){

  // draw the original background
  ctx.drawImage(img,0,0);

  // copy the existing polygon to its new position


}


function copyPolygon(newStartingX,newStartingY){

  // calculate the copy's offset versus the original
  var dx=newStartingX-polygonData[0].x;
  var dy=newStartingY-polygonData[0].y;

  // define the path of the new polygon
  ctx.beginPath();
  ctx.moveTo(polygonData[0].x+dx,polygonData[0].y+dy);
  for(var i=1;i<polygonData.length;i++){
    ctx.lineTo(polygonData[i].x+dx,polygonData[i].y+dy);
  }
  ctx.closePath();

  // clip to the path of the new polygon
  ctx.save();
  ctx.clip();

  // use the clipping version of drawImage to
  // redraw the existing canvas over the new polygon position
  // Note: with clipping, new pixels will only be drawn in the new polygon
  ctx.drawImage(canvas, 0,0,cw,ch, dx,dy,cw,ch);

  // clean up -- un-clip by resetting the context state
  ctx.restore();

}
function myFunction() {
    copyPolygon(250,75);
}
user1924218
  • 99
  • 1
  • 11

1 Answers1

4

Since you have the polygon data points that you want to copy, there's a simpler method to copy your polygon than using a second off-screen canvas.

Instead, you can:

  • Use the polygon points to define the path of the new polygon copy.

  • Use context.clip() to restrict all new drawings to be inside that polygon copy.

  • Use the canvas as its own image source and draw it with an offset equal to how far the new polygon is from the previous polygon.

enter image description here

enter image description here

Here's example annotated code and a Demo:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var polygonData=[];
polygonData.push({x:125,y:75});
polygonData.push({x:100,y:118});
polygonData.push({x:50,y:118});
polygonData.push({x:25,y:75});
polygonData.push({x:49,y:31});
polygonData.push({x:100,y:31});
polygonData.push({x:125,y:75});


var img=new Image();
img.onload=start;
img.src='https://dl.dropboxusercontent.com/u/139992952/multple/stars1.png';
function start(){

  // draw the original background
  ctx.drawImage(img,0,0);

  // copy the existing polygon to its new position
  $('#copy').click(function(){
    copyPolygon(250,75);
    $('#status').text('With the polygon copied');
  });

}


function copyPolygon(newStartingX,newStartingY){

  // calculate the copy's offset versus the original
  var dx=newStartingX-polygonData[0].x;
  var dy=newStartingY-polygonData[0].y;

  // define the path of the new polygon
  ctx.beginPath();
  ctx.moveTo(polygonData[0].x+dx,polygonData[0].y+dy);
  for(var i=1;i<polygonData.length;i++){
    ctx.lineTo(polygonData[i].x+dx,polygonData[i].y+dy);
  }
  ctx.closePath();

  // clip to the path of the new polygon
  ctx.save();
  ctx.clip();

  // use the clipping version of drawImage to
  // redraw the existing canvas over the new polygon position
  // Note: with clipping, new pixels will only be drawn in the new polygon
  ctx.drawImage(canvas, 0,0,cw,ch, dx,dy,cw,ch);

  // clean up -- un-clip by resetting the context state
  ctx.restore();

}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button id=copy>Copy the polygon</button>
<br>
<h4 id='status'>Original background</h4>
<canvas id="canvas" width=400 height=250></canvas>
markE
  • 102,905
  • 11
  • 164
  • 176
  • Hi Mark.Thanks for your help. But it seems that this is just copying the polygon again rather than what is behind the polygon. I am trying to make it so that you basically draw a polygon over an image and then you have JS copy everything from the image that is inside the polygon. This basically just makes a polygon and then copies it to another part of the image. What I am looking for is sort of like GIMPS magic wand. You draw on an image and you could then copy and paste it somewhere else in the image or into another app. -Its sorta like that. I hope that makes sense. Thanks again! – user1924218 Apr 11 '15 at 23:48
  • This technique will grab and then copy any set of points on the image. I just used a gold polygon for illustration. You could just as easily use your captured set of mouse-points and copy the background inside the polygon and paste those copied pixels anywhere on the background. Here's a different example without the gold polygon: https://jsfiddle.net/m1erickson/fcuugwd4/ – markE Apr 11 '15 at 23:59
  • 1
    Ah yes! I see it now. I didn't realize the Polygon was drawn onto the background already. I edited my request above. What I wanted though was not to be able to need JQUERY, simply because I will be using this as an Apache Cordova app in the long run and the user may not be connected to the Internet to reference the JQUERY Library. So I am looking for a way to do this without that. Which actually, now that I look at the code, I can change that easily here. I will try and let you know. Thanks! – user1924218 Apr 12 '15 at 00:01
  • You're welcome. As you probably see, the jQuery is just there to handle the Demo's button events--no need for jQuery to accomplish the effect :-) – markE Apr 12 '15 at 00:03
  • 1
    Yep! You are right. I posted your solution without JQUERY. Thanks again! – user1924218 Apr 12 '15 at 00:12