Avatar of thenelson
thenelson
 asked on

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

Web Graphics SoftwareHTMLJavaScript

Avatar of undefined
Last Comment
thenelson

8/22/2022 - Mon
Michel Plungjan

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...
thenelson

ASKER
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
Michel Plungjan

I am investigating.

I found the resource here at EE too :)
Your help has saved me hundreds of hours of internet surfing.
fblack61
Tom Beck

On a side note, remove line 72, context.moveTo(ev._x, ev._y);, from your script and the drawn line will be much smoother.
thenelson

ASKER
Removing context.moveTo(ev._x, ev._y); results in some jagged jumps when the mouse is moved quickly. But thanks for the suggestion:
Tom Beck

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.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
thenelson

ASKER
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.
Tom Beck

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.
thenelson

ASKER
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)
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
Tom Beck

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.
Michel Plungjan

I was sure the second example was on purpose since it really gives a good idea of intensity.
I'm still investigating chrome
Michel Plungjan

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

⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
thenelson

ASKER
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.
Michel Plungjan

I have NO jaggies in fx 10 at all
thenelson

ASKER
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.
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
ASKER CERTIFIED SOLUTION
Michel Plungjan

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
thenelson

ASKER
I have the script now working FF, IE and Chrome. Thanks for your help.