Drawing an image from a data URL to a canvas - image

How can i open an image in a Canvas ? which is encoded
I am using the
var strDataURI = oCanvas.toDataURL();
The output is the encoded base 64 image. How can i draw this image on a canvas?
I want to use the strDataURI and create the Image ? Is it poosible ?
If its not then what possibly can be the solution for loading the image on a canvas ?

Given a data URL, you can create an image (either on the page or purely in JS) by setting the src of the image to your data URL. For example:
var img = new Image;
img.src = strDataURI;
The drawImage() method of HTML5 Canvas Context lets you copy all or a portion of an image (or canvas, or video) onto a canvas.
You might use it like so:
var myCanvas = document.getElementById('my_canvas_id');
var ctx = myCanvas.getContext('2d');
var img = new Image;
img.onload = function(){
ctx.drawImage(img,0,0); // Or at whatever offset you like
};
img.src = strDataURI;
Edit: I previously suggested in this space that it might not be necessary to use the onload handler when a data URI is involved. Based on experimental tests from this question, it is not safe to do so. The above sequence—create the image, set the onload to use the new image, and then set the src—is necessary for some browsers to surely use the results.

function drawDataURIOnCanvas(strDataURI, canvas) {
"use strict";
var img = new window.Image();
img.addEventListener("load", function () {
canvas.getContext("2d").drawImage(img, 0, 0);
});
img.setAttribute("src", strDataURI);
}

In case you don't like the onload callback approach, you can "promisify" it like so:
let url = "data:image/gif;base64,R0lGODl...";
let img = new Image();
await new Promise(r => img.onload=r, img.src=url);
// now do something with img

Perhaps this fiddle would help ThumbGen - jsFiddle It uses File API and Canvas to dynamically generate thumbnails of images.
(function (doc) {
var oError = null;
var oFileIn = doc.getElementById('fileIn');
var oFileReader = new FileReader();
var oImage = new Image();
oFileIn.addEventListener('change', function () {
var oFile = this.files[0];
var oLogInfo = doc.getElementById('logInfo');
var rFltr = /^(?:image\/bmp|image\/cis\-cod|image\/gif|image\/ief|image\/jpeg|image\/jpeg|image\/jpeg|image\/pipeg|image\/png|image\/svg\+xml|image\/tiff|image\/x\-cmu\-raster|image\/x\-cmx|image\/x\-icon|image\/x\-portable\-anymap|image\/x\-portable\-bitmap|image\/x\-portable\-graymap|image\/x\-portable\-pixmap|image\/x\-rgb|image\/x\-xbitmap|image\/x\-xpixmap|image\/x\-xwindowdump)$/i
try {
if (rFltr.test(oFile.type)) {
oFileReader.readAsDataURL(oFile);
oLogInfo.setAttribute('class', 'message info');
throw 'Preview for ' + oFile.name;
} else {
oLogInfo.setAttribute('class', 'message error');
throw oFile.name + ' is not a valid image';
}
} catch (err) {
if (oError) {
oLogInfo.removeChild(oError);
oError = null;
$('#logInfo').fadeOut();
$('#imgThumb').fadeOut();
}
oError = doc.createTextNode(err);
oLogInfo.appendChild(oError);
$('#logInfo').fadeIn();
}
}, false);
oFileReader.addEventListener('load', function (e) {
oImage.src = e.target.result;
}, false);
oImage.addEventListener('load', function () {
if (oCanvas) {
oCanvas = null;
oContext = null;
$('#imgThumb').fadeOut();
}
var oCanvas = doc.getElementById('imgThumb');
var oContext = oCanvas.getContext('2d');
var nWidth = (this.width > 500) ? this.width / 4 : this.width;
var nHeight = (this.height > 500) ? this.height / 4 : this.height;
oCanvas.setAttribute('width', nWidth);
oCanvas.setAttribute('height', nHeight);
oContext.drawImage(this, 0, 0, nWidth, nHeight);
$('#imgThumb').fadeIn();
}, false);
})(document);

