swapping div with canvas elements using javascript - javascript

I have 2 div. Every div has a canvas element. At the beginning of my program I put an image on the canvas. The images are different. Then I try to swap the divs using
var contentofmyfirstdiv = $('#myfirstdiv').html();
var contentofmyseconddiv = $('#myseconddiv').html();
$('#myseconddiv').html(contentofmyfirstdiv);
$('#myfirstdiv').html(contentofmyseconddiv)
;
All works except that every canvas is empty. It seems the "contentof..." didn't get the image from the canvas... Anyone knows how to swap the content of the canvas? I am using Firefox.

You are serializing to html and reparsing it, this is lossy operation. Instead you should operate
on the live DOM tree directly:
var contentofmyfirstdiv = $('#myfirstdiv').children().detach();
var contentofmyseconddiv = $('#myseconddiv').children().detach();
$('#myseconddiv').append(contentofmyfirstdiv);
$('#myfirstdiv').append(contentofmyseconddiv)
Here's a demo that doesn't do justice but nevertheless http://jsfiddle.net/9JdqQ/
What's retained compared to serialization are unserializable attributes, event listeners, element data (canvas image etc)..

If you are only using images to draw on the canvas there is really no need for the canvas - you could just use the images directly and swap those.
However, if you need to use canvas for other reasons you can extract the data directly from one, draw the other canvas to this, and then put the data from the first to the second.
This method shows a way that doesn't need DOM manipulation.
One option using a new canvas as a swap:
var temp = document.createElement('img');
temp.width = canvas1.width;
temp.height = canvas1.height;
//swap
var tempctx = temp.getContext('2d');
tempctx.drawImage(canvas1, 0, 0);
ctx1.drawImage(canvas2, 0, 0);
ctx2.drawImage(temp, 0, 0);
The other method using an image element as a swap:
var temp = canvas1.toDataURL();
ctx1.drawImage(canvas2, 0, 0);
var img = document.createElement('img');
img.onload = function() {ctx2.drawImage(this, 0, 0);}
img.src = temp;
The latter not optimal in speed as you need to compress and encode the data-uri.
Note that this example assume the images being of the same size. If the images are of different sizes you will need to handle this as well by setting canvas1 and 2 to the correct sizes after the image is copied to swap and before you redraw.
swap = canvas1
resize canvas1 = canvas2
draw canvas2 to canvas1
resize canvas2 = swap
draw swap to canvas2

Related

Is it possible to draw a canvas thats bigger than the current screen?

I'm drawing a image to a canvas, and when doing so the image gets downscaled to the canvas(which makes it lose quality) even though the image is the same size as the canvas, thats because the img does a good job scaling down the actual img that in reality has a bigger naturalheight and naturalwidth. I know there is possible ways to make this quality better, however i have no need of actually showing this canvas to the user/no need of downscaling. Therefore am i wondering if there is any way to drawImage that is bigger than the screen and hold it somewhere? Heard someone mention a box object or a camera object somewhere but couldn't really get use of that information only.
Question, is it possible to draw a canvas bigger than the screen? in that case how?
This is the code im working with atm
var image = document.getElementById('insertedImg');
var height = $("#insertedImg").height();
var width = $("#insertedImg").width();
var c=document.getElementById("canvass");
var ctx=c.getContext("2d");
c.height=height;
c.width=width;
ctx.drawImage(image,0,0,width,height);
Use an offscreen canvas, you just need to create a new canvas and set its height and width accordingly. Then you can append it to an element or export the image as a base64 string or whatever you need.
//canvas is not visible unless appended to a DOM element
var canvas = document.createElement('canvas');
canvas.width = $("#insertedImg").height();
canvas.height = $("#insertedImg").width();
var ctx = canvas.getContext('2d');
//do the drawing, etc.
ctx.drawImage(...);
//export the image
var img = canvas.toDataURL("image/png");

canvas is cleared on mousedown, sketch.js & jquery 2.0.0

11I'm using sketch.js from here: http://intridea.github.io/sketch.js/ and jquery 2.0.0
On my page, I have a list of images presented like so:
<img src="http://url.to/image"><br><span class="background">click for background</span>
and a canvas, set up like so:
<canvas id="simple_sketch" style="border: 2px solid black;"></canvas>
relevant JavaScript:
var winwidth = 800;
var winheight = 600;
$('#simple_sketch').attr('width', winwidth).attr('height', winheight);
$('#simple_sketch').sketch();
$('.background').on('click', function(event) {
event.preventDefault();
var imgurl = $(this).parent().attr('href');
console.log('imgurl: ' + imgurl);
var n = imgurl.split('/');
var size = n.length;
var file = '../webkort/' + n[size - 1];
var sigCanvas = document.getElementById('simple_sketch');
var context = sigCanvas.getContext('2d');
var imageObj = new Image();
imageObj.src = imgurl;
imageObj.onload = function() {
context.drawImage(this, 0, 0,sigCanvas.width,sigCanvas.height);
};
alert('background changed');
});
Backgrounds are changed just as I want them to, but whenever I click on the canvas, the backgound image is cleared. As per a suggestion on this thread: html5 canvas background image disappear on mousemove I commented out this.el.width = this.canvas.width(); on line 116 of sketch.js, but to no avail.
Any help appreciated!
EDIT: jsfiddle: http://jsfiddle.net/RXFX4/1/
EDIT: Couldn't figure out how to do this with sketch.js, so instead went with jqScribble (link posted in comments) which has the ability to do this as a built-in function instead.
Find this line on the library - sketch.js and delete/comment it out.
this.el.width = this.canvas.width();
Good luck
Assign the url on the image source after the onload event. If the image is already loaded, the event is probably firing before you are hooking it. Which means that your drawImage is never being called.
var imageObj = new Image();
imageObj.onload = function() {
context.drawImage(this, 0, 0,sigCanvas.width,sigCanvas.height);
};
imageObj.src = imgurl;
EDIT: I'm going to take a shot in the dark here, since I'm not familiar with sketchjs
I'm thinking that your problem is that you are completely re-render the canvas when you click your 'change background' link. Notice that if you draw, then click the change background, you lose your drawing.
However, notice that once you click again, the background disappears, and you get your original drawing back again. This tells me that sketchjs is keeping track of what has been drawn on it's own in-memory canvas, and then it drops it onto the target. The problem, then, is that when this in-memory canvas is drawn, it completely replaces the contents of the target canvas with it's own.
I notice in some of the sketchjs examples, if you want a background they actually assign the canvas a background style. In your example, you are drawing the background directly onto the canvas. The prior probably works because sketchjs knows to incorporate the background style when it draws. However, it does not know that when you drew your fresh background image, it should be using that.
Can you just change the background style on the canvas element, instead of drawing directly on the canvas?

