Solved

Canvas script works in Firefox and IE but not Chrome

Posted on 2012-03-13
17
1,037 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
 
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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
This article explains how to prepare an HTML email signature template file containing dynamic placeholders for users' Azure AD data. Furthermore, it explains how to use this file to remotely set up a department-wide email signature policy in Office …
Learn how to create interesting presentations by including videos to keep your audience engaged using Prezi. Select "Insert" from the top menu in your Prezi editor: Select "YouTube Video": Paste the video URL into the prompt: "Select "Insert":…
It’s easy to embed any of your public Prezi presentations on your website or social network to share with others. Learn how simple it is in this tutorial.

758 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

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now