Mixing the answers I do.
function drawDataURIOnCanvas(strDataURI, canvas) {
var img = new window.Image();
img.addEventListener("load", function () {
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
canvas.width = img.width;
canvas.height = img.height;
canvas.getContext("2d").drawImage(img, 0, 0, img.width, img.height);
});
img.setAttribute("src", strDataURI);
}

You might wanna clear the old Image before setting a new Image.
You also need to update the Canvas size for a new Image.
This is how I am doing in my project:
// on image load update Canvas Image
this.image.onload = () => {
// Clear Old Image and Reset Bounds
canvasContext.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.canvas.height = this.image.height;
this.canvas.width = this.image.width;
// Redraw Image
canvasContext.drawImage(
this.image,
0,
0,
this.image.width,
this.image.height
);
};

in javascript , using jquery for canvas id selection :
var Canvas2 = $("#canvas2")[0];
var Context2 = Canvas2.getContext("2d");
var image = new Image();
image.src = "images/eye.jpg";
Context2.drawImage(image, 0, 0);
html5:
<canvas id="canvas2"></canvas>

Related

View pdf instead of download using PDF js

In my page, I'm trying to display a thumbnails of my pdf using PDF JS and it works on local, but when I upload my code in my webserver the pdf file is auto download.
In my local :
Code :
$(function() {
var filePath = "http://example.com/public/uploads/docs/Document_One_1.pdf";
function Num(num) {
var num = num;
return function () {
return num;
}
};
function renderPDF(url, canvasContainer, options) {
var options = options || {
scale: 1.1
},
func,
pdfDoc,
def = $.Deferred(),
promise = $.Deferred().resolve().promise(),
width,
height,
makeRunner = function(func, args) {
return function() {
return func.call(null, args);
};
};
function renderPage(num) {
var def = $.Deferred(),
currPageNum = new Num(num);
pdfDoc.getPage(currPageNum()).then(function(page) {
var viewport = page.getViewport(options.scale);
var canvas = document.createElement("canvas");
canvas.setAttribute("id","pdfCanvas"+num);
canvas.setAttribute("onclick","popCanvas('{{url('/dashboard/showcanvas')}}','"+document.getElementById('pdfPath').innerHTML+"','"+num+"');");
var ctx = canvas.getContext('2d');
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
if(currPageNum() === 1) {
height = viewport.height;
width = viewport.width;
}
canvas.height = height;
canvas.width = width;
canvasContainer.appendChild(canvas);
page.render(renderContext).then(function() {
def.resolve();
});
})
return def.promise();
}
function renderPages(data) {
pdfDoc = data;
var pagesCount = pdfDoc.numPages;
for (var i = 1; i <= pagesCount; i++) {
func = renderPage;
promise = promise.then(makeRunner(func, i));
}
}
PDFJS.disableWorker = true;
PDFJS.getDocument(url).then(renderPages);
};
var body = document.getElementById("bodyofpdf");
renderPDF(filePath, body);
});
When I change the filepath url, for example: "https://www.tutorialspoint.com/bootstrap/bootstrap_tutorial.pdf", it works.
Can somebody help me ??
Sorry for my poor english.
If you are using Laravel you can control the behaviour of the routes, including the one to a .pdf. For local files, browsers have a different behaviour by default than for no local files.
I have used a lot PDF.js and I don't know why do you link the user directly to the file, you could create like a view page where it gets a parameter like the id or the name of the book and then you load it with pdf.js. If you use an url with a file extension you will probably confuse the browser.
yourpage.com/books/view/{id_book}

How to access the image data after dropping an image from the html-part of a webpage onto a canvas?

