Solved

Canvas script works in Firefox and IE but not Chrome

Posted on 2012-03-13
17
1,047 Views
Last Modified: 2013-11-19
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
Comment
Question by:thenelson
  • 7
  • 6
  • 4
17 Comments
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 37718594
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
 
LVL 39

Author Comment

by:thenelson
ID: 37719707
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
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 37719979
I am investigating.

I found the resource here at EE too :)
0
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

 
LVL 38

Expert Comment

by:Tom Beck
ID: 37722363
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
 
LVL 39

Author Comment

by:thenelson
ID: 37722495
Removing context.moveTo(ev._x, ev._y); results in some jagged jumps when the mouse is moved quickly. But thanks for the suggestion:
0
 
LVL 38

Expert Comment

by:Tom Beck
ID: 37722578
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
 
LVL 39

Author Comment

by:thenelson
ID: 37723305
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
 
LVL 38

Expert Comment

by:Tom Beck
ID: 37723379
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
 
LVL 39

Author Comment

by:thenelson
ID: 37723473
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
 
LVL 38

Expert Comment

by:Tom Beck
ID: 37724469
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
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 37725788
I was sure the second example was on purpose since it really gives a good idea of intensity.
I'm still investigating chrome
0
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 37728229
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
 
LVL 39

Author Comment

by:thenelson
ID: 37730250
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
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 37730556
I have NO jaggies in fx 10 at all
0
 
LVL 39

Author Comment

by:thenelson
ID: 37732434
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
 
LVL 75

Accepted Solution

by:
Michel Plungjan earned 500 total points
ID: 37732691
I commented out
//              context.moveTo(ev._x, ev._y);

that did it for me in Chrome
0
 
LVL 39

Author Closing Comment

by:thenelson
ID: 37732831
I have the script now working FF, IE and Chrome. Thanks for your help.
0

Featured Post

Problems using Powershell and Active Directory?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many programs have tried to outwit PowerPoint in terms of technology and skill. These programs, however, still lack several characteristics that PowerPoint has possessed from the start. Here's why PowerPoint replacements won't entirely work for desi…
The article shows the basic steps of integrating an HTML theme template into an ASP.NET MVC project
The viewer will learn the benefit of using external CSS files and the relationship between class and ID selectors. Create your external css file by saving it as style.css then set up your style tags: (CODE) Reference the nav tag and set your prop…
Learn how to create flexible layouts using relative units in CSS.  New relative units added in CSS3 include vw(viewports width), vh(viewports height), vmin(minimum of viewports height and width), and vmax (maximum of viewports height and width).

773 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question