EzDevInfo.com

html5-canvas interview questions

Top html5-canvas frequently asked interview questions

How can I animate the drawing of text on a web page?

I want to have a web page which has one centered word.

I want this word to be drawn with an animation, such that the page "writes" the word out the same way that we would, i.e. it starts at one point and draws lines and curves over time such that the end result is a glyph.

I do not care if this is done with <canvas> or the DOM, and I don't care whether it's done with JavaScript or CSS. The absence of jQuery would be nice, but not required.

How can I do this? I've searched exhaustively with no luck.


Source: (StackOverflow)

HTML5 Canvas Resize (Downscale) Image High Quality?

I use html5 canvas elements to resize images im my browser. It turns out that the quality is very low. I found this: Disable Interpolation when Scaling a <canvas> but it does not help to increase the quality.

Below is my css and js code as well as the image scalled with Photoshop and scaled in the canvas API.

What do I have to do to get optimal quality when scaling an image in the browser?

Note: I want to scale down a large image to a small one, modify color in a canvas and send the result from the canvas to the server.

CSS:

canvas, img {
    image-rendering: optimizeQuality;
    image-rendering: -moz-crisp-edges;
    image-rendering: -webkit-optimize-contrast;
    image-rendering: optimize-contrast;
    -ms-interpolation-mode: nearest-neighbor;
}

JS:

var $img = $('<img>');
var $originalCanvas = $('<canvas>');
$img.load(function() {


   var originalContext = $originalCanvas[0].getContext('2d');   
   originalContext.imageSmoothingEnabled = false;
   originalContext.webkitImageSmoothingEnabled = false;
   originalContext.mozImageSmoothingEnabled = false;
   originalContext.drawImage(this, 0, 0, 379, 500);
});

The image resized with photoshop:

enter image description here

The image resized on canvas:

enter image description here

Edit:

I tried to make downscaling in more than one steps as proposed in:

Resizing an image in an HTML5 canvas and Html5 canvas drawImage: how to apply antialiasing

This is the function I have used:

function resizeCanvasImage(img, canvas, maxWidth, maxHeight) {
    var imgWidth = img.width, 
        imgHeight = img.height;

    var ratio = 1, ratio1 = 1, ratio2 = 1;
    ratio1 = maxWidth / imgWidth;
    ratio2 = maxHeight / imgHeight;

    // Use the smallest ratio that the image best fit into the maxWidth x maxHeight box.
    if (ratio1 < ratio2) {
        ratio = ratio1;
    }
    else {
        ratio = ratio2;
    }

    var canvasContext = canvas.getContext("2d");
    var canvasCopy = document.createElement("canvas");
    var copyContext = canvasCopy.getContext("2d");
    var canvasCopy2 = document.createElement("canvas");
    var copyContext2 = canvasCopy2.getContext("2d");
    canvasCopy.width = imgWidth;
    canvasCopy.height = imgHeight;  
    copyContext.drawImage(img, 0, 0);

    // init
    canvasCopy2.width = imgWidth;
    canvasCopy2.height = imgHeight;        
    copyContext2.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvasCopy2.width, canvasCopy2.height);


    var rounds = 2;
    var roundRatio = ratio * rounds;
    for (var i = 1; i <= rounds; i++) {
        console.log("Step: "+i);

        // tmp
        canvasCopy.width = imgWidth * roundRatio / i;
        canvasCopy.height = imgHeight * roundRatio / i;

        copyContext.drawImage(canvasCopy2, 0, 0, canvasCopy2.width, canvasCopy2.height, 0, 0, canvasCopy.width, canvasCopy.height);

        // copy back
        canvasCopy2.width = imgWidth * roundRatio / i;
        canvasCopy2.height = imgHeight * roundRatio / i;
        copyContext2.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvasCopy2.width, canvasCopy2.height);

    } // end for


    // copy back to canvas
    canvas.width = imgWidth * roundRatio / rounds;
    canvas.height = imgHeight * roundRatio / rounds;
    canvasContext.drawImage(canvasCopy2, 0, 0, canvasCopy2.width, canvasCopy2.height, 0, 0, canvas.width, canvas.height);


}

Here is the result if I use a 2 step down sizing:

enter image description here

Here is the result if I use a 3 step down sizing:

enter image description here

Here is the result if I use a 4 step down sizing:

enter image description here

Here is the result if I use a 20 step down sizing:

enter image description here

Note: It turns out that from 1 step to 2 steps there is a large improvement in image quality but the more steps you add to the process the more fuzzy the image becomes.

Is there a way to solve the problem that the image gets more fuzzy the more steps you add?

Edit 2013-10-04: I tried the algorithm of GameAlchemist. Here is the result compared to Photoshop.

PhotoShop Image:

PhotoShop Image

GameAlchemist's Algorithm:

GameAlchemist's Algorithm


Source: (StackOverflow)

Advertisements

How to free up the memory in JavaScript

I'm working with canvas and its ImageData object which contains a huge amount of data (millions of integers). So working with a few arrays already takes a lot of memory (up to 300MB). Is there a way to free up the memory of some array when it's unnecessary? I'm trying to assign undefined to that variable. Is it right?


Source: (StackOverflow)

Working with Canvas and AngularJS

I am taking up a task to re-write the following flash app in HTML5:

http://www.docircuits.com/circuit-editor

Given the complexity of the app and my RnD so far, I have identified AngularJS as the preferred MVC framework for the implementation. The app has various parts such as panels, menus, properties, charts etc, all of which I believe can be easily implemented in AngularJS.

The key problem however is the component design and interaction (things like, drag/drop, move, wire handling etc.), which needs to be canvas based, as I have been able to export all the vector graphics from flash using CreateJS toolkit (http://www.adobe.com/in/products/flash/flash-to-html5.html) into a canvas lib and not to a svg.

The problem which I am facing is that there is no clear way to communicate between the "individual objects inside a canvas" and angularJS. I have looked at the following examples, but almost all of them work on the canvas object, and not about handling individual components inside canvas:

AngularJS Binding to WebGL / Canvas

Is there already a canvas drawing directive for AngularJS out there?

I am kind of stuck here, and not sure what to do. Would really appreciate a some comments on:

  • Whether angular is the right choice? (I still think most other things will be done quite easily in Angular....if I can only handle the canvas stuff.....but being a newbie my knowledge is limited)

  • Should I try implementing the canvas part in another library (such as Fabric.js, kinect.js, Easel.js) and integrate it with Angular (which again seems too big a tasks for now)

  • If none of the above, what other framework should I switch to, which can easily handle canvas as well as other functionality like panels, menus, charts etc. with ease.

Regards,

Kapil


Source: (StackOverflow)

how to draw grid using html5 and (canvas or svg)

I want to draw a grid as shown in image but I totally don't have idea that where should I begin. Should I use SVG or should I use Canvas with HTML5 and how to draw it.
Please guide on this. I want this grid to draw rectangle, circle or other diagrams on it and I will calculate area of that diagram like area of square.

enter image description here


Source: (StackOverflow)

Canvas Rotating Star Field

I'm taking the following approach to animate a star field across the screen, but I'm stuck for the next part.

JS

var c = document.getElementById('stars'),
    ctx = c.getContext("2d"),
    t = 0; // time

c.width = 300;
c.height = 300;

var w = c.width,
    h = c.height,
    z = c.height,
    v = Math.PI; // angle of vision

(function animate() {

    Math.seedrandom('bg');
    ctx.globalAlpha = 1;

    for (var i = 0; i <= 100; i++) {

        var x = Math.floor(Math.random() * w), // pos x
            y = Math.floor(Math.random() * h), // pos y
            r = Math.random()*2 + 1, // radius
            a = Math.random()*0.5 + 0.5, // alpha

            // linear
            d = (r*a),       // depth
            p = t*d;         // pixels per t

        x = x - p;       // movement
        x = x - w * Math.floor(x / w); // go around when x < 0

        (function draw(x,y) {
            var gradient = ctx.createRadialGradient(x, y, 0, x + r, y + r, r * 2);
            gradient.addColorStop(0, 'rgba(255, 255, 255, ' + a + ')');
            gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');

            ctx.beginPath();
            ctx.arc(x, y, r, 0, 2*Math.PI);
            ctx.fillStyle = gradient;
            ctx.fill();

            return draw;

        })(x, y);

    }

    ctx.restore();
    t += 1;

    requestAnimationFrame(function() {
        ctx.clearRect(0, 0, c.width, c.height);
        animate();
    });
})();

HTML

<canvas id="stars"></canvas>

CSS

canvas {
    background: black;
}

JSFiddle

What it does right now is animate each star with a delta X that considers the opacity and size of the star, so the smallest ones appear to move slower.

Use p = t; to have all the stars moving at the same speed.

QUESTION

I'm looking for a clearly defined model where the velocities give the illusion of the stars rotating around the expectator, defined in terms of the center of the rotation cX, cY, and the angle of vision v which is what fraction of 2π can be seen (if the center of the circle is not the center of the screen, the radius should be at least the largest portion). I'm struggling to find a way that applies this cosine to the speed of star movements, even for a centered circle with a rotation of π.

These diagrams might further explain what I'm after:

Centered circle:

center of vision in x,y

Non-centered:

shifted center

Different angle of vision:

different angle of vision

I'm really lost as to how to move forwards. I already stretched myself a bit to get here. Can you please help me with some first steps?

Thanks


UPDATE

I have made some progress with this code:

        // linear
        d = (r*a)*z,   // depth
        v = (2*Math.PI)/w,
        p = Math.floor( d * Math.cos( t * v ) );     // pixels per t

    x = x + p;       // movement
    x = x - w * Math.floor(x / w); // go around when x < 0

JSFiddle

Where p is the x coordinate of a particle in uniform circular motion and v is the angular velocity, but this generates a pendulum effect. I am not sure how to change these equations to create the illusion that the observer is turning instead.


UPDATE 2:

Almost there. One user at the ##Math freenode channel was kind enough to suggest the following calculation:

        // linear
        d = (r*a),       // depth
        p = t*d;         // pixels per t

    x = x - p;       // movement
    x = x - w * Math.floor(x / w); // go around when x < 0

    x = (x / w) - 0.5;
    y = (y / h) - 0.5;

    y /= Math.cos(x);

    x = (x + 0.5) * w;
    y = (y + 0.5) * h;

JSFiddle

This achieves the effect visually, but does not follow a clearly defined model in terms of the variables (it just "hacks" the effect) so I cannot see a straightforward way to do different implementations (change the center, angle of vision). The real model might be very similar to this one.


UPDATE 3

Following from Iftah's response, I was able to use Sylvester to apply a rotation matrix to the stars, which need to be saved in an array first. Also each star's z coordinate is now determined and the radius r and opacity a are derived from it instead. The code is substantially different and lenghthier so I am not posting it, but it might be a step in the right direction. I cannot get this to rotate continuously yet. Using matrix operations on each frame seems costly in terms of performance.

JSFiddle


Source: (StackOverflow)

Cropping images in the browser BEFORE the upload [closed]

Many libraries I have found, like Jcrop, do not actually do the cropping, it only creates an image cropping UI. It then depends on the server doing the actual cropping.

How can I make the image cropping client-side by using some HTML5 feature without using any server-side code.

If yes, are there some examples or hints?


Source: (StackOverflow)

Canvas drawImage scaling

I'm trying to scale an image proportionately to the canvas. I'm able to scale it with fixed width and height as so:

context.drawImage(imageObj, 0, 0, 100, 100)

But I only want to resize the width and have the height resize proportionately. Something like the following:

context.drawImage(imageObj, 0, 0, 100, auto)

I've looked everywhere I can think of and haven't seen if this is possible.


Source: (StackOverflow)

html5 canvas general performance tips

i am developing a game for the html5-canvas platform while mainly targeting mobile devices. the canvas is resized to the biggest available resolution, so that it almost makes a fullscreen game.

on an ipad that would be a 1024x786 canvas. at a resolution like this i notice a significant drop in framerate. on smaller resolution like 480x320 on iphone the game runs smooth! so i guess this is because the device is fillrate limited.

but anyhow i would like to optimize as much as possible.

so i would be very grateful if you could post any general performance tips that you have, when it comes to html5-canvas development.


Source: (StackOverflow)

Three.js detect webgl support and fallback to regular canvas

Can anyone who has used three.js tell me if its possible to detect webgl support, and, if not present, fallback to a standard Canvas render?


Source: (StackOverflow)

getImageData() error The canvas has been tainted by cross-origin data

My code is working very well on my localhost but it is not working on the site.

I got this error from the console, for this line .getImageData(x,y,1,1).data:

Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data. 

part of my code:

jQuery.Event.prototype.rgb=function(){
        var x =  this.offsetX || (this.pageX - $(this.target).offset().left),y =  this.offsetY || (this.pageY - $(this.target).offset().top);
        if (this.target.nodeName!=="CANVAS")return null;
        return this.target.getContext('2d').getImageData(x,y,1,1).data;
    }

Note: my image url (src) is from a subdomain url


Source: (StackOverflow)

Dynamically generated favicon

Would it be possible using only JavaScript and HTML to dynamically generate a favicon, using the current page's favicon as a background, and a random number in the foreground?

For example, lets say the current favicon looks similar to this:

======================
====XXXXXXXXXXXXXX====
====X=================
====X=================
====X=====XXXXXXXX====
====X============X====
====X============X====
====XXXXXXXXXXXXXX====
======================

If possible, how would I get it to look something similar to this using only JavaScript and HTML:

======================
====XXXXXXXXXXXXXX====
====X=================
====X=================
====X=====XXXXXXXX====
====X=========--111--=
====X=========--1-1--=
====XXXXXXXXXX----1--=
==============--1111-=

map:
= : white background
x : Original Favicon image
- : Red generated image with a number
1 : White text

Ideas:

  • Canvas?
  • Data Uri's?

Source: (StackOverflow)

Changing three.js background to transparent or other color

I've been trying to change what seems to be the default background color of my canvas from black to transparent / any other color - but no luck.

My HTML:

<canvas id="canvasColor">

My CSS:

<style type="text/css">
#canvasColor {
 z-index: 998;
opacity:1;
background: red;
}
</style>

