Resize canvas elements - javascript

I am looking for an easy solution to resize a canvas element (a chart) automatically once the parent div size changes (= browser size changes). At the moment my Canvas element only fits perfectly into the parent div when the page is loaded.
This is what I've done so far and what I've tried:
<div class="panel-body">
<canvas id="userlogins"></canvas>
<script type="text/javascript">
jQuery(document).ready(function($)
{
var ctx = $("#userlogins").get(0).getContext("2d");
var myLineChart = new Chart(ctx).Line(data, options);
});
function fitToContainer(canvas){
// Make it visually fill the positioned parent
canvas.style.width ='100%';
// ...then set the internal size to match
canvas.width = canvas.offsetWidth;
}
var canvas = document.querySelector('canvas');
fitToContainer(canvas);
jQuery( window ).resize(function() {
fitToContainer(canvas);
redraw();
});
</script>
</div>
When I resize my browser the canvas chart disappears. The parent div fit on page load works well.
Edit: The approaches in the given "duplicates" doesn't work for me! Here is what I have tried given from the "duplicate question":
jQuery( window ).resize(function() {
clearTimeout(timerID);
timerID = setTimeout(function() {
var cnvs = $("#userlogins")[0]; // cache canvas element
var rect = cnvs.getBoundingClientRect(); // actual size of canvas el. itself
cnvs.width = rect.width;
cnvs.height = rect.height;
redraw();
});
});

It looks like you're using ChartJS. If yes, it has a property you can set to make the chart responsive to resizing.
Chart.defaults.global.responsive = true;

Changing the canvas element width or height clears the canvas. In fact, it's often used as a way of clearing it on purpose. So this line:
canvas.width = canvas.offsetWidth;
clears your canvas. After that, you can either:
redraw the chart
or remove that line and rely on the CSS transformations, which can ruin the proportions of your canvas

Related

Canvas height and width

When programming in HTML canvas, the js dimensions of the canvas don't always match the css dimensions.
Why is this happening and how can I fix this?
I've found the problem. I was setting the dimensions of the  using CSS, when you actually have to set the width and height attributes. This was causing it to be stretched/skewed.
var canvas = $('<canvas/>').attr({width: cw, height: ch}).appendTo('body');
http://jsfiddle.net/h2yJn/66/
You can try to set the width and height of the canvas to be equal to the dimensions of the window object:
function createCanvas() {
var ctx = //the canvas context;
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
//your code
}
In addition, it is a good idea to set the body and html tags to the full width of the window:
body, html{
height: 100%;
width: 100%;
}
You can also do this by using pure javascript and set the dimensions of the canvas in javascript depending on your CSS values:
//Get Canvas
var canvas = document.getElementById("canv");
// Get computed style of the canvas element.
var cstyle = window.getComputedStyle(canvas);
// Returns the width as str in px: e.g. 600px.
// Parse resolves that issue.
canv.width = parseInt(cstyle.width);
canv.height = parseInt(cstyle.height);
Demo:
https://jsfiddle.net/ofaghxfq/2/

CreateJs Canvas resize Bitmap

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;

Canvg - canvas changes on mousemove

