Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

CSS jQuery Basics (2014) Creating a Simple Drawing Application Perform: Part 5

Tobias Bothma
Tobias Bothma
5,814 Points

Added Responsive layout with Media Query but now the lines do not match up with the cursor position. Code Fix?

I added a responsive layout with CSS. I just need some help getting the JQuery to take into account a browser size change and line up the stroke with the cursor. When I size the browser down the stroke is offset to the left of the cursor.

Any thoughts?

This is the media query:

@media (min-width: 568px) and (max-width: 1200px) {

canvas { width: 85%; height: 600px; }

.controls {

min-height: 60px;
margin: 0 auto;
width: 95%;
border-radius: 5px;
overflow: hidden;
}

}

@media (min-width: 320px) and (max-width: 568px) {

canvas { width: 90%; height: 400px; }

.controls {

min-height: 60px;
margin: 0 auto;
width: 95%;
border-radius: 5px;
overflow: hidden;
}

}

Tobias Bothma MDN advises "The displayed size of the canvas can be changed using a stylesheet. The image is scaled during rendering to fit the styled size. If your renderings seem distorted, try specifying your width and height attributes explicitly in the <canvas> attributes, and not using CSS."

The code below is simplified from that used in Treehouse simple drawing application videos, modified to accommodate a canvas size that adjusts with the window.

In summary, whenever the window is resized ($(window).resize()), the new dimensions are used to recalculate the desired canvas dimensions (0.8 * window width/height) and set with .prop(). However, resetting the canvas width/height attributes (instead of by css) erases the image. Therefore, at the end of every draw event (.mouseup()), the image is copied (context.getImageData()) and stored in a global variable (imageData). Then, whenever the the canvas is resized, the drawing is restored using context.putImageData().

Note: I did this because I wanted to figure out how it COULD be done; I have no idea if this resembles how it SHOULD be done.

<!DOCTYPE html>
<html>
  <head>
    <title>Resizeable Drawing Canvas</title>
    <style>
      body {
        background: #384047;
      }
      canvas {
        background-color: #ddd;
        display: block;
        margin: 50px auto 10px;
        border-radius: 5px;
      }
    </style>
  </head>
  <body>
    <canvas></canvas>
    <script src="http://code.jquery.com/jquery-1.11.0.min.js" type="text/javascript" charset="utf-8"></script>
    <script>
      var color = "#000";
      var $canvas = $("canvas");
      var context = $canvas[0].getContext("2d");
      var lastEvent;
      var mouseDown = false;

      //added for resizing
      var canvasRelativeSize = 0.8;
      var imageData = copyCanvas();

      //On mouse events on the canvas
      $canvas.mousedown(function(e) {
        lastEvent = e;
        mouseDown = true;
      }).mousemove(function(e) {
        //Draw lines
        if(mouseDown) {
          context.beginPath();
          context.moveTo(lastEvent.offsetX, lastEvent.offsetY);
          context.lineTo(e.offsetX, e.offsetY);
          context.strokeStyle = color;
          context.stroke();
          lastEvent = e;
        }
      }).mouseup(function() {
        mouseDown = false;
        //record image data
        imageData = copyCanvas();
      }).mouseleave(function() {
        if (mouseDown) {
          $canvas.mouseup();
        }
      });

      function copyCanvas() {
        return context.getImageData(0, 0, 
                                    $canvas[0].offsetWidth,
                                    $canvas[0].offsetHeight);
        /* NOTE: Only the visible portion of the drawing is copied, 
        so if you draw on a wide canvas, then shrink the window 
        so part of the drawing is hidden, then draw some more, 
        the hidden section is lost. */
      }

      //Respond to changes in window size
      $(window).resize(function(event) {
        //reset canvas size
        $canvas.prop("width", "" + window.innerWidth * canvasRelativeSize); 
        $canvas.prop("height", "" + window.innerHeight * canvasRelativeSize); 
        //replace image data
        context.putImageData(imageData, 0, 0);
      });

      //call resize() manually to set initial canvas size when page first loads
      $(window).resize();
    </script>
  </body>
</html>