I am working with the HTML5 canvas element. I am using the following javascript to draw an image into the canvas:
var img = new Image();
var canvas = this.e;
var ctx = canvas.getContext('2d');
img.src = options.imageSrc;
img.onload = function() {
ctx.drawImage(img,0,0);
}
This works fine. However I am experiencing some weird css issues. When I use inline css like the following, the image scales perfectly in the canvas:
<canvas id="canvas" width="800" height="448"></canvas>
However, when I remove the inline css and use an external css file the image is drawn too big for the canvas and I only see the top left corner of the image. Here is the css I am using:
#canvas {
height:448px;
width:800px;
border:none;
}
When I use the inline css is the drawn image somehow inheriting the css from the canvas? Not sure what is going on here but I would like to use the external css file.
EDIT
If I provide no styling for the canvas element, it is smaller but still shows just the top corner of the image. When I do style it with a css file, the canvas is bigger but it is as if it just zoomed in on the image. The same amount of the image is shown, it is now just bigger.
EDIT 2
Based on the answer received I am now sizing the dom size of the canvas with javascript. I changed my img.onload function to the following:
img.onload = function() {
if (options.imageWidth == 0 && options.imageHeight == 0) {
canvas.height = this.height;
canvas.width = this.width;
} else {
canvas.height = options.imageHeight;
canvas.width = options.imageWidth;
}
ctx.drawImage(img,0,0);
}
Canvases have two sizes - the actual pixel grid size (in the width and height attributes) and the CSS size.
If the pixel size is not specified it typically defaults to something like 300x300.
The CSS size only specifies the amount of space taken in the page, and defaults to the pixel size. If they are not equal the image will be scaled.
You MUST specify the pixel size in the <canvas> element, or set it using Javascript:
var img = new Image();
var canvas = this.e;
var ctx = canvas.getContext('2d');
img.src = options.imageSrc;
img.onload = function() {
canvas.width = this.width; // new code
canvas.height = this.height; // "
ctx.drawImage(img, 0, 0);
}
Try putting !important on your external styles, might be that something is overriding it, but inline it overrides last.
#canvas {
height:448px !important;
width:800px !important;
border:none !important;
}
Related
I want to add draw shapes on a Image, so decided to use Fabric JS. I am able to get all shapes and objects working well. Now How do I background set exactly to Image. The Image is dynamic, I want to draw on top of that image, and basically store the annotations of objects for backend processing.
Existing solution using Canvas
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
canvas.width = 903;
canvas.height = 657;
var background = new Image();
background.src = "http://www.samskirrow.com/background.png";
// Make sure the image is loaded first otherwise nothing will draw.
background.onload = function(){
ctx.drawImage(background,0,0);
}
Reference - https://stackoverflow.com/a/14013068/2094670
I like this solution.
Live Demo
My Current Fabric JS Code
// Initialize a simple canvas
var canvas = new fabric.Canvas("c", {
hoverCursor: 'pointer',
selection: true,
selectionBorderColor: 'green',
backgroundColor: null
});
// Define the URL where your background image is located
var imageUrl = "../dog.jpg";
// Define
canvas.setBackgroundImage(imageUrl, canvas.renderAll.bind(canvas), {
// Optionally add an opacity lvl to the image
backgroundImageOpacity: 0.5,
// should the image be resized to fit the container?
backgroundImageStretch: false
});
Html
<canvas id="c"></canvas>
Problem.
The image of dog is full hd image, however I see only portion of it. How to do render the background image to its actual height and width using Fabric Canvas ? Since Images are comming dynamically, I might not know exact height and width to hardcode it.
Here's the way to set canvas size base on image size via fabric.js.
It's done initiating the Fabric canvas inside the onload callback, that way we are able to get the image width and height, then set them into the setDimesions method.
img.onload = function () {
...
canvas.setDimensions({ width: img.width, height: img.height });
};
var imageUrl = "http://i.imgur.com/yf6d9SX.jpg";
var background = new Image();
background.src = imageUrl;
// wait for the image to load, then set Fabric Canvas on the callback that runs after image finishes loading
background.onload = function () {
var canvas = new fabric.Canvas("c", {
hoverCursor: "pointer",
selection: true,
selectionBorderColor: "green",
backgroundColor: null,
});
// set canvas width and height based on image size
canvas.setDimensions({ width: background.width, height: background.height });
canvas.setBackgroundImage(imageUrl, canvas.renderAll.bind(canvas), {
// Optionally add an opacity lvl to the image
backgroundImageOpacity: 0.5,
// should the image be resized to fit the container?
backgroundImageStretch: false,
});
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.1.0/fabric.min.js"></script>
<canvas id="c"></canvas>
I want to display an element's width in javascript. This part is already working, but here is my issue :
When the element's width is animated, during the animation I want to see the real element's width, and not the final element's width.
I'm working with Angular, and what I wanted to do was possible by including JQuery using the function $(el).width() but I want to remove JQuery uses.
I already tried (assuming el is a HTML element) :
el.offsetWidth
el.clientWidth
el.scrollWidth
el.getBoundingClientRect().width
Some time ago I faced the same issue, with images who are not loaded yet and had the size of 0. I fixed the problem with using the following code to get the original image size. Be sure you continue your code inside the onload function
var image = new Image();
image.onload = function() {
// set its dimension to target size
var width = image.width;
var height = image.height;
};
image.src = el.img;
It is also possible to do this with a base64 string if needed
var image = new Image();
image.onload = function() {
// set its dimension to target size
var width = image.width;
var height = image.height;
};
image.src = "data:image/jpg;base64," + img;
I'm currently working with createJS canvas. I have an image with a predefined size into a Json file and boxes that are link to an eventListener on "mouseout" and "mouseover").
var stage = new createjs.Stage("testCanvas");
createjs.Touch.enable(stage);
stage.enableMouseOver(10);
Bitmap for the image:
var image = new Image();
image.onload = function () {
var img = new createjs.Bitmap(event.target);
stage.addChild(img);
then i draw my boxes (rectangles):
angular.forEach(..., function(value){
var rectGreen = new createjs.Shape();
rectGreen.graphics.beginFill("green")
.drawRect(
value.shapeDimension....,
value.shapeDimension....,
value.shapeDimension....,
value.shapeDimension....
);
rectGreen.alpha = 0.01;
stage.addChild(rectGreen);
my mouse events:
rectGreen.addEventListener("mouseover", function (event) {
var target = event.target;
target.alpha = 0.35;
stage.update();
});
rectGreen.addEventListener("mouseout", function (event) {
var target = event.target;
target.alpha = 0.01;
stage.update();
});
So, it's working but I have some difficulties with the canvas/image size.
If I don't set any width/heigth to the canvas Html, it results in a
300*150 canvas but the image is not resized so it displays only a
slight piece of the real image.
If i set width and height in the canvas html, (real size is 1700*1133), the image appears only 842*561 and the canvas takes place).
I tried different solution with Setting DIV width and height in JavaScript
but nothing enabled me to set my image correctly, and responsive so that the size of my rectangles adpt to the screen size of the image.
In order to dynamically resize the Canvas to the exact size of the image, you can do this:
//to get a variable reference to the canvas
var canvas = document.getElementById("testCanvas");
//supposing the Bitmap is the variable named 'img'
canvas.width = img.image.width;
canvas.height = img.image.height;
If you have more elements on the screen and the total size is bigger than the image itself, you can add everything on the screen in a container, and then scale the container itself to fit the canvas perfectly, like this:
var container = new createjs.Container();
container.addChild(img, [your other rectangle elements here]);
stage.addChild(container);
//will downscale or upscale the container to fit the canvas
container.scaleX = container.scaleY = canvas.width / img.image.width;
No matter what I try, I can't figure out why does drawImage vertically stretch a picture. Here is the code:
<canvas id="canvas" style="padding:0;border:0;margin:0 auto;
width:320px;height:456px;z-index:0;"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var d = new Image
d.src = './images/portadilla.jpg';
d.onload = function a(){context.drawImage(d, 0, 0);}
</script>
My image is 456px high and 320px wide, same as the canvas. I've tried using different images and formats, but the problem remains. How would you solve this?
Because you're not setting the size of the canvas correctly. Don't use CSS/style to set the size but use its attributes:
<canvas id="canvas" width=320 height=456 style="..."></canvas>
Your image is stretched because the default size of the bitmap for a canvas element is 300x150 pixels so if you don't set the size properly the canvas bitmap will be stretched to fit the element size set with CSS.
You can also set the size using JavaScript:
var canvas = document.getElementById('canvas');
canvas.width = 320;
canvas.height = 456;
I need to draw an Image object to a canvas but I've got an INDEX_SIZE_ERR exception in Firefox and IE10 but not in Chrome nor Safari...
According to the W3C: If one of the sw or sh arguments is zero, the implementation must raise an INDEX_SIZE_ERR exception..
Here is the code that causes the problem:
function writePhotoOnCanvas(data, width, height) {
// Get the canvas
var canvasGallery = document.getElementById("canvasGallery");
// Clear the canvas
canvasGallery.width = canvasGallery.width;
// Get its context
var ctxCapture = canvasGallery.getContext("2d");
// Create an image in order to draw in the canvas
var img = new Image();
// Set image width
img.width = width;
// Set image height
img.height = height;
// To do when the image is loaded
img.onload = function() {
console.log("img.width="+img.width+", img.height="+img.height);
console.log("width="+width+", height="+height+", canvasGallery.width="+canvasGallery.width+", canvasGallery.height="+canvasGallery.height);
// Draw the picture
try {
ctxCapture.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvasGallery.width, canvasGallery.height);
} catch(e) {
console.error(e.message);
}
};
// Set image content from specified photo
img.src = data;
}
The console shows:
img.width=640, img.height=480
width=640, height=480, canvasGallery.width=589, canvasGallery.height=440
Index or size is negative or greater than the allowed amount
What is the source of the problem?
Thanks
You are manually setting the width and height of the image (img.width = width; img.height = height;). I don't really understand why you are doing this, but it is likely unnecessary.
These should be calculated automatically from the image data you load. Try to remove them to see what the actual size of the data is.
The image width and height are read-only properties so they will cause the code to break in some browser.
If you absolutely want to set the width and height before loading the image you can do:
var img = new Image(width, height);
Then you can read img.width and img.height when image has loaded (or read img.naturalWidth and img.naturalHeight to get the original dimension).
There is no need though to do this. Simply call your drawImage() like this:
ctxCapture.drawImage(img, 0, 0, canvasGallery.width, canvasGallery.height);
This will use the full dimension of the image and scale it to the canvasGallery's dimension.
Tip: If you are using this function to load several images you will want to exchange img with this inside your onload handler.
Modified code:
function writePhotoOnCanvas(data, width, height) {
var canvasGallery = document.getElementById("canvasGallery");
var ctxCapture = canvasGallery.getContext("2d");
/// setting width to clear does not work in all browser, to be sure:
ctxCapture.clearRect(0, 0, canvasGallery.width, canvasGallery.height);
var img = new Image();
img.onload = function() {
// Draw the picture
try {
ctxCapture.drawImage(this, 0, 0,
canvasGallery.width, canvasGallery.height);
} catch(e) {
console.error(e.message);
}
};
// Set image content from specified photo
img.src = data;
}