SitePoint Sponsor

User Tag List

Results 1 to 12 of 12
  1. #1
    SitePoint Member
    Join Date
    Jul 2013
    Posts
    18
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Scaling JavaScript animation without blurring

    Hi,

    With help some time ago, an AS3 animation (for an eLearning lesson) was ported to JS. Because of the scaling, it displays in browsers as blurry. I think the problem is that the canvas drawing is using 1X1 rectangles, when they should be 8X8. Also, there are mis-matches between canvas size in the JS, CSS, index files. Canvas should be 640X640.

    I have tried to fix this but with no success and would appreciate any help getting it sized correctly and displaying clearly.

    There are 3 small files (index.html, style.css and src.js) and the link is: http://elearningprojects.com/websample1/index.html

    Thank you for any help.

    Kind Regards,
    writer1

  2. #2
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,717
    Mentioned
    103 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by writer1 View Post
    Hi,

    With help some time ago, an AS3 animation (for an eLearning lesson) was ported to JS. Because of the scaling, it displays in browsers as blurry. I think the problem is that the canvas drawing is using 1X1 rectangles, when they should be 8X8. Also, there are mis-matches between canvas size in the JS, CSS, index files. Canvas should be 640X640
    There's a new CSS property called image-rendering that might solve the problem for you.

    Code css:
    image-rendering: optimize-contrast;

    It's designed to help fix such pixel-rendering issues.

    So far, the most compatible use that I've seen of it is with this:

    Code css:
    canvas {
        image-rendering: optimizeSpeed;             // Older versions of FF
        image-rendering: -moz-crisp-edges;          // FF 6.0+
        image-rendering: -webkit-optimize-contrast; // Webkit
                                                    //  (Safari now, Chrome soon)
        image-rendering: -o-crisp-edges;            // OS X & Windows Opera (12.02+)
        image-rendering: optimize-contrast;         // Possible future browsers.
        -ms-interpolation-mode: nearest-neighbor;   // IE
    }
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  3. #3
    SitePoint Member
    Join Date
    Jul 2013
    Posts
    18
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi Paul,

    Thank you for your reply. I had found this information earlier and tried it without success.

    I suspect that the problem is that the script is using scaling which causes blurring. (I am a beginner and don't fully understand the script. A few years ago, someone had helped with the script-no longer available to help). I think that it is trying to build the animation with 1X1 rectangles and then scale them up (8X) to the canvas size. Instead, I think that it would solve the scaling/blurring problem if it started with 8X8 rectangles. But, I don't know how to re-write this to accomplish the change. Also, the canvas size is different in 2 files (style.css and index.html) : 640X640 (correct size) in one and 80X80 in the other. Simply changing these has also not been successful in solving the problem. So, I'm stuck, need some additional help to get it working without blurring.

    Any help re-writing to avoid scaling, match up canvas sizes, would be appreciated.

    Kind Regards,

    writer1

  4. #4
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,717
    Mentioned
    103 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by writer1 View Post
    I suspect that the problem is that the script is using scaling which causes blurring.
    No - the problem in this case is that CSS is being used to stretch the canvas, so the web browser automatically interpolates the image which blurs it.
    Do not use CSS to make the canvas bigger. Using CSS to make the width and height bigger is directly causing your problem.

    So far as a solution goes, the canvas has a scale command.
    Here are a couple of examples that demonstrate how the pixel art can be scaled up without smoothing by applying a custom scale command to the canvas:

    http://jsfiddle.net/wa95p/
    http://jsfiddle.net/saviski/pGs4f/12/
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  5. #5
    SitePoint Member
    Join Date
    Jul 2013
    Posts
    18
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi Paul,

    Thank you for this explanation which narrows down the problem.

    I took a look at these examples. But, I'm not sure how to fix the CSS. Currently, it is:

    canvas{
    border:1px solid black;
    height:640px;
    width:640px;
    }
    This seems to be specifying the width and height? So, I'm not sure what to change?

    writer1

  6. #6
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,717
    Mentioned
    103 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by writer1 View Post
    I'm not sure how to fix the CSS.

    This seems to be specifying the width and height? So, I'm not sure what to change?
    Remove the bloody width and height parts from the CSS. They are badly scaling up the canvas, which is causing your unwanted blurry look.
    Instead of using CSS, use a larger canvas in the HTML, and from the JavaScript scale up the context that JavaScript uses on the canvas.

    I'm going to bed - good luck
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  7. #7
    SitePoint Member
    Join Date
    Jul 2013
    Posts
    18
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks, Paul.

    Apologies for my not understanding fully. I will try to get it right.

    Kind Regards,

    writer1

  8. #8
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,717
    Mentioned
    103 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by writer1 View Post
    Apologies for my not understanding fully. I will try to get it right.
    I looked at a few possible solutions, and found that even when using a correct technique, that it leaves out browsers such as Internet Explorer:

    Code javascript:
    ctx.webkitImageSmoothingEnabled = false;
    ctx.mozImageSmoothingEnabled = false;
    ctx.scale(8, 8);

    See demo at http://jsfiddle.net/saviski/pGs4f/12/

    So instead of doing that type of thing, it's time to do it the old-fashioned way. I've put together a drawAtScale function instead, which also requires that a buffered work space is used, so that it can then be scaled to whatever size the target canvas is.

    Code javascript:
        function init() {
            buffer = document.createElement('canvas');
            buffer.width = 80;
            buffer.height = 80;
            bufferCtx = buffer.getContext("2d");
            canvas = document.querySelector("canvas");
            displayCtx = canvas.getContext("2d");
            ...
    }

    Code javascript:
    function drawAtScale() {
        var width = buffer.width,
            height = buffer.height,
            xScale = canvas.width / width,
            yScale = canvas.height / height,
            i,
            pixelDataSize = width * height;
        for (i = 0; i < pixelDataSize; i += 1) {
            displayCtx.fillStyle = "rgb(" + px.data[i * 4] + ", " + px.data[i * 4 + 1] + ", " + px.data[i * 4 + 2] + ")";
            displayCtx.fillRect((i % width) * xScale, (i / height | 0) * yScale, xScale, yScale);
        }
    }

    I've also reworked some of it to be clearer, and to allow you to easily change the buffer width and height from 80x80 to any other dimension you might wish to experiment with, or the canvas width and height in the HTML to anything you may desire.


    You can see it working in action at http://jsfiddle.net/pmw57/as4UR/
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  9. #9
    SitePoint Member
    Join Date
    Jul 2013
    Posts
    18
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi Paul,

    Spent the day at it, but not with such an excellent result as you provided above. Impressive!

    I tested in FF and IE, and it works in both on the desktop.

    When I uploaded it and tried it using Chrome on an Android device, got a blank screen. (Ugh)

    Also because it is constantly refreshing, when viewed in FF on an Android device, it stays at full screen even if pinched (it will get smaller while pinched and held, but once you stop pinching/touching the screen, it resumes its full screen display). So, I'll keep trying to dissect the script, see if I can apply any fixes for these, especially the full screen issue.

    Again, thank you very much for your help. Brilliant!

    Kind Regards,

    writer1

  10. #10
    SitePoint Member
    Join Date
    Jul 2013
    Posts
    18
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi,

    I've been researching online about cancelling full screen mode and found some script:

    Code:
    function cancelFullscreen() {
      if(document.cancelFullScreen) {
        document.cancelFullScreen();
      } else if(document.mozCancelFullScreen) {
        document.mozCancelFullScreen();
      } else if(document.webkitCancelFullScreen) {
        document.webkitCancelFullScreen();
      }
    }
    
    cancelFullscreen();
    Tried adding this to the JS, but so far when I view on a mobile FF browser, will not cancel full screen even with this script. I think the constant refreshing keeps causing the window to go to full screen?

    I'll keep trying to find a solution.

  11. #11
    SitePoint Member
    Join Date
    Jul 2013
    Posts
    18
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    OK, adding the following to the HTML seems to solve the full screen problem:

    HTML Code:
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
    Now, I need to figure out how to center the canvas in the middle of the screen on any device? It is currently displaying at 0,0.

    Any help appreciated.

    writer1

  12. #12
    SitePoint Member
    Join Date
    Jul 2013
    Posts
    18
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Resolved:

    Code:
    canvas{
        border:1px solid black;
    	position: absolute;
      	top: 50%;
      	left: 50%;
      	margin-left: -320px;
      	margin-top: -320px;
    }


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •