I'm experimenting with the canvas element, but for some reason it doesn't display my image.
I use the following code:
function Canvas() {
this.field = function() {
var battlefield = document.getElementById('battlefield');
var canvas = battlefield.getElementsByTagName('canvas')[0];
return canvas.getContext('2d');
}
}
function Draw(canvas) {
if (!canvas) {
alert('There is no canvas available (yet)!');
return false;
}
this.canvas = canvas;
this.grass = function(pos_x, pos_y) {
var terrain = new Terrain();
var specs = terrain.grass();
var img = new Image();
img.onload = function(){
canvas.drawImage(img, specs.position_x, specs.position_y, specs.dimension_x, specs.dimension_y, pos_x, pos_y, specs.dimension_x, specs.dimension_y);
console.log('success???'); // this is being output
};
img.src = '/img/terrain.png';
}
}
(function() {
var canvas = new Canvas();
var draw = new Draw(canvas.field());
draw.grass();
})();
There are no errors, but the image just doesn't display. I've verified if the image exists and it does. I also verified the specs and they do contain what they should:
dimension_x: 25
dimension_y: 25
position_x: 0
position_y: 0
Any idea what I'm doing wrong?
http://jsfiddle.net/uwkfD/3/
pos_x and pos_y are undefined in your code. It works if you pass values for them to draw.grass():
draw.grass(0, 0);
DEMO
Tested in Chrome and Firefox.
This may be because you need a context to draw on.
Try:
this.context = canvas.getContext('2d')
Then call your draw functions on the context object not the canvas object:
this.context.drawImage(img, specs.position_x, specs.position_y, specs.dimension_x, specs.dimension_y, pos_x, pos_y, specs.dimension_x, specs.dimension_y);
It also appears that your reference to canvas is wrong too, it should be this.canvas (or this.context) not just canvas, at least as I understand scope in javascript.
Related
I'm importing an image (that has to come in portrait) onto a canvas object, rotating it (because it's actually landscape) and running some OCR on the base64 from the canvas. That all works fine. However when I put a new image onto the canvas, the old one is retained and never replaced. I've tried clearRect, even gone to the extent of creating a new dom element each time and destroying it when I have everything I need (which is still in the code below) but I just cannot get the first image to clear.
Here's the relevant bit of the code
function onSuccess(imageURI) {
//CREATE NEW CANVAS ELEMENT
g = document.createElement('canvas');
g.setAttribute("id", "thePic");
g.style.overflow = "visible";
document.body.appendChild(g);
const canvas = document.getElementById('thePic'),
context = canvas.getContext('2d');
make_base();
function make_base()
{
base_image = new Image();
base_image.src = imageURI;
base_image.onload = function(){
const uriheight = base_image.naturalHeight;
const uriwidth = base_image.naturalWidth;
console.log(uriwidth + " " + uriheight);
context.canvas.width = uriheight;
context.canvas.height = uriheight;
context.drawImage(base_image, 0, 0);
//ROTATE THE IMAGE 90
context.clearRect(0,0,canvas.width,canvas.height);
context.save();
context.translate(canvas.width/2,canvas.height/2);
context.rotate(90*Math.PI/180);
context.drawImage(base_image,-base_image.width/1.2,-base_image.width/1.2);
context.restore();
var theCanvas = document.getElementById('thePic');
var rotImg = theCanvas.toDataURL();
var rotImg = rotImg.substring(21);
textocr.recText(4, rotImg, onSuccess, onFail);
function onSuccess(recognizedText) {
var recdata = recognizedText.lines.linetext;
var blockData = recognizedText.blocks.blocktext;
context.clearRect(0, 0, 10000,10000);
base_image = "";
rotImg = "";
document.getElementById('thePic').outerHTML = "";
document.getElementById('cgh').innerHTML = "";
}
}
}
Any advice much appreciated.
So it turned out to not be the canvas at all, it was image caching in a previous function that give the image to the canvas.
Thanks to everyone who took the time to have a squiz.
I'm trying to output the pixel values from an image. The image is loading correctly; another answer on here suggested that the browswer is trying to read the pixels before the image is finished loading, but I can see that it's loaded by the time the alert() fires.
function initContext(canvasID, contextType)
{
var canvas = document.getElementById(canvasID);
var context = canvas.getContext(contextType);
return context;
}
function loadImage(imageSource, context)
{
var imageObj = new Image();
imageObj.onload = function()
{
context.drawImage(imageObj, 0, 0);
};
imageObj.src = imageSource;
return imageObj;
}
function readImage(imageData)
{
console.log();
console.log(imageData.data[0]);
}
var context = initContext('canvas','2d');
var imageObj = loadImage('images/color-test.png',context);
var imageData = context.getImageData(0,0,10,10);
alert();
readImage(imageData);
Image.onload() is called asynchronously when the image has been loaded. That can happen after your current code calls context.getImageData().
The following code should work:
function initContext(canvasID, contextType)
{
var canvas = document.getElementById(canvasID);
var context = canvas.getContext(contextType);
return context;
}
function loadImage(imageSource, context)
{
var imageObj = new Image();
imageObj.onload = function()
{
context.drawImage(imageObj, 0, 0);
var imageData = context.getImageData(0,0,10,10);
readImage(imageData);
};
imageObj.src = imageSource;
return imageObj;
}
function readImage(imageData)
{
console.log();
console.log(imageData.data[0]);
}
var context = initContext('canvas','2d');
var imageObj = loadImage('images/color-test.png',context);
If you want to access the imageData value outside of loadImage(), you have 2 basic choices:
Store the imageData in a variable that is declared outside the function. In this case, the value will be unset until your onload() is called, so the outside code would have to test it for reasonableness before calling readImage(imageData).
Have the outside code register a callback function, and have your onload() call that function with the imageData value.
It is also possible you are evaluating a portion of an image that is transparent. I had this issue while scanning a PNG.
Share a situation I encountered when I used a loop to request multiple images at the same time and get their pixels respectively. Then I encountered this problem.
//my code looks like this
for(let i = 0; i < urls.length; ++i){
let img = new Image() // it will be destoryed every loop begin, even if use keyword 'var' insteads of 'let'.
img.onload = ()=>{
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
ctx.drawImage(img, 0, 0)
let imgData = ctx.getImageData(0, 0, 1024, 1024) // imgData will be all 0 or some other unexpected result.
}
img.src = urls[i]
}
// fixed bug
window.imgs = []
for(let i = 0; i < urls.length; ++i)
window.imgs[i] = new Image()
for(let i = 0; i < urls.length; ++i){
let img = window.imgs[i]
img.onload = ()=>{
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
ctx.drawImage(img, 0, 0)
let imgData = ctx.getImageData(0, 0, 1024, 1024)
}
img.src = urls[i]
}
The reason may be object reference, garbage collection and other problems. I don't know. Because I'm a beginner of js.
I googled enough examples and found solution how to resize images:
function imageToDataUri(img, width, height) {
// create an off-screen canvas
var canvas = document.createElement('canvas'),ctx = canvas.getContext('2d');
// set its dimension to target size
canvas.width = width;
canvas.height = height;
// draw source image into the off-screen canvas:
ctx.drawImage(img, 0, 0, width, height);
// encode image to data-uri with base64 version of compressed image
return canvas.toDataURL();
}
function resizeImage() {
var newDataUri = imageToDataUri(this, 10, 10); // resize to 10x10
return newDataUri;
}
and this is my problem:
I have list of objects where each Item has based 64 image string: group.mAvatarImgBase64Str. That string is greater then 10x10 and I need replace it with new String.
So far I did:
if (group.mAvatarImgBase64Str !== 'none') {
var img = new Image();
img.onload = resizeImage;
img.src = group.mAvatarImgBase64Str;
// group.mAvatarImgBase64Str = ??
}
If I'll print out new value in resizeImage method - It resized properly but:
How do I add new String back to group.mAvatarImgBase64Str?
onload task is async and I need something like:
group.mAvatarImgBase64Str = resize(group.mAvatarImgBase64Str, 10, 10);
Thanks,
You should be able to do it this way:
if (group.mAvatarImgBase64Str !== 'none') {
(function(group) {
var img = new Image();
img.onload = function() {
group.mAvatarImgBase64Str = resizeImage.call(this);
}
img.src = group.mAvatarImgBase64Str;
})(group);
}
Additional IIFE is needed in case if you use for loop to iterate over array of object. If you use forEach loop, it's not needed.
I am writing some basic code using the prototypal pattern. I am trying to draw an image to canvas but it is not working. I have debugged the code within Chrome and it is because the image.onload is not firing. I don't believe the image is being loaded.
Here are the two functions that control this.
var SimpleGame = function () {
self = this; //Reference to this function
//Canvas
this.canvas = document.createElement("canvas");
this.ctx = this.canvas.getContext("2d");
this.canvas.width = 251;
this.canvas.height = 217;
//Default objects
this.bgReady = false;
this.bgImage = new Image();
};
var simpleProto = SimpleGame.prototype; //Cache the prototype
//Draw the objects on the canvas
simpleProto.draw = function() {
//Draw/ Render the canvas
document.body.appendChild(self.canvas);
//Draw the background
self.bgImage.onload = function() {
self.bgReady = true;
};
self.bgImage.src = "images/background.png";
if(self.bgReady) {
self.ctx.drawImage(self.bgImage, 10, 10);
};
}
Any idea why?
Your if(self.bgReady) is being tested before the image has a chance to load.
So naturally it will be false and drawImage will not be executed.
Fix:
Put self.ctx.drawImage in self.bgImage.onload
Good luck with your project!
its very confused i`m designing a 2d game and i use this code to draw images to canvas the alert method return background.x = 0 ! but when i change x to z or any letter its return the number 400 i ! why background.x always equal to zero ???
var canvas = document.getElementById('game');
var context = canvas.getContext('2d');
function loadResources(){
background = new Image();
background.src = "11.jpg";
background.width = 128;
background.height = 128;
background.x = 400;
background.y = 450;
}
function drawimage(){
alert(background.x);
context.drawImage(background,background.x,background.y,background.width,background.height);
}
function gameLoop() {
drawimage();
}
loadResources();
setInterval(gameLoop, 1000/60);
Unlike other objects, you are actually not able to set properties of an Image object that do not belong to it. As you've seen, when you try to access them after setting them, the properties will not be available. You can slightly rework your code as follows to get the behavior you're looking for:
var canvas = document.getElementById('game');
var context = canvas.getContext('2d');
var resources = {};
function loadResources(){
resources.background = new Image();
resources.background.src = "11.jpg";
resources.background.width = 128;
resources.background.height = 128;
resources.backgroundx = 400;
resources.backgroundy = 450;
}
function drawimage(){
console.log(resources.backgroundx);
context.drawImage(resources.background,resources.backgroundx,resources.backgroundy,resources.background.width,resources.background.height);
}
function gameLoop() {
drawimage();
}
loadResources();
setInterval(gameLoop, 1000/60);