As you can see in the following online example I have some animation appended to the canvas, so cant just do a opacity: 0; on the id.

Live preview: http://devsgs.com/preview/test/particle/

Any ideas how to overwrite the default black?


Source: (StackOverflow)

event.offsetX in Firefox

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script language="javascript">
function main(){
    var canvas = document.getElementById("canvas");
    canvas.addEventListener("mousemove", function(e){
        if (!e) e = window.event;
        var ctx = canvas.getContext("2d");

        var x = e.offsetX;
        var y = e.offsetY;

        ctx.fillRect(x, y, 1, 1);
    });
}
</script>
</head>
<body onload="main();">
<div style="width: 800px; height: 600px; -webkit-transform: scale(0.75,0.75); -moz-transform: scale(0.75,0.75)">
    <canvas id="canvas" width="400px" height="400px" style="background-color: #cccccc;"></canvas>
</div>
</body>
</html>

Please consider the above quick and dirty example. Please notice that my canvas in contained by a div having a scale transform applied. The above code works perfectly on any webkit based browser. While moving the mouse it draws points on the canvas. Unfortunately it doesn't in Firefox as its event model does not support the offsetX / Y properties. How can I transform mouse coordinates from (perhaps) event.clientX (which is supported in firefox too) into canvas relative coordinates taking into account canvas position, transform etc? Thanks, Luca.


Source: (StackOverflow)

JS Client-Side Exif Orientation: Rotate and Mirror JPEG Images

Digital camera photos are often saved as JPEG with an EXIF "orientation" tag. To display correctly, images need to be rotated/mirrored depending on which orientation is set, but browsers ignore this information rendering the image. Even in large commerical web apps, support for EXIF orientation can be spotty 1. The same source also provides a nice summary of the 8 different orientations a JPEG can have:

Summary of EXIF Orientations

Sample images are available at 4.

The question is how to rotate/mirror the image on the client side so that it displays correctly and can be further processed if necessary?

There are JS libraries available to parse EXIF data, including the orientation attribute 2. Flickr noted possible performance problem when parsing large images, requiring use of webworkers 3.

Console tools can correctly re-orient the images 5. A PHP script solving the problem is available at 6


Source: (StackOverflow)