I am aware of having to set the size of a <canvas> element using the width and height attribute to avoid stretching. I have no CSS applied to it other than background-color.
I am using ctx.drawImage() to show a video. The weird thing is, my 640x480 video plays fine and is not stretched. It is only happening on my 640x360 videos for now.
I have created an angular directive that draws video onto a canvas element and it all works except for the stretching. Here is my code that draws the video element onto the canvas:
scope.renderPlayer = function()
{
var $this = this;
attributes.width = player.videoWidth;
attributes.height = player.videoHeight;
canvas.setAttribute('width', attributes.width);
canvas.setAttribute('height', attributes.height);
(function loop()
{
if (!$this.paused && !$this.ended)
{
ctx.drawImage($this, 0,0, attributes.width, attributes.height);
setTimeout(loop, 1000/30);
}
})();
};
player.addEventListener('play', scope.renderPlayer);
I assure you the source of the videos don't have that stretching artifacting on the bottom as shown in the image below (You can really see the pixels stretched on the bottom right). My initial width and height of the canvas element is 640x480 and it will change depending on the size of the loaded video.
Let me know if this CSS fixes it for you, I need it whenever I use canvas:
canvas {
display: block;
}
the canvas tag is susceptible to the same pitfalls as the img tag in that it renders extra space below it. You are correct to set the dimensions as HTML attributes though, what a pain.
I haven't worked with canvas in a while, but you can give ctx.drawImage($this) a try, also you can requestAnimationFrame and use it instead of setTimeout:
scope.renderPlayer = function()
{
var $this = this;
canvas.width = player.width; // if canvas is a Jquery Object, try canvas[0].width
canvas.height = player.height; // if canvas is a Jquery Object, try canvas[0].height
(function loop()
{
if (!$this.paused && !$this.ended)
{
ctx.drawImage($this);
setTimeout(loop, 1000/30);
}
})();
};
player.addEventListener('play', scope.renderPlayer);
Related
I have a canvas with an image that fills the canvas. This works fine but I would like to have the canvas be full width of the window. At the moment the canvas is the width of the image I put in it.
I've tried the following at the bottom of my script:
function resizeCanvas() {
canvas.setHeight(img.height);
canvas.setWidth(window.innerWidth);
canvas.renderAll();
}
resizeCanvas();
But this does not work.
I've also tried giving the canvas element 100% width in its paramaters and with css, both with no success.
Codepen with working example:
https://codepen.io/twan2020/pen/YzpeEEr
If you increase your screen size the image stops after a while instead of keeping full width of the browser window.
Is this possible? With keeping all objects in their place?
It was not easy to fix but i found some documentation that could make it work.
First edit the code to realWidth and add var realWidth = window.innerWidth;
and then for setting the background remove your current code and add
fabric.Object.NUM_FRACTION_DIGITS = 10;
fabric.Image.fromURL(source, function(img) {
img.scaleToWidth(canvas.width);
canvas.setBackgroundImage(img);
canvas.requestRenderAll();
});
this should fix the problem, and the backgound will take the full size of the screen.
Update for the new calculation of the circle position.
is equal to Newposition= oldPosition * (newWidth / oldWidth)
Here you can see that it work https://codepen.io/AlenToma/pen/ExNEooX
I'm developing a drawing app, and I've encountered a problem which I have been trying to solve but I haven't found a reliable solution yet:
Sketches have an original resolution of 1280 x 720, and I would like to resize the canvas when the page is opened to the maximum size possible (given the screen dimensions minus a toolbar I have put on the upper side of the page) keeping the 1280 x 720 aspect ratio.
The canvas needs to be centered in the screen and black stripes will cover the rest: when the the browser window dimensions relation is less than the sketch original w/h relation there will be horizontal black stripes (fig 1), and when it is bigger, vertical black stripes (fig 2).
I've tried using javascript applying to the canvas the offsetWidth and offsetHeight of a div containing an auxiliar invisible image which I generate programatically with the original sketch dimensions, but doesn't seem to be a robust way to do this. Most of the time the offset properties aren't ready when the page is loaded and I have to wait for them using a timer (or mutation observers).
Some images of what I'm trying to do:
I've spend much time on this little thing and is driving me crazy, because every solution I found is way too hacky or unreliable. Any help will be very appreciated.
I'm using Angular + Ionic 4.
If I'm understanding you correctly, you want to dynamically change the size of your canvas based on how big the window is. The one stipulation is that it must maintain the 1280 x 720 (1:0.5625) ratio.
I'm going to attempt to provide a solution that will also listen for resizing of the window after it's been loaded. Keep in mind that this means you'll need to redraw everything on the canvas from there.
HTML
<body>
<canvas id="canvas"></canvas>
</body>
CSS
body {
background-color: black;
}
JavaScript:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
startListening();
function startListening() {
// resize the canvas every time the window is adjusted
window.addEventListener('resize', resizeCanvas, false);
// manually call the resizeCanvas() function as the window loads with it's starting dimensions (before a resize has happened)
resizeCanvas();
}
function resizeCanvas() {
// if the canvas height isn't maxed out, match it to the width of the page at the correct aspect ration (1:0.5625)
if(canvas.height < window.innerHeight){
canvas.width = window.innerWidth;
canvas.height = canvas.width * 0.5625;
}
// if the canvas height is maxed out, stop widening the canvas and lock the canvas height at 0.5625 of that locked height
if(canvas.height >= window.innerHeight){
canvas.height = canvas.width * 0.5625;
}
// lastly, if we are shrinking the width back down, readjust both the width and height to match
if(canvas.width > window.innerWidth){
canvas.width = window.innerWidth;
canvas.height = canvas.width * 0.5625;
}
// redraw the canvas with our newly calculated dimensions
redraw();
}
function redraw() {
ctx.fillStyle = "#FF0000";
// Draw the canvas in the center of the screen at the height and width calculated above in the resizeCanvas() function
ctx.fillRect((window.innerWidth - canvas.width) / 2, (window.innerHeight - canvas.height) / 2, canvas.width, canvas.height);
}
I'm having a problem with loading image into canvas - the image is somehow scaled.
Background: I've got several canvases on my web page, I want to load images into them. When constructing, I'm not sure about the dimension, because the size depends on the screen size.
So I create div and canvas, use css to have it in the size that I want it to have and print an image onto the canvas. There would couple more things to do with the image (i.e. decide based on the ratio if I need to center it vertically or horizontally), but those are not really important at this point. The problem is that the image is rendered "zoomed".
Example: the javascript piece is here:
$("canvas").each(function() {
var context = $(this)[0].getContext('2d');
var img = new Image;
img.src = 'http://i67.tinypic.com/n38zdv.jpg';
$(img).load(function() {
context.drawImage(this, 0, 0);
});
//img will print 400 (correct, thats the width of the img)
//canvas will print based on the screen size (correct)
//img displayed in the canvas shows 300px out of 400px, it's zoomed (not correct)
$(this).parent().append(
'img width: '+img.width+
', canvas width: '+$(this).width());
});
I put the whole example with HTML and CSS to https://jsfiddle.net/7zdrfe58/11/.
I'm trying on Mac. Safari and Chrome work the same (i.e. with the zoom).
I would very appreciate help with this!! Thanks a lot
drawImage lets you specify the width and height of the image. You can get the canvas width like so:
$("canvas").each(function() {
var canvas = this;
var context = canvas.getContext('2d');
var img = new Image;
img.src = 'http://i67.tinypic.com/n38zdv.jpg';
$(img).load(function() {
context.drawImage(this, 0, 0, canvas.width, canvas.height);
});
});
Check out your working code here:
https://jsfiddle.net/ucxdLsq9/
The documentation of the drawImage signatures can be found here:
https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/drawImage
Give proper width and height to drawImage.
context.drawImage(this, 0, 0 ,300 ,160);
Updated Fiddle
I'm using Easel JS to develop Canvas based Solitaire game.
TODO: Set height for canvas and draw all elements inside of that.
Issue: EaselJS change the canvas height automatically.
References:
How I set the height:
var gameBoard = document.getElementById("board");
gameBoard.style.height = window.innerHeight+"px";
gameBoard.height = gameBoard.offsetHeight;
gameBoard.style.height = "auto";
Without knowing what your goals are, it's hard to tell what the problem is exactly... but setting the CSS "canvas.style.height" property to "auto" seems to be the problem. The width and height properties (not CSS) are still what you set them to originally (1300 x 501).
Remove this line and you will be left with a canvas that is the size of the window when the page is loaded.
gameBoard.style.height = "auto";
If you want your canvas to have as many pixels as there are in the window, you will need to listen for the "resize" event and apply the values back to your canvas.
window.addEventListener("resize", function(){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
});
When using the HTML5 drag and drop API, it would appears though the .width property on has no impact on the width of an image being used as an icon for dragging. Take this fiddle for example: http://jsfiddle.net/cnAHv/7/. You can set dragIcon.width to anything you want, and it will not change the actual width of the icon.
Most of the resources on the web seem to arbitrarily set dragIcon.width to 100. Is this just a matter of people copying eachother's code without checking functionality?
So...
Is the width property on an image variable actually something that setDragImage() will accept?
If not, how would you set the width of the icon without manually changing sizing the image in a program like photoshop?
When you use an <img> in setDragImage Javascript will just use the actual image bitmap data, ignoring other attributes like width. Check the specs.
However if you do something like this:
function handleDragStart(e) {
var dragIcon = document.createElement('img');
dragIcon.src = 'http://jsfiddle.net/favicon.png';
dragIcon.width = '100';
var div = document.createElement('div');
div.appendChild(dragIcon);
document.querySelector('body').appendChild(div);
e.dataTransfer.setDragImage(div, -10, -10);
}
http://jsfiddle.net/cnAHv/9/
You will see the drag shadow now contains the bigger image. It occurs because when we use other visible HTML elements (that's why I appended the DIV to the body), the browser will use its rendered view as a drag image.
This answer might be a bit late but you can also use a canvas to scale your original image.
function handleDragStart(e) {
var dragIcon = document.createElement('img');
dragIcon.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC';
var width = 100;
var height = width * (3/4); // The height must be set explicitly. I'm assuming the image is 4:3 for this example
var c = document.createElement("canvas");
c.width = width;
c.height = height;
var ctx = c.getContext('2d');
ctx.drawImage(dragIcon,0,0,width,height);
dragIcon.src = c.toDataURL();
e.dataTransfer.setDragImage(dragIcon, -10, -10);
}
http://jsfiddle.net/cnAHv/138/
The only downside to this is that the canvas may be tainted if the image doesn't come from the same origin. More on tainted canvases here