This is a follow up question to
How to drop texts and images on a canvas? (Firefox 41.0.1)
I simply can't find out how to access the image data of the image I dropped onto the canvas. I tried things like data = event.dataTransfer.getData("image"), but that all doesn't work.
function addDragNDropToCanvas() {
document.getElementById('canvas').addEventListener("dragover", function(event) { event.preventDefault();}, false);
//handle the drop
document.getElementById('canvas').addEventListener("drop", function(event) {
event.preventDefault();
console.log('something is dropped on the object with id: ' + event.target.id);
// var directData=event.dataTransfer.getData("image");
console.log(event);
}, false);
}
There surely is the image-data somewhere incorporated in the drop-event data? Isn't it???
(The image doesn't have an own id-attribute.)
Your user might do one (or both) of these two drags:
Drag an img element from your webpage onto the canvas, or
Drag an image file from your local drive onto the canvas.
If the image is being dragged from your webpage:
Listen for the dragover, drop, and optionally the dragenter events.
When handling all 3 events, tell the browser you're handling the event with event.preventDefault and optionally event.stopPropagation.
In the drop handler, get event.dataTransfer.getData('text/plain') which fetches the.src` of the image that was dropped.
Create a new Image() object using the .src and drawImage to the canvas.
If the image is being dragged from your local drive:
1 & 2. Listen & handle the same events as in the webpage code.
Fetch the local image file(s) that the user dropped which have been placed in event.dataTransfer.files.
Create a FileReader and read each image file. The FileReader.readAsDataURL method will return an image URL that you can use as a .src for an Image object.
drawImage each new image to the canvas.
Here's example code that allows both:
window.onload=function(){
// canvas related vars
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
// dropZone event handlers
var dropZone=document.getElementById("canvas");
dropZone.addEventListener("dragenter", handleDragEnter, false);
dropZone.addEventListener("dragover", handleDragOver, false);
dropZone.addEventListener("drop", handleDrop, false);
//
function handleDragEnter(e){e.stopPropagation(); e.preventDefault();}
//
function handleDragOver(e){e.stopPropagation(); e.preventDefault();}
//
function handleDrop(e){
e.stopPropagation();
e.preventDefault();
//
var url=e.dataTransfer.getData('text/plain');
// for img elements, url is the img src so
// create an Image Object & draw to canvas
if(url){
var img=new Image();
img.onload=function(){ctx.drawImage(this,0,0);}
img.src=url;
// for img file(s), read the file & draw to canvas
}else{
handleFiles(e.dataTransfer.files);
}
}
// read & create an image from the image file
function handleFiles(files) {
for (var i=0;i<files.length;i++) {
var file = files[i];
var imageType = /image.*/;
if (!file.type.match(imageType)){continue;}
var img = document.createElement("img");
img.classList.add("obj");
img.file = file;
var reader=new FileReader();
reader.onload=(function(aImg){
return function(e) {
aImg.onload=function(){
ctx.drawImage(aImg,0,0);
}
// e.target.result is a dataURL for the image
aImg.src = e.target.result;
};
})(img);
reader.readAsDataURL(file);
} // end for
} // end handleFiles
}; // end $(function(){});
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<!doctype html>
<html>
<body>
<h4>Drag an image from below onto the canvas, or<br>Drag an image file from your desktop onto the canvas.</h4>
<canvas id="canvas" width=300 height=300></canvas>
<br>
<img width="50" src="https://cfl.dropboxstatic.com/static/images/index/rebrand/logos/glyphs/glyph_french_vanilla.svg">
</body>
</html>
Here is a set of (stripped down) tools I use to play with images
var imageTools = (function () {
var tools = {
canvas : function (width, height) { // create a blank image (canvas)
var c = document.createElement("canvas");
c.width = width;
c.height = height;
return c;
},
createImage : function (width, height) {
var image = this.canvas(width, height);
image.ctx = image.getContext("2d");
return image;
},
loadImage : function (url, callback) {
var image = new Image();
image.src = url;
image.addEventListener('load', cb);
image.addEventListener('error', cb);
return image;
},
image2Canvas : function (img) {
var image = this.canvas(img.width, img.height);
image.ctx = image.getContext("2d");
image.drawImage(ig, 0, 0);
return image;
},
getImageData : function (image) {
return (image.ctx || (this.image2Canvas(image).ctx)).getImageData(0, 0, image.width, image.height).data;
},
};
return tools;
})();
After it is parsed you will have the global variable imageTools
To load and get the image data you will have to wait for the image load callback.
var image;
var imageData;
function loaded(event){
if(event.type === "load"){
image = imageTools.image2Canvas(this);
imageData = imageTools.getImageData(image);
// image data is now in the typed array
// imageData.data
// with imageData.width and imageData.height holding the size
// there are 4 bytes per pixel in the form RGBA
}
}
imageTools.loadImage(imageURL,loaded);
To put the data back into the image after using the imageTools
// image.ctx is non standard and is a result of the imageTools adding the
// attribute ctx
image.ctx.putImageData(imageData,0,0);
To get the URL from the drop event which may be more than one image
var fileList = []; // a list of dropped images
// function called when images dropped
var imagesDropped = function(){
fileList.forEach(function(image){
// image.name is the image URL
// image.type is the mime type
});
fileList = []; // clear the file list
}
var dropEvent = function (event) {
var i,j, imagesFound;
imagesFound = false;
event.preventDefault();
dt = event.dataTransfer;
for (i = 0; i < dt.types.length; i++) { // for each dropped item
if (dt.types[i] === "Files") { // content from the file system
for (var j = 0; j < dt.files.length; j++) {
// check the mime type for the image prefix
if (dt.files[j].type.indexOf("image/") > -1){
fileList.push({ // add to image list
name : dt.files[j].name,
type : dt.files[j].type,
});
imagesFound = true; // flag images found
}
}
}
}
if(imagesFound){ // if images dropped call the handling function
imagesDropped();
}
}
Please note this is an example only and is not a cross browser solution. You will have to implement a variety of drop managers t cover all the browsers. This works on Chrome so covers the majority of users.

embed webgl in powerpoint or render animated gif from webgl

anyone got an idea how to embed a webgl animation into powerpoint. any tools that can be used on server side to capture an animated gif?
I did not make it work to embed webgl html directly in a powerpoint.
You can create images of webgl by calling toDataURL() as in
var canvas = document.createElement("canvas");
var gl = canvas.getContext("experimental-webgl");
function render() {
gl.clearColor(Math.random(), Math.random(), Math.random(), 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// takes a 'screenshot' of the canvas.
var image = canvas.toDataURL();
requestAnimationFrame(render);
}
render();
To make an animation you could send each of those screenshots to a server
...
var image = canvas.toDataURL();
var req = new XMLHTTPRequest();
req.open("POST", "http://localhost:8080", true);
var data = {
cmd: 'screenshot',
dataURL: image,
};
req.setRequestHeader("Content-type", "application/json");
req.send(JSON.stringify(data));
Here's a node.js server that will save the screenshots as .png files. You could then load them into some program to turn them into a gif.
var port = 8080
var screenshotCount = 0;
var http = require('http'),
url = require('url'),
fs = require('fs'),
util = require('util'),
path = require('path'),
querystring = require('querystring');
function postHandler(request, callback) {
var query_ = { };
var content_ = '';
request.addListener('data', function(chunk) {
content_ += chunk;
});
request.addListener('end', function() {
query_ = JSON.parse(content_);
callback(query_);
});
}
function sendJSONResponse(res, object) {
res.writeHead(200, {'Content-Type': 'application/json'});
res.write(JSON.stringify(object), 'utf8');
res.end();
}
function startsWith(str, start) {
return (str.length >= start.length &&
str.substr(0, start.length) == start);
}
function saveScreenshotFromDataURL(dataURL) {
var EXPECTED_HEADER = "data:image/png;base64,";
if (startsWith(dataURL, EXPECTED_HEADER)) {
var filename = "screenshot-" + (screenshotCount++) + ".png";
fs.writeFile(
filename,
dataURL.substr(
EXPECTED_HEADER.length,
dataURL.length - EXPECTED_HEADER.length),
'base64');
util.print("Saved Screenshot: " + filename + "\n");
}
}
server = http.createServer(function(req, res) {
// your normal server code
if (req.method == "POST") {
postHandler(req, function(query) {
switch (query.cmd) {
case 'screenshot':
saveScreenshotFromDataURL(query.dataURL);
sendJSONResponse(res, { ok: true });
break;
default:
util.print("err: unknown post: " + query + "\n");
break;
}
});
}
}),
server.listen(port);
Note that server only saves screenshots, it doesn't serve files (for brevity). So you'll need to either add that functionality or serve the files from another server.

JavaScript- calling functions from within functions

I am making an HTML5 canvas based game using JavaScript. The game is just a simple one, where a number of images are displayed on the canvas, along with a number of description boxes. The user is required to drag and drop each image to its corresponding description box.
Currently, I have the canvas displaying the images and description boxes. These are displayed straight away, as soon as the page loads, however, I want to add a 'start button' which the user will be required to click before the images and description boxes etc are displayed and they start playing the game.
The code for my page currently looks like this:
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
canvas{
border: 1px solid #9C9898;
background:#F5F5F5;
}
</style>
<div id="container"></div>
<script src="kinetic.js"></script>
<script src="drawdescriptionboxes.js"></script>
<script src="drawLevelOneElements.js"></script>
<script src="startGameDrawGameElementsDrawStartButton.js"></script>
<script>
/*Add the game elements' global variables */
var currentLevel = 1;
var totalLevels = 3;
var currentScore = 0;
var currentScorePositionX = 950;
var currentScorePositionY = 10;
/*Add code to draw images to random locations here */
//var imageX = Math.floor(Math.random()*950);
//var imageY = Math.floor(Math.random()*450);
var stage = new Kinetic.Stage({
container: "container",
width: 1000,
height: 500
});
var imagesLayer = new Kinetic.Layer();
var canvas = imagesLayer.getCanvas();
var context = canvas.getContext("2d");
console.log("Foo ");
/*Load the images from the HTML into the JavaScript */
function loadImages(sources, callback){
var imagesDir = "";
var images = {};
var loadedImages = 0;
var numImages = 0;
//console.log("length " + sources.length);
for (var src in sources){
numImages++;
}
//console.log("Num Images " + numImages);
var index=0;
console.log("length " + sources.length);
for (index=0;index < numImages ;index++){
console.log(index);
images[index] = new Image();
images[index].src = sources[index];
console.log("Adding " + sources[index]);
callback(images[index]);
console.log("sources array length = " + sources.length);
}
stage.add(imagesLayer); // should only be added once!!
}
/*Function to check whether the item being dragged is near its description box */
function isNearDescriptionBox(itemImage, descriptionBox){
var ii = itemImage;
var db = descriptionBox;
if(ii.attrs.x > db.x - 20 && ii.attrs.x < db.x + 20 && ii.attrs.y > db.y - 20 && ii.attrs.y < db.y +20){
return true;
}else{
return false;
}
}
/* This function draws the game elements */
function drawGameElements(){
/* Draw a line for the 'score bar'. */
context.moveTo(0, 25);
context.lineTo(1000, 25);
context.stroke();
/* Draw current level/ total levels on the left, and current score on the right. */
context.font = "11pt Calibri"; /* Text font & size */
context.strokeStyle = "black"; /* Font colour */
context.strokeText(currentLevel + "/" + totalLevels, 10, 15);
context.strokeText(currentScore, 750, 15);
}
function initStage(images){
var stage = new Kinetic.Stage({
container: "container",
width: 1000,
height: 500
});
var descriptionLayer = new Kinetic.Layer();
//var imagesLayer = new Kinetic.Layer();
var allImages = [];
var currentScore = 0;
var descriptionBoxes = {
assetsDescriptionBox: {
x: 70,
y: 400
},
liabilitiesDescriptionBox: {
x: 300,
y: 400
},
incomeDescriptionBox: {
x: 530,
y: 400
},
expenditureDescriptionBox: {
x: 760,
y: 400
},
};
/*Code to detect whether image has been dragged to correct description box */
for (var key in sources){
/*Anonymous function to induce scope */
(function(){
var privateKey = key;
var imageSource = sources[key];
/*Check if image has been dragged to the correct box, and add it to that box's
array and remove from canvas if it has */
canvasImage.on("dragend", function(){
var descriptionBox = descriptionBoxes[privateKey];
if(!canvasImage.inRightPlace && isNearDescriptionBox(itemImage, descriptionBox)){
context.remove(canvasImage);
/*Will need to add a line in here to add the image to the box's array */
}
})
})();
}
}
function drawImage(imageObj) {
//var layer = new Kinetic.Layer();
//var imageX = Math.floor(Math.random()*950);
//var imageY = Math.floor(Math.random()*450);
/*Got the code from generating random coordinates from:
http://stackoverflow.com/questions/4959975/random-between-two-numbers-in-javascript*/
function randomPosition(from, to){
return Math.floor(Math.random()*(to-from+1)+from);
}
var canvasImage = new Kinetic.Image({
image: imageObj,
width: 50,
height: 50,
// puts the image in teh middle of the canvas
x: randomPosition(0, 950), //imageX, //stage.getWidth() / 2 - 50 / 2,
y: randomPosition(30, 350), //imageY, //stage.getHeight() / 2 - 50 / 2,
draggable: true
});
// add cursor styling
canvasImage.on('mouseover', function() {
document.body.style.cursor = 'pointer';
});
canvasImage.on('mouseout', function() {
document.body.style.cursor = 'default';
});
imagesLayer.add(canvasImage);
}
/*This code loads the images to the canvas when the browser window loads */
window.onload = function(){
var sources = [];
sources[0] = document.getElementById("building").src,
sources[1] = document.getElementById("chair").src,
sources[2] = document.getElementById("drink").src,
sources[3] = document.getElementById("food").src,
sources[4] = document.getElementById("fridge").src,
sources[5] = document.getElementById("land").src,
sources[6] = document.getElementById("money").src,
sources[7] = document.getElementById("oven").src,
sources[8] = document.getElementById("table").src,
sources[9] = document.getElementById("van").src,
sources[10] = document.getElementById("burger").src,
sources[11] = document.getElementById("chips").src,
sources[12] = document.getElementById("drink").src,
sources[13] = document.getElementById("franchiseFee").src,
sources[14] = document.getElementById("wages").src,
sources[15] = document.getElementById("admin").src,
sources[16] = document.getElementById("cleaners").src,
sources[17] = document.getElementById("electricity").src,
sources[18] = document.getElementById("insurance").src,
sources[19] = document.getElementById("manager").src,
sources[20] = document.getElementById("rates").src,
sources[21] = document.getElementById("training").src,
sources[22] = document.getElementById("water").src,
sources[23] = document.getElementById("burger").src,
sources[24] = document.getElementById("chips").src,
sources[25] = document.getElementById("drink").src,
sources[26] = document.getElementById("creditors").src,
sources[27] = document.getElementById("electricity").src,
sources[28] = document.getElementById("food").src,
sources[29] = document.getElementById("hirePurchase").src,
sources[30] = document.getElementById("loan").src,
sources[31] = document.getElementById("overdraft").src,
sources[32] = document.getElementById("payeTax").src,
sources[33] = document.getElementById("tax").src;
drawStartButton();
loadImages(sources, drawImage);
//drawGameElements();
//drawDescriptionBoxes();
};
I also have a hidden section in the <body></body> of the page, where I've loaded all of the images to be used into the HTML first, before manipulating them using the JS.
Currently, when I view the page in a browser, all of the images from the sources array are displayed on the canvas in random locations, along with the description boxes, score bar, and start button.
However, what I want to happen, is that when the page initially loads, only the start button is displayed on the canvas, and then when the user clicks this, everything else is displayed.
Presumably, to do this, I would want to delete/ comment out the calls to all of the functions except drawStartButton() at the end of the windows.onload = function(){...} function, and then have calls to the other function in an onmousedown event attached to the start button?
However, for some reason, when I comment out the call to loadImages(sources, drawImage); at the end of this function, and then view my page in the browser again, the canvas is no longer displayed on the page. I would have expected the canvas to still be there, just without the images displayed on it. Does anyone have any idea why this isn't happening, and how I can put it right?
The code for my loadImages(sources, drawImage); function is:
function loadImages(sources, callback){
var imagesDir = "";
var images = {};
var loadedImages = 0;
var numImages = 0;
//console.log("length " + sources.length);
for (var src in sources){
numImages++;
}
//console.log("Num Images " + numImages);
var index=0;
console.log("length " + sources.length);
for (index=0;index < numImages ;index++){
console.log(index);
images[index] = new Image();
images[index].src = sources[index];
console.log("Adding " + sources[index]);
callback(images[index]);
console.log("sources array length = " + sources.length);
}
stage.add(imagesLayer); // should only be added once!!
}
I can't see why removing a call to this function would stop the canvas from being displayed on the page... any ideas?
The last line of the function,
stage.add(imagesLayer); // should only be added once!!
adds the layer to the stage. While the stage is a container (div, for example),
the layer is the actual canvas.
If you don't call loadImages(), the layer never gets added to the DOM, because that line never runs.

Add/Remove Image Dynamically from Controls in Google Maps V3

Greetigns Everyone,
I am working on a little application that will add and remove an image of a squirrel to a Google Maps application’s controls (http://www.geogodesigns.com/projects/squirrel/indexTest.html). Strange, yes, I know.
If you check out the site you will see that I can add and remove the squirrel just fine by clicking the 'Squirrel' button. However, subsequent additions and subtractions of the squirrel cause the little critter to scurry down the map. Hmmm...
What I want is for the squirrel to stay in the same place, just under the Google basemap controls, each and every time I click the 'Squirrel' button. This has been a tough nut to crack.
(function() {
window.onload = function() {
var chicago = new google.maps.LatLng(41.850033, -87.6500523);
var myOptions = {
zoom: 10,
center: chicago,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map"), myOptions);
var homeControlDiv = document.createElement('DIV');
var homeControl = new HomeControl(homeControlDiv, map);
homeControlDiv.index = 1;
map.controls[google.maps.ControlPosition.TOP_RIGHT].push(homeControlDiv);
};
})();
function HomeControl(controlDiv, map) {
controlDiv.style.padding = '5px';
var controlUI = document.createElement('DIV');
controlUI.style.backgroundColor = 'white';
controlUI.style.borderStyle = 'solid';
controlUI.style.borderWidth = '2px';
controlUI.style.cursor = 'pointer';
controlUI.style.textAlign = 'center';
controlUI.title = 'Show squirrel';
controlDiv.appendChild(controlUI);
var controlText = document.createElement('DIV');
controlText.style.fontFamily = 'Arial,sans-serif';
controlText.style.color = 'black';
controlText.style.fontSize = '12px';
controlText.style.paddingLeft = '4px';
controlText.style.paddingRight = '4px';
controlText.innerHTML = '<b>Squirrel</b>';
controlUI.appendChild(controlText);
var imageDiv = document.createElement('DIV');
imageDiv.setAttribute('id','imageDiv');
google.maps.event.addDomListener(controlUI, 'click', function() {
if(document.getElementById('image')){
controlUI.style.backgroundColor = 'white';
controlText.style.color = 'black';
var oldimage = document.getElementById('image');
imageDiv.removeChild(oldimage);
}
else{
controlUI.style.backgroundColor = 'black';
controlText.style.color = 'white';
var image = document.createElement('IMG');
image.setAttribute('id','image');
image.src = 'http://www.geogodesigns.com/projects/squirrel/img/squirrel.jpg';
imageDiv.appendChild(image);
map.controls[google.maps.ControlPosition.RIGHT].push(imageDiv);
}
});
}
Add the last line.
if(document.getElementById('image')){
controlUI.style.backgroundColor = 'white';
controlText.style.color = 'black';
var oldimage = document.getElementById('image');
imageDiv.removeChild(oldimage);
map.controls[google.maps.ControlPosition.RIGHT].pop(oldimage);
}

Resources