[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1093
  • Last Modified:

Canvas script works in Firefox and IE but not Chrome

The following canvas script works in Firefox and IE but not Chrome. In Chrome, no lines are drawn.  Any ideas why it doesn't work in Chrome?
/* © 2009 ROBO Design
 * http://www.robodesign.ro
 */

// Keep everything in anonymous function, called on window load.
if(window.addEventListener) {
window.addEventListener('load', function () {
  var canvas, context, tool;

  function init () {
    // Find the canvas element.
    canvas = document.getElementById('imageView');
    if (!canvas) {
      alert('Error: I cannot find the canvas element!');
      return;
    }

    if (!canvas.getContext) {
      alert('Error: no canvas.getContext!');
      return;
    }

    // Get the 2D canvas context.
    context = canvas.getContext('2d');
    if (!context) {
      alert('Error: failed to getContext!');
      return;
    }
	
	var img=new Image();
	img.onload = function(){
	context.drawImage(img,0,0);
	};
	img.src="PainDiagram.png";
	
    // Pencil tool instance.
    tool = new tool_pencil();

    // Attach the mousedown, mousemove and mouseup event listeners.
    canvas.addEventListener('mousedown', ev_canvas, false);
    canvas.addEventListener('mousemove', ev_canvas, false);
    canvas.addEventListener('mouseup',   ev_canvas, false);
  }

  // This painting tool works like a drawing pencil which tracks the mouse 
  // movements.
  function tool_pencil () {
    var tool = this;
    this.started = false;

    // This is called when you start holding down the mouse button.
    // This starts the pencil drawing.
    this.mousedown = function (ev) {
		context.beginPath();
		context.lineWidth = 5;
		context.lineCap = "round";
		context.globalAlpha=0.01;
		context.shadowColor="red";
		context.shadowBlur=10;
		context.strokeStyle = "red"; // line color
        context.moveTo(ev._x, ev._y);
        tool.started = true;
    };

    // This function is called every time you move the mouse. Obviously, it only 
    // draws if the tool.started state is set to true (when you are holding down 
    // the mouse button).
    this.mousemove = function (ev) {
      if (tool.started) {
	    //var p = context.getImageData(ev._x, ev._y, 1, 1).data; 
        //if(p[0]==255 && p[1]==204 && p[2]==153){
	        context.moveTo(ev._x, ev._y);
	        context.lineTo(ev._x, ev._y);
	        context.stroke();
		//}
      }
    };

    // This is called when you release the mouse button.
    this.mouseup = function (ev) {
      if (tool.started) {
        tool.mousemove(ev);
        tool.started = false;
      }
    };
  }

  // The general-purpose event handler. This function just determines the mouse 
  // position relative to the canvas element.
  function ev_canvas (ev) {
    if (ev.layerX || ev.layerX == 0) { // Firefox
      ev._x = ev.layerX;
      ev._y = ev.layerY;
    } else if (ev.offsetX || ev.offsetX == 0) { // Opera
      ev._x = ev.offsetX;
      ev._y = ev.offsetY;
    }

    // Call the event handler of the tool.
    var func = tool[ev.type];
    if (func) {
      func(ev);
    }
  }

  init();

}, false); }

// vim:set spell spl=en fo=wan1croql tw=80 ts=2 sw=2 sts=2 sta et ai cin fenc=utf-8 ff=unix:

Open in new window

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Paint</title>
    <style type="text/css"><!--
      #container { position: relative; }
      #imageView { border: 1px solid #000; }
    --></style>
  </head>
  <body BGCOLOR="#CCFFFF"> 
  
    <div id="container">
      <canvas id="imageView" width="700" height="643" margin: 0 auto>
        <p>Unfortunately, your browser is currently unsupported by our web 
        application.  We are sorry for the inconvenience. Please use one of the 
        supported browsers listed below, or draw the image you want using an 
        offline tool.</p>
        <p>Supported browsers: <a href="http://www.opera.com">Opera</a>, <a 
          href="http://www.mozilla.com">Firefox</a>, <a 
          href="http://www.apple.com/safari">Safari</a>, and <a 
          href="http://www.konqueror.org">Konqueror</a>.</p>
      </canvas>
    </div>

    <script type="text/javascript" 
    src="example1.js"></script>
  </body>
</html>

Open in new window

0
thenelson
Asked:
thenelson
  • 7
  • 6
  • 4
1 Solution
 
Michel PlungjanIT ExpertCommented:
Please look in the console

I get

Failed to load resource
file:///C:/temp/PainDiagram.png

but the next error is more likely the problem:

event.layerX and event.layerY are broken and deprecated in WebKit. They will be removed from the engine in the near future.

So I got rid of the error message by reversing the test here

  function ev_canvas (ev) {
    if (ev.offsetX || ev.offsetX == 0) { // Opera and WebKit
      ev._x = ev.offsetX;
      ev._y = ev.offsetY;
    }  
    else if (ev.layerX || ev.layerX == 0) { // Firefox
      ev._x = ev.layerX;
      ev._y = ev.layerY;
    } 

Open in new window


It did not help, though...
0
 
thenelsonAuthor Commented:
Thanks for that suggestion. I applied the change but as you mentioned, it still does not work in Google. To avoid the Failed to load resource  problem, here is the temporally link to the project while I am building it: www.barnwellmd.com/paint.html
0
 
Michel PlungjanIT ExpertCommented:
I am investigating.

I found the resource here at EE too :)
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
Tom BeckCommented:
On a side note, remove line 72, context.moveTo(ev._x, ev._y);, from your script and the drawn line will be much smoother.
0
 
thenelsonAuthor Commented:
Removing context.moveTo(ev._x, ev._y); results in some jagged jumps when the mouse is moved quickly. But thanks for the suggestion:
0
 
Tom BeckCommented:
The opposite is true. With context.moveTo(ev._x, ev._y);  in the script, the moveTo method is run unnecessarily for every pixel traversed causing a delay in processing. There's no need to re-position the stroke starting point in the mousemove event, it's already been set on mousedown. The result is that when you move the cursor quickly you get dots spaced far apart. The lineTo method is all you need to call as it will draw a continuous string of dots from one point to the next to form a smooth line. Be sure to refresh everything between tests.
0
 
thenelsonAuthor Commented:
The theory makes sense but it doesn't seem to work out that way. You can try it yourself. www.barnwellmd.com/paint2  has the line context.moveTo(ev._x, ev._y);  remarked out. http://www.barnwellmd.com/paint does not.
0
 
Tom BeckCommented:
Look again.

http://www.barnwellmd.com/paint has example1.js in which moveTo is not commented out. The drawn line is choppy.

http://www.barnwellmd.com/paint2 has example2.js in which moveTo is commented out. The drawn line is smooth.
0
 
thenelsonAuthor Commented:
I don't know why we are getting different results.  l am using Firefox 10.0.2 on a tablet computer running Win 7.  I am using a pen with the tablet.  On the two screen print I am moving my penup and down approximately between the two green lines as I move it to the right.  
paint (with moveto)paint (with moveto)
paint2 (without moveto)paint2 (without moveto)
0
 
Tom BeckCommented:
In that case, we are talking about two different things. moveTo
I'm using Firefox 9.0.1 on Vista. You are moving your pen up and down in a small area. I am sweeping the mouse quickly across the image. Why you get red lines in both cases and I get black for a pen color on one test site is a mystery to me. Leaving moveTo in may be desirable for this project. It's reasonable to anticipate that users will want to draw lines in small, concentrated areas rather than drawing in quick sweeping motions across the page. I think you have bigger problems to overcome than this (like cross browser compatibility). I should not have brought it up as it is unrelated to this question.
0
 
Michel PlungjanIT ExpertCommented:
I was sure the second example was on purpose since it really gives a good idea of intensity.
I'm still investigating chrome
0
 
Michel PlungjanIT ExpertCommented:
http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-moveto

This works for me identically in Chrome and Fx on Windows

I commented out BOTH moveTo and it works very well in my opinion

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Paint</title>
    <style type="text/css"><!--
      #container { position: relative; }
      #imageView { border: 1px solid #000; }
    --></style>
  </head>
  <body BGCOLOR="#CCFFFF"> 
  
    <div id="container">
      <canvas id="imageView" width="700" height="643" margin: 0 auto>
        <p>Unfortunately, your browser is currently unsupported by our web 
        application.  We are sorry for the inconvenience. Please use one of the 
        supported browsers listed below, or draw the image you want using an 
        offline tool.</p>
        <p>Supported browsers: <a href="http://www.opera.com">Opera</a>, <a 
          href="http://www.mozilla.com">Firefox</a>, <a 
          href="http://www.apple.com/safari">Safari</a>, and <a 
          href="http://www.konqueror.org">Konqueror</a>.</p>
      </canvas>
    </div>

    <script type="text/javascript">
/* © 2009 ROBO Design
 * http://www.robodesign.ro
 */

// Keep everything in anonymous function, called on window load.
if(window.addEventListener) {
window.addEventListener('load', function () {
  var canvas, context, tool;

  function init () {
    // Find the canvas element.
    canvas = document.getElementById('imageView');
    if (!canvas) {
      alert('Error: I cannot find the canvas element!');
      return;
    }

    if (!canvas.getContext) {
      alert('Error: no canvas.getContext!');
      return;
    }

    // Get the 2D canvas context.
    context = canvas.getContext('2d');
    if (!context) {
      alert('Error: failed to getContext!');
      return;
    }
	
	var img=new Image();
	img.onload = function(){
	context.drawImage(img,0,0);
	};
	img.src="PainDiagram.png";
	
    // Pencil tool instance.
    tool = new tool_pencil();

    // Attach the mousedown, mousemove and mouseup event listeners.
    canvas.addEventListener('mousedown', ev_canvas, false);
    canvas.addEventListener('mousemove', ev_canvas, false);
    canvas.addEventListener('mouseup',   ev_canvas, false);
  }

  // This painting tool works like a drawing pencil which tracks the mouse 
  // movements.
  function tool_pencil () {
    var tool = this;
    this.started = false;

    // This is called when you start holding down the mouse button.
    // This starts the pencil drawing.
    this.mousedown = function (ev) {
		context.beginPath();
		context.lineWidth = 5;
		context.lineCap = "round";
		context.globalAlpha=0.01;
		context.shadowColor="red";
		context.shadowBlur=10;
		context.strokeStyle = "red"; // line color
//        context.moveTo(ev._x, ev._y);
        tool.started = true;
    };

    // This function is called every time you move the mouse. Obviously, it only 
    // draws if the tool.started state is set to true (when you are holding down 
    // the mouse button).
    this.mousemove = function (ev) {
      if (tool.started) {
	    //var p = context.getImageData(ev._x, ev._y, 1, 1).data; 
        //if(p[0]==255 && p[1]==204 && p[2]==153){
//	        context.moveTo(ev._x, ev._y);
	        context.lineTo(ev._x, ev._y);
	        context.stroke();
		//}
      }
    };

    // This is called when you release the mouse button.
    this.mouseup = function (ev) {
      if (tool.started) {
        tool.mousemove(ev);
        tool.started = false;
      }
    };
  }

  // The general-purpose event handler. This function just determines the mouse 
  // position relative to the canvas element.
  
 
  function ev_canvas (ev) {
    if (ev.offsetX || ev.offsetX == 0) { // Opera and WebKit
      ev._x = ev.offsetX;
      ev._y = ev.offsetY;
    }  
    else if (ev.layerX || ev.layerX == 0) { // Firefox
      ev._x = ev.layerX;
      ev._y = ev.layerY;
    } 

    // Call the event handler of the tool.
    var func = tool[ev.type];
    if (func) {
      func(ev);
    }
  }

  init();

}, false); }

// vim:set spell spl=en fo=wan1croql tw=80 ts=2 sw=2 sts=2 sta et ai cin fenc=utf-8 ff=unix:
                                      
    </script>
  </body>
</html>
                                  

Open in new window

0
 
thenelsonAuthor Commented:
Very nice!   What changes did you make? Your version works in FF, Chrome and IE 9. I switched to a different routine  (www.barnwellmd.com/Paindiagram/PainDiagram) that works in FF & Chrome but not IE. With your version and the moveTo remmed out, the jaggedness is pronounced in FF but not so much in Chrome or IE. I doubt the jaggedness would be much of a problem.using a mouse instead of a pen since I can move the pen faster than the mouse.
0
 
Michel PlungjanIT ExpertCommented:
I have NO jaggies in fx 10 at all
0
 
thenelsonAuthor Commented:
I found the answer to  the problem that the code was not working in IE9: I was using a Doctype specifying Html 4
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01
    Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
instead of Html 5
     <!DOCTYPE HTML>

So the webpage is working in the latest versions of FF, IE and Chrome. Although I don't know what I did to get it working in Chrome.
0
 
Michel PlungjanIT ExpertCommented:
I commented out
//              context.moveTo(ev._x, ev._y);

that did it for me in Chrome
0
 
thenelsonAuthor Commented:
I have the script now working FF, IE and Chrome. Thanks for your help.
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 7
  • 6
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now