Determine when a canvas is resized - javascript

I am trying to determine when a canvas is resized to repaint it.
Context: my canvas is inserted in a flex layout and its height gets set by the flexbox model and changes depending on other layout elements whose content and size may dynamically vary (e.g., the result of an AJAX request inserts texts in a nearby span, which causes the canvas to grow by, say, 10 pixels vertically).
It seems that the resize event is only sent to the window — so the resize event does not do the trick here, as the canvas may also change its size when the window does not.
How can I get notified when my canvas is resized?

If multiple parts of your code will change your canvas size, then you must indeed refactor each scriptlet to notify you when it changes the canvas size.
An easy way to do this is to create a resizing function that any scriptlet must use to resize the canvas. If that function is called, you know a scriptlet has resized the canvas:
function resizeCanvas(canvas,w,h){
canvas.width=w;
canvas.height=h;
// All canvas resizing will flow to this point
// so respond to the resizing here.
console.log('The canvas has been resized');
}

Related

HTML5 canvas and scrolling

I have a canvas element of size 1024x768 where I draw a very large image, let's just say with width >> 1024 and height >> 768. The image can be scrolled with normal scrollbars to be seen entirely.
Users can click onto the canvas to add vertices to a polygon: each time a vertex is added, a line from the new vertex to the mouse cursor is drawn.
Each mouse movement onto the canvas updates the canvas in order to redraw such line from the vertex to the new mouse cursor position.
Being the image VERY large, redrawing is very slow, so I'd like to just redraw the currently visible chunk of image or, even better, the "sub-chunk" that is affected by this line.
The problem is: how do I detect the current topLeft and bottomRight of the visible part of the context according to how much the user scrolled the image? Basically I'd like to add support for a custom viewport, but I can't seem to exploit the scolling information to determine the boundingBox of the chunk to crop from the original image.
I actually have a canvasDiv container, which is the real scrollable element, not the canvas itself.
This means your canvas is the full size and you're using the container div as a sort of a "frame". That's really bad as canvas pixels are quite expensive, especially if you're not even using them (they're out of the viewport).
The best approach here is to set the canvas size to the container size and use the drawImage function to control the scrolling. The original image would be places either on an offscreen canvas or an image element. I can guarantee you a much better performance this way.
You'll lose the scrollbars, that's the downside.
I'm assuming you create the scrollbars by having a larger canvas element contained inside a smaller div.
Instead, you can mimic this setup by:
Having a canvas the size of your container div.
Add 2 input type=range controls to act as vertical & horizontal scrollbars (or grab a jqueryUI scrollbar plugin if you want to be fancy).
Then you can use the clipping version of context.drawImage to draw only the portion of the image specified by the range controls. The clipping version of drawImage looks like this: drawImage(myLargeImage, clipX,clipY,clipWidth,clipHeight, 0,0,canvas.width,canvas.height)

HTML Blurry Canvas Images

I use jcrop to provide users with a friendly way of uploading their images via ajax. Obviously these images have some constraint like width and height which is where jcrop comes into play. So for the sake of brevity what im doing is as follows:
input file select via javascript file api loads the image into a img tag. Jcrop works with this image tag and renders the result onto a html canvas.
Now this is the dodgy part. The canvas image is always blurry...
for arguments sake the canvas is set to 400x200 which is the crop size.
If the canvas width and height is set via CSS it results in a blurry image result. TO get around this I had to set the width and height via html attributes. Now I have a wonderful cropping solution that can save images via AJAX. Crisp and Clear:)
<canvas id="preview" width="400" height="200"></canvas>
According to HTML Standard, if width or height attribute is missing, then the default value must be used instead, which is 300 for width and 150 for height. And these two attributes will determine the canvas's width and height, while the css properties merely determine the size of the box in which it will be shown.
The canvas element has two attributes to control the size of the element's bitmap: width and height. These attributes, when specified, must have values that are valid non-negative integers. The rules for parsing non-negative integers must be used to obtain their numeric values. If an attribute is missing, or if parsing its value returns an error, then the default value must be used instead. The width attribute defaults to 300, and the height attribute defaults to 150.
The intrinsic dimensions of the canvas element when it represents embedded content are equal to the dimensions of the element's bitmap.
The user agent must use a square pixel density consisting of one pixel of image data per coordinate space unit for the bitmaps of a canvas and its rendering contexts.
A canvas element can be sized arbitrarily by a style sheet, its bitmap is then subject to the 'object-fit' CSS property.
You can refer to the following post for more details:
Canvas is stretched when using CSS but normal with "width" / "height" properties
This is really just an extension of the answer above. I too encountered the problem of CANVAS images resized using Javascript/CSS becoming fuzzy and blurry, because my application first used HTML to create a few DIVs, one of which held a CANVAS control, then the ONLOAD event called a Javascript routine to get the screen size, optimise the sizes and positions of all the DIVs and the CANVAS accordingly, and finally draw on the CANVAS. I did it that way as I wanted the CANVAS to always be as big possible for whatever device it was viewed on.
My solution is to use Javascript to dynamically draw the CANVAS control too, i.e. for the DIV that contains the CANVAS simply include...
var CanvasWidth=screen.availWidth-30;
var CanvasHeight=screen.availHeight-190;
//The 30 and 90 above are arbitrary figures to allow for other DIVS on the page
var o=window.document.getElementById("IdOfDivContainingCanvas");
o.innerHTML="<canvas id='myCanvas' width='"+CanvasWidth+"' height='+CanvasHeight+'></canvas>";
...so that the size of the CANVAS is effectively dynamic; Created with it's size specified using HTML attributes, just before executing the Javascript statements that actually draw on the CANVAS.