I am using canvg in order to render some SVG into an image. Currently SVG to canvas part is working just fine. However I am unable to determine why the generated canvas changes when a pointer enters it. Do I really have to copy the generated canvas, or am I missing something?
svgElement.each(function () {
var canvas = document.createElement("canvas");
//convert SVG into a XML string
var xml = (new XMLSerializer()).serializeToString(this);
// Removing the name space as IE throws an error
xml = xml.replace(/xmlns=\"http:\/\/www\.w3\.org\/2000\/svg\"/, '');
// Rounded svg dimensions
var width = Math.floor(svgElement.width());
var height = Math.floor(svgElement.height());
// Draw the SVG onto a canvas
canvas.width = width;
canvas.height = height;
$(canvas).css('border', '2px solid red');
canvg(canvas, xml, {
ignoreDimensions: true,
scaleWidth: width,
scaleHeight: height
});
$('body').append(canvas); // When pointer enters the canvas it changes
// I can copy the canvas and that copy won't change on pointer enter.
$(this).hide();
}
jsfiddle
Verified on Firefox DE 47 and Chrome 49 under MacOS X El Capitan (also my friend verified that this is happening under Windows on both Firefox and Chrome).
You have to use the ignoreMouse option :
updated fiddle : http://jsfiddle.net/35t6fkvj/7/
canvg(canvas, xml, {
ignoreDimensions: true,
scaleWidth: width,
scaleHeight: height,
ignoreMouse: true
});
Not sure why it thinks it should add some mouse events though

Force constant dimensions of a HTML video element regardless of dimensions and ratio of source

I am trying to do a not so simple task. I would like to have in a HTML5 page a video element with constant width and height (those of the window), that can manages the dimensions and aspect ratio of the source video to display at best that is to say with the window fully covered with the video and with no scroll bars.
I wrote this javascript code:
$("video").bind("loadedmetadata", function () {
var screenSize = {}, videoSize = {};
videoSize["width"] = this.videoWidth;
videoSize["height"] = this.videoHeight;
screenSize["height"] = $( window ).height();
screenSize["width"] = $( window ).width();
var ratio_screen = screenSize["width"]/screenSize["height"];
var ratio_video = videoSize["width"]/videoSize["height"];
if (ratio_video > ratio_screen) {
$("video").height(screenSize["height"]);
$("video").width(screenSize["height"]*ratio_screen);
}
else
{
$("video").width(screenSize["width"]);
$("video").height(screenSize["width"]/ratio_screen);
}
});
At the moment, I have a video element, almost fitting the window (I still have a border or margin that inspector says to be part of html element). But the source video is fitting inside the video element! As an example for my test video which is wider than the screen, I have a black strip over and under the video.
How can I manage this to "zoom" the video. Do I have to apply a scaling factor to the video element or somenthing can be done at source video level.
Thanks
Finally this piece of code worked:
$("video").on('canplay',function() {
$("video").bind("loadedmetadata", function () {
var screenSize = {}, videoSize = {};
videoSize["width"] = this.videoWidth;
videoSize["height"] = this.videoHeight;
screenSize["height"] = $( window ).height();
screenSize["width"] = $( window ).width();
var ratio_screen = screenSize["width"]/screenSize["height"];
var ratio_video = videoSize["width"]/videoSize["height"];
if (ratio_video > ratio_screen) {
$("video").css("-webkit-transform", "scale("+ratio_video/ratio_screen+")");
$("video").height(screenSize["height"]);
$("video").width(screenSize["height"]*ratio_screen);
} else {
$("video").css("-webkit-transform", "scale("+ratio_video/ratio_screen+")");
$("video").width(screenSize["width"]);
$("video").height(screenSize["width"]/ratio_screen);
}
});
});
This results in displaying a video, filling the whole screen, without stretching the video if the aspect ratio is not fitting the one of the screen.
Note that my video element plays several sources in a loop. The first video played does not apply this resizing function (I have to work on that to ensure the at start up this works).

jQuery and Canvas loading behaviour

After being a long time lurker, this is my first post here! I've been RTFMing and searching everywhere for an answer to this question to no avail. I will try to be as informative as I can, hope you could help me.
This code is for my personal webpage.
I am trying to implement some sort of a modern click-map using HTML5 and jQuery.
In the website you would see the main image and a hidden canvas with the same size at the same coordinates with this picture drawn into it.
When the mouse hovers the main picture, it read the mouse pixel data (array of r,g,b,alpha) from the image drawn onto the canvas. When it sees the pixel color is black (in my case I only check the RED value, which in a black pixel would be 0) it knows the activate the relevant button.
(Originally, I got the idea from this article)
The reason I chose this method, is for the page to be responsive and dynamically change to fit different monitors and mobile devices. To achieve this, I call the DrawCanvas function every time the screen is re-sized, to redraw the canvas with the new dimensions.
Generally, this works OK. The thing is ,there seems to be an inconsistent behavior in Chrome and IE(9). When I initially open the page, I sometimes get no pixel data (0,0,0,0), until i re-size the browser. At first I figured there's some loading issues that are making this happen so I tried to hack it with setTimeout, it still doesn't work. I also tried to trigger the re-size event and call the drawCanvas function at document.ready, still didn't work.
What's bothering me is most, are the inconsistencies. Sometimes it works, sometimes is doesn't. Generally, it is more stable in chrome than in IE(9).
Here is the deprecated code:
<script type="text/javascript">
$(document).ready(function(){setTimeout(function() {
// Get main image object
var mapWrapper = document.getElementById('map_wrapper').getElementsByTagName('img').item(0);
// Create a hidden canvas the same size as the main image and append it to main div
var canvas = document.createElement('canvas');
canvas.height = mapWrapper.clientHeight;
canvas.width = mapWrapper.clientWidth;
canvas.fillStyle = 'rgb(255,255,255)';
canvas.style.display = 'none';
canvas.id = 'hiddencvs';
$('#map_wrapper').append(canvas);
// Draw the buttons image into the canvas
drawCanvas(null);
$("#map_wrapper").mousemove(function(e){
var canvas = document.getElementById('hiddencvs');
var context = canvas.getContext('2d');
var pos = findPos(this);
var x = e.pageX - pos.x;
var y = e.pageY - pos.y;
// Get pixel information array (red, green, blue, alpha)
var pixel = context.getImageData(x,y,1,1).data;
var red = pixel[0];
var main_img = document.getElementById('map_wrapper').getElementsByTagName('img').item(0);
if (red == 0)
{
...
}
else {
...
}
});
},3000);}); // End DOM Ready
function drawCanvas(e)
{
// Get context of hidden convas and set size according to main image
var cvs = document.getElementById('hiddencvs');
var ctx = cvs.getContext('2d');
var mapWrapper = document.getElementById('map_wrapper').getElementsByTagName('img').item(0);
cvs.width = mapWrapper.clientWidth;
cvs.height = mapWrapper.clientHeight;
// Create img element for buttons image
var img = document.createElement("img");
img.src = "img/main-page-buttons.png";
// Draw buttons image inside hidden canvas, strech it to canvas size
ctx.drawImage(img, 0, 0,cvs.width,cvs.height);
}
$(window).resize(function(e){
drawCanvas(e);
}
);
function findPos(obj)
{
...
}
</script>
I'd appreciate any help!
Thanks!
Ron.
You don't wait for the image to be loaded so, depending on the cache, you may draw an image or not in the canvas.
You should do this :
$(function(){
var img = document.createElement("img");
img.onload = function() {
var mapWrapper = document.getElementById('map_wrapper').getElementsByTagName('img').item(0);
...
// your whole code here !
...
}
img.src = "img/main-page-buttons.png";
});

Categories

Resources