I'm trying to display an image via JavaScript and set its opacity, but the opacity I've specified is getting ignored. I've tried all the latest browsers, but am mainly using IE11. The image I specify displays fine and I can position, scale, and rotate it without any problem. I've done extensive searches on this site and others to try to identify the problem but so far haven't had any luck. I've also tried rebooting my PC and using another PC to check the results. Nothing seems to help. Even trying a PNG file.
Here's my code:
var imageObj = new Image();
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
imageObj.onload = function () {
imageObj.style.filter = "alpha(opacity=20)";
imageObj.style.opacity = 0.20;
ctx.drawImage(imageObj, 10, 10);
};
Oh, prior to this code, the background color was set to pure white (#ffffff). I tried playing around with the background color, but it seemed to make no difference.
Try context.imageSmoothingEnabled = true;. The canvas element has a global alpha attribute that lets you apply partial transparency to anything you draw. You can see more here.
The CSS opacity is applied to the Node and not to the image data, this means that when you draw to your canvas' context, this meta information is forgotten.
Instead, you can use context.globalAlpha
imageObj.onload = function () {
var x = ctx.globalAlpha;
ctx.globalAlpha = 0.2;
ctx.drawImage(imageObj, 10, 10);
ctx.globalAlpha = x;
};
Beware though, this may not be safe if you're expecting to draw a lot asynchronously, so you may even want to create a second canvas for fixing the alpha, then export/import into the canvas you're really interested in, getImageData, putImageData.
Another option could always be to use an image format which supports an alpha channel, such as PNG and just serve the images at the desired opacity. This would cut down on processing, but may increase bandwidth usage (really depends on the image contents to how well each format compresses the data, e.g. JPEG is designed for photos/real world images whereas a PNG may better compress an artificial image with no noise).
Related
There's a bunch of questions on panning a background image in a canvas (i.e. to simulate a 'camera' in a game with the character in the center) - and most answers suggest using the canvas' translate method.
But since you have to re-draw the image in each frame anyway, why not just clip it? Does it matter in terms of efficiency?
In particular, is panning like this a bad idea? (This example shows a simplified pan of the camera moving in one direction)
let drawing = new Image();
drawing.src = "img_src";
drawing.onload = function () {
ctx.drawImage(drawing, 0, 0);
let pos = 0
setInterval(() => {
pos += 1
ctx.clearRect(0, 0, cnvs.width, cnvs.height);
ctx.drawImage(drawing, -pos, 0 ); // "pans" the image to the left using the option `drawImage` parameters `sx` and `sy`
}, 33);
};
Example result: fiddle
Thanks in advance!
The main advantage of using the transform matrix to control your camera is that you don't have to update all the elements in your world, you just move the world instead.
So yes, if you are willing to move only a single element (be it the background like in your case), moving only that one element might be a better choice.
But if you need several layers of elements to all move relatively to the camera, then using the transformation matrix is a better choice.
As for the perfs, I didn't ran any benchmarks on this, but I'd suspect it's exactly the same, though beware when messing with the cropping features of drawImage, at least Safari doesn't handle cropping from outside of a source canvas correctly.
I'm two days into js,html and css programming. So very newbie!
Following and building upon this TUTORIAL
Q1: How can I add this male into the background (see figuere 1.) and prohibit any strokes outside of the borders?
Adding image to background was no biggy!
function make_base()
{
base_image = new Image();
base_image.src = 'img/bmapFront.gif';
base_image.onload = function(){
context.drawImage(base_image, 0,0);
}
}
There is a context.clip function, not sure if I can use pixel form as clipping path. Making tons of "image substractions" isn't the best way.
Any suggestions
Edit:
Did the Job for me: VeryHelpful
var frontPath = new Path2D ("M 133.41,17.00 C 141.37,2.41 160.66, !VERY LONG! ")
context.clip(frontPath);
Messy strokes!
He should look like this. Then I want to save him.
Although there is such a thing as ctx.clip(), this is sometimes not what's wanted as it's impractical to use a path.
The solution that I like involves creating a virtual empty canvas onto which you draw your pixel image. Through various manipulations, like using ctx.getImageData and similar to make sure you only get one kind of color or apply other filters only once, you can obtain an image that seems to be empty (alpha of 0, mostly) in the places where you want to clip other images or paths out.
At that point, you'd use ctx.globalCompositeOperation = 'source-atop', or pick another one you might want to use from mdn's list of globalCompositeOperations.
At this point, you can just draw this virtual canvas image onto the main canvas
I created a basic 2D game using pure JavaScript. My problem is when the sprite stops moving it is sometimes blurred sometimes not. I use requestAnimationFrame to move the sprite and keydown/keyup events trigger moving. When keyup is triggered the sprite stops moving and the default tile is set however sometimes it is showing blurred.
https://arpadvas.github.io/untitled_game_project/
Since you didn't posted an minimal code example, and that I don't want to go through the raw code you linked to, this will stay as a guess (an educated one).
Generally, this happens when you draw your sprites on floating coordinates.
Since there is no way to draw on half a pixel, the pixel being the smallest unit in canvas, to smoothen drawings, the browser will by default create antialias artifacts, turning some pixels less opaque so that your eyes think it is on half a pixel.
While this usually works well with realistic photographs, it doesn't at all with pixel-art.
The solution then is either to round all your coordinates, or if you are lazy, to set the imageSmoothingEnabled property of your context.
var img = new Image();
img.onload = draw;
function draw(){
i = .316252;
blurred.width = round.width = noAntiAlias.width = img.width +20;
blurred.height = round.height = noAntiAlias.height = img.height +20;
blurred.getContext('2d').drawImage(img, 10+i, 20+i);
round.getContext('2d').drawImage(img, 10, 20);
var nA = noAntiAlias.getContext('2d');
nA.mozImageSmoothingEnabled = nA.msImageSmoothingEnabled = nA.webkitImageSmoothingEnabled = nA.imageSmoothingEnabled = false;
noAntiAlias.getContext('2d').drawImage(img, 10+i, 20+i);
};
img.src = "https://dl.dropboxusercontent.com/s/4e90e48s5vtmfbd/aaa.png";
<canvas id="blurred"></canvas>
<canvas id="round"></canvas>
<canvas id="noAntiAlias"></canvas>
Ps : this made me realize that somehow my FF doesn't smooth this particular image I used... If someone can confirm in comments, I'd be glad to dig into this further if needed.
I have been unsuccessfully trying to find documentation that details the limitations regarding the Html5 Canvas Element such as what is the largest image file size it can load etc. The reason I ask is that I have been trying to resize image sizes ranging from 50kb to 2.0mb through ctx.scale(), yet it has been horribly inconsistent in that for the same image sometimes ctx.drawImage() will be successful and other times unsuccessful (unsuccessful being no re-scaled image appears in the canvas).
I have also placed console.log(base64) to monitor the result of var base64 = canvas.toDataURL() and have noticed that when successfully resized the resized base64 will be quite a long string as expected and when unsuccessfully resized a string will still appear yet be relatively short and outputs a blank image.
Does this have something to do with memory limitations and the unsuccessful strings wrapping around themselves? If so, what are the memory limitations imposed on the canvas element?
First:
Hard limitations would depend on the browser, not the canvas API.
Even then, browsers are always trying to improve that performance, so that number would always be changing.
But with WebGL and Canvas being used to make games, texture atlases / sprite atlases are HUGE .jpg/.png files.
Chances are very, very good that your images are smaller, and I've frequently used 4MB/5MB/16MB images in canvas for demonstrations.
A huge image (or dozens of them) might crash the tab, if it's big enough, but until that time, canvas hasn't really complained to me.
Second:
There are security-limitations.
Editing photos in canvas comes down to what browser you're on, and whether the file is on the same domain as your website or not.
Third:
When you say that "large files don't work, but they do sometimes..."
...that leads me to believe that your image-loading method is faulty.
If you do something like this:
var canvas = document.createElement("canvas"),
context = canvas.getContext("2d"),
img = new Image();
img.src = "//mydomain.com/myimg.png";
context.drawImage(img, 0, 0, img.width, img.height);
...or anything else which isn't either event-based or callback-based,
then your problem has nothing to do with canvas and has everything to do with callbacks, and that you're trying to draw the image to the canvas before the image is done loading.
If your browser has already cached a copy of the large image, or if a small image only takes a fraction of a second to download, then there's no problem.
If you try downloading an 18MB image, and draw it to the canvas as soon as you set the url for the image, then you're going to get a blank screen, because it hasn't finished loading.
Instead, you need to wait for the image to finish loading, and then draw it to the canvas when it's ready.
var canvas = document.createElement("canvas"),
context = canvas.getContext("2d"),
image = new Image();
image.onload = function () {
var img = this,
width = img.width,
height = img.height;
canvas.width = width;
canvas.height = height;
context.drawImage(img, 0, 0, width, height);
document.body.appendChild(canvas);
};
image.src = "//mydomain.com/path-to-really-huge-image.png";
Now it could be a 16MP image. Nothing will happen until the file is done loading.
Then, the onload event fires, and does the rest of the setup.
You could make it more abstract, and turn it into a nifty program, but it feels like this is the key piece you might be missing.
I am faced with a problem that slows down animation on a canvas, as various pictures move left, right, up and down. I need advice on how to optimize the animation.
It is important that the animation works on all main browsers, in particular: Chrome, Firefox and Internet Explorer.
Is it possible to optimize the animation? Maybe put a delay on the drawing? Thank you in advance.
In javascript you can use the setInterval and setTimeout functions to create delays and throttle the frame rate.
for instance if you wanted to make your drawing loop approximately 30 FPS you could have some code that looks like this:
function draw(){
var canvas = document.getElementById('myCanvas');
//create the image object
var img = new Image();
//set the image object's image file path
var img.src = "images/myImage.png"
//check to see that our canvas exists
if( canvas.getContext )
{
//grab the context to draw to.
var ctx = cvs.getContext('2d');
//clear the screen to a white background first
//NOTE to make this faster you can clear just the parts
//of the canvas that are moving instead of the whole thing
//every time. Check out 'Improving HTML5 Canvas Performance'
//link mention in other post
ctx.fillStyle="rgb(255,255,255)";
ctx.fillRect (0, 0,512, 512);
//DO ALL YOUR DRAWING HERE....
//draw animation
ctx.drawImage(img, 0, 0);
}
//Recalls this draw update 30 times per second
setTimeout(draw,1000/30);
}
This will help you control how much processing time the animation is taking. Thus if you find that your animation is going too slow you can increase the frame rate by changing the denominator '30' to something like '60' fps or anything that really works well for your program.
As far as optimizing goes in addition to setTimeout() the way you draw your animations is critical too. Try to load all your images before you render them this is called "Preloading". That is if you have a bunch of different images for each animated cell then before you call your draw function load all the images into an array of images like so:
var loadedImages = new Array();
loadedImages[0] = new Image();
loadedImages[0].src = "images/animationFrame1.png";
loadedImages[1] = new Image();
loadedImages[1].src = "images/animationFrame2.png";
loadedImages[2] = new Image();
loadedImages[2].src = "images/animationFrame3.png";
loadedImages[3] = new Image();
loadedImages[3].src = "images/animationFrame4.png";
you could even put them in a hash if it makes sense for you app where instead of
loadedImages[0] = new Image();
loadedImages[0].src = "images/animationFrame1.png";
you do this
loadedImages['frame1'] = new Image();
loadedImages['frame1'].src = "images/animationFrame1.png";
once you have all your images loaded you references them for drawing by doing calling them like so:
//Using the integer array
ctx.drawImage(loadedImages[0], 0, 0);
//OR
//Using the stringed hash
ctx.drawImage(loadedImages['frame1'], 0, 0);
You want to separate your loading process from your rendering process because loading images is process intensive thus will slow your animations down if you are loading things while rendering.
That is not to say that you can't ever load anything while rendering, but instead just be conscience that this will slow animation speed down.
Here is an article on preloading images.
There is another post on here which talks about consistent animation speed on all browsers here
Note the link posted by the green checked answer
Other things to be noted are making sure to only clearing and redrawing bounding boxes as mentioned in the post with HTML 5 canvas optimization. That link has some really good techniques to be conscience of while developing canvas animations.
Here are some frame works as well which might come in handy to cross compare what you are doing to what other engines are doing.
Hope some of this helps. I am new to javascript (only started coding with it about 2 weeks ago) and so there could be better ways to do things but these are the things I have found thus far.
window.requestAnimationFrame() is one sure way to make your animation run smoother.
https://developer.mozilla.org/en/DOM/window.mozRequestAnimationFrame
(cross browser http://paulirish.com/2011/requestanimationframe-for-smart-animating/ )
However it doesn't fix the possible problems with your drawing code which was missing from the question.