Make HTML canvas bigger while scaling the website

Do you have any idea how it could be possible not to scale a HTML canvas element while scaling the whole website (ctrl+"+" in most browsers) but to make its dimensions bigger? I have got an application where you can view large images, zoom and pan them in the canvas element. Now I think it would be cool to scale the website with ctrl+"+" to have more space for viewing the image. As it is by default the canvas scales, too and you gain nothing.
You can use technique described in this article http://novemberborn.net/2007/12/javascriptpage-zoom-ff3-128.
The main idea is to place any two elements and set for the first element css value in pixels like top\left\width etc and for the second element percentage value. When you scale the page the percentage value stays unchanged, but the value in pixels changes depending on zoom factor.
Based on these changes you can calculate the scale factor and multiple it with canvas dimensions to scale it.
How to calculate scale factor you can find in the demo link from article in the script block.
Something like Zoomooz.js could work - http://janne.aukia.com/zoomooz/

Why doesn't translate works for the canvas in a div?

I have 2 canvas in a div. I tried to translate one of the canvas, but it didn't work.
http://jsfiddle.net/VkbV5/ shows the case where i commented off the translation line:
this.innerElement2Ctx.translate(100,100);
But when I include the line, the small square disappeared. Why? If you run this page in browser and inspect the innerElement2, you will see that it didn't move at all, but the small square disappeared.
For your information, I need 2 canvas, because I am planning to attach mouse event to innerElement2.
Translating a context adjusts where the 0,0 point is for future drawing commands; scaling a context adjusts how large items draw on the canvas; rotating a context adjusts the direction that items are drawn. None of these context transformations adjust the size or position of the canvas box itself.
Here's an example I made of adjusting canvas transformation so that drawing the same commands allows the user to zoom and pan around a canvas drawing:
http://phrogz.net/tmp/canvas_zoom_to_cursor.html
If you want to move the placement of a canvas within your HTML page, use simple CSS placement as you would with any other element, e.g. a <div>.
If you want complex 2D or 3D transformations you can use cutting edge features of CSS for this (as supported by modern browsers). For example, see:
https://developer.mozilla.org/en/CSS/transform#CSS_transform_functions

How does TheSixyOne.com proportionally stretch the image to full page?

I love the new http://thesixtyone.com design. I am wondering how do they proportionally stretch the image to fit the whole background? Are they using CSS/Javascript or other tricks?
Both CSS and Javascript are used.
It takes the greater of height or width, sets the matching image dimension to that, then calculates the ratio of original dimension to the new dimension, then applies that ratio to the opposing dimension.
For example. Say the original photo was 100x100. If your screen is 200x100; then it stretches the first dimension (200 is larger than 100) to fit. This is a 2:1 ratio, so it does the same streatch to the other dimension. The resulting image is actually 200x200.
Add a touch more code to keep the whole thing centered (so the off-screen portions of the lessor dimension are equal), and voila.
In my example, the image would be moved up 50, so that you see the middle 100 (the screen size) of the picture that has been stretched to 200.
The image is actually a DIV tag with the background image property set.
Not sure what library they'e using but in their javascript source I did a search for "resize" and found:
Event.observe(window,"resize",t61.background.sync_size);
Which looks like they're attaching an event handler to window.onresize.

Categories

Resources