html image id and canvas

Hi there I have a simple question I can'[t seem to find the answer to on google. I'm trying to draw an image on a canvas. I originally used the "new" constructor ( ballPic = new Image(); ballPic.src = "ball.png" ) which worked when drawing on my canvas, but I needed to do some scaling and wasn't sure if I could attach a css id to the object. So I instead tried to use the image tag and did the rest in css.
However using a variable that way doenst seem to work with my canvas' drawing:
ballPic = '<img id="soccerBall">';
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.drawImage(BallPic, -25, -25);
Is this because assigning a variable like ballPic = is not the same as being the element itself like when using the constructor? How would I pass it other than attaching it to the document and using getElementbyID?
You can keep using the Image constructor and still scale the image. There's another method overload of the drawImage function:
From MDN:
The second variant of the drawImage() method adds two new parameters and lets us place scaled images on the canvas.
drawImage(image, x, y, width, height)
This adds the width and height parameters, which indicate the size to which to scale the image when drawing it onto the canvas.
I would recommend you check out that page, it has a lot of good information, like
Using data: urls
Handling image loading
Loading still frames from videos
Slicing
Examples gallore
Create an image, handle the onload event, in which you update the canvas size to the scaled size of the image, then drawImage with a scale.
var scale = 2 ;
var ballPic = new Image();
ballPic.onload = function drawImage() {
var c=document.getElementById("myCanvas");
c.width = ballPic.width * scale ;
c.height = ballPic.height * scale ;
var ctx=c.getContext("2d");
ctx.scale(scale, scale) ;
ctx.drawImage(ballPic, 0, 0);
};
ballPic.src =
'http://melinabeachturtlehatchery.files.wordpress.com/2010/07/turtle4.jpg';
the fiddle is here :
http://jsbin.com/etemox/1/edit

Fill image with a repeatable texture

Would it be possible to fill a png with transparency with a pattern (a repeatable texture)?
Here's a quick example of loading an image onto the canvas, just not sure how to fill it with a pattern, if that isn't possible then would there be a way to extract a path from the png?
<script>
var c = document.getElementById("a");
var ctx = c.getContext("2d");
var test= new Image();
test.src = "images/test.png";
test.onload = function() {
ctx.drawImage(test, 0, 0);
};
</script>
<body>
<canvas id="a"></canvas>
</body>
I've also created a jsfiddle with an actual loaded png
This is the effect I'm looking to achieve
Update
working example based on Simon Sarris' answer
http://jsfiddle.net/sergeh/G8egW/6/
First, draw the image to Canvas.
Then do globalCompositeOperation = 'source-in';
Then draw the pattern. It will only exist where the image was.
http://jsfiddle.net/G8egW/2/
If you had stuff already on the canvas before this time, you'll need to do the above operations on an in-memory canvas and then draw that canvas to your normal canvas. Like this:
http://jsfiddle.net/G8egW/5/
(notice the difference in the grid)

canvas - layer small image on larger background image, merge to single canvas pixel data

How do I merge a smaller image on top of a larger background image on one canvas. The smaller image will move around. So I will need to keep reference of the original background pixel data, so that the each frame the canvas can be redrawn, with the overlay in its new position.
BgImage: 1280 x 400, overlayImage: 320 x 400, overlayOffsetX: mouseX
I think it is common to draw whole scene each time you want to change something, so:
context.drawImage(bgImage, 0, 0);
context.drawImage(overlayImage, overlayOffsetX, 0);
UPDATE
You could manually compose image data of two images with making copy of background image data
or
do something easier, probably faster. You could create new canvas element (without attaching to the document) which would store image data in easy to manage form. putImageData is good if you want to place rectangular image into the canvas. But if you want to put image with transparency, additional canvas will help. See if example below is satisfying you.
// preparation of canvas containing data of overlayImage
var OVERLAY_IMAGE_WIDTH = 320;
var OVERLAY_IMAGE_Height = 400;
var overlayImageCanvas = document.createElement('canvas');
overlayImageCanvas.width = OVERLAY_IMAGE_WIDTH;
overlayImageCanvas.height = OVERLAY_IMAGE_HEIGHT;
overlayImageCanvas.getContext('2d').putImageData(overlayImage, 0, 0);
// drawing scene, execute this block every time overlayOffsetX has changed
context.putImageData(bgImage, 0, 0);
context.drawImage(overlayImageCanvas, overlayOffsetX, 0);

Categories

Resources