Miko Diko
Miko Diko

Reputation: 954

Can't draw on a HTML5 Canvas using Phonegap 2.7

I've found a simple drawer example online. It works fine on the PC.

When I run it, using Phonegap 2.7, on my Galaxy S4 (4.2.2), with Android 2.2 or 4.2.2, for the project, it just doesn't draw anything at all.

What am I doing wrong ?

<html lang="en">
<head>
<meta charset="utf-8" />
<title>Desktops and Tablets</title>

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" charset="utf-8" src="cordova-2.7.0.js"></script>
<script type="text/javascript">
  $(document).ready(function () {
     initialize();
  });

  // works out the X, Y position of the click inside the canvas from the X, Y position on the page
  function getPosition(mouseEvent, sigCanvas) {
     var x, y;
     if (mouseEvent.pageX != undefined && mouseEvent.pageY != undefined) {
        x = mouseEvent.pageX;
        y = mouseEvent.pageY;
     } else {
        x = mouseEvent.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
        y = mouseEvent.clientY + document.body.scrollTop + document.documentElement.scrollTop;
     }

     return { X: x - sigCanvas.offsetLeft, Y: y - sigCanvas.offsetTop };
  }

  var sigCanvas;
  var context;
  function initialize() {
    sigCanvas = document.getElementById("canvasSignature");
    context = sigCanvas.getContext("2d");
    context.strokeStyle = 'Black';
    context.lineWidth = 1;
    if ('ontouchstart' in document.documentElement) {
        var drawer = {
        isDrawing: false,
        touchstart: function (coors) {
              context.beginPath();
              context.moveTo(coors.x, coors.y);
              this.isDrawing = true;
           },
           touchmove: function (coors) {
              if (this.isDrawing) {
                 context.lineTo(coors.x, coors.y);
                 context.stroke();
              }
           },
           touchend: function (coors) {
              if (this.isDrawing) {
                 this.touchmove(coors);
                 this.isDrawing = false;
              }
           }
        };

        // create a function to pass touch events and coordinates to drawer
        function draw(event) {
            if (event.targetTouches[0] === undefined) {
                context.closePath();
                this.isDrawing = false;
                return;
            }
           // get the touch coordinates.  Using the first touch in case of multi-touch
           var coors = {
              x: event.targetTouches[0].pageX,
              y: event.targetTouches[0].pageY
           };
           // Now we need to get the offset of the canvas location
           var obj = sigCanvas;
           if (obj.offsetParent) {
              // Every time we find a new object, we add its offsetLeft and offsetTop to curleft and curtop.
              do {
                 coors.x -= obj.offsetLeft;
                 coors.y -= obj.offsetTop;
              }
              // The while loop can be "while (obj = obj.offsetParent)" only, which does return null
              // when null is passed back, but that creates a warning in some editors (i.e. VS2010).
              while ((obj = obj.offsetParent) != null);
           }

           // pass the coordinates to the appropriate handler
           drawer[event.type](coors);
        }
        // attach the touchstart, touchmove, touchend event listeners.
        sigCanvas.addEventListener('touchstart', draw, false);
        sigCanvas.addEventListener('touchmove', draw, false);
        sigCanvas.addEventListener('touchend', draw, false);
        // prevent elastic scrolling
        sigCanvas.addEventListener('touchmove', function (event) {
           event.preventDefault();
        }, false); 
     }
     else {
         // start drawing when the mousedown event fires, and attach handlers to
        // draw a line to wherever the mouse moves to
        $("#canvasSignature").mousedown(function (mouseEvent) {
           var position = getPosition(mouseEvent, sigCanvas);

           context.moveTo(position.X, position.Y);
           context.beginPath();
           $(this).mousemove(function (mouseEvent) {
              drawLine(mouseEvent, sigCanvas, context);
           }).mouseup(function (mouseEvent) {
              finishDrawing(mouseEvent, sigCanvas, context);
           }).mouseout(function (mouseEvent) {
              finishDrawing(mouseEvent, sigCanvas, context);
           });
        });

     }
  }

   // draws a line to the x and y coordinates of the mouse event inside
  // the specified element using the specified context
  function drawLine(mouseEvent, sigCanvas, context) {
      var position = getPosition(mouseEvent, sigCanvas);

     context.lineTo(position.X, position.Y);
     context.stroke();
  }

   // draws a line from the last coordiantes in the path to the finishing
  // coordinates and unbind any event handlers which need to be preceded
  // by the mouse down event
  function finishDrawing(mouseEvent, sigCanvas, context) {
     // draw the line to the finishing coordinates
     drawLine(mouseEvent, sigCanvas, context);
      context.closePath();
      // unbind any events which could draw
     $(sigCanvas).unbind("mousemove")
                 .unbind("mouseup")
                 .unbind("mouseout");
  }
</script>
</head>
<body>
<h1>Canvas test</h1>
<div id="canvasDiv">
   <canvas id="canvasSignature" width="500px" height="500px" style="border:2px solid #000000;"></canvas>
</div>
</body>
</html> 

Upvotes: 7

Views: 6772

Answers (4)

Daniel Pereira
Daniel Pereira

Reputation: 347

You should consider using Crosswalk. It replaces the default android webview, which is very incosistent (each vendor usually imlements its own) and it's hard to keep your application consistent among all android versions and vendors.

Crosswalk has a Cordova compatible version and in all of my tests the performance increase is noticeable.

https://crosswalk-project.org/

Upvotes: 0

FunkyKnuck
FunkyKnuck

Reputation: 34

My Galaxy S4 "bugs out" when I try to draw any image to the coordinates 0,0.

I only realized this because I drag elements around inside the canvas and whatever color is being drawn to those coordinates covers the whole screen.

When I drag to a point where there is no image covering the 0,0 coordinates in the canvas, my application runs normally. Also never happened in the desktop browser. Very strange.

I just run:

context.clearRect(0,0,1,1);

at the end of my draw function, and it solved it for me. Worth a try at least.

My friend's Galaxy S3 did not do this however.

Upvotes: 1

user664186
user664186

Reputation: 111

I'm experiencing the same issue on Galaxy S4. HTML Canvas drawing is not showing in webview, but it is working in Safari browser. Galaxy S2, S3 don't have the same issue.

In my case, when I disable Hardware acceleration, canvas works.

appView.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);

but it is very slow. It has nothing to do with PhoneGap. Probably Samsung made another bug on their implementation.

Upvotes: 5

DaveAlden
DaveAlden

Reputation: 30366

Are you building with Phonegap Build or Eclipse? If Eclipse, do you have your project set up correctly?

Replace $(document).ready(function () { with $(document).on("deviceready",function () { because phonegap uses the deviceready event to signal when it has initialised.

Also save the jQuery JS file inside your project; if the HTTP request fails or your Android device doesn't have a connection, the app will fail to load because it can't load jQuery.

Therefore replace <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

with <script type="text/javascript" src="jquery.min.js"></script>

I tried the code above with these modifications (plus I added some debug) and it works fine on my HTC HD2 running Android 2.2.3 and my Nexus 7 running Android 4.2.2

Here's a zip file containing the Eclipse project I created to test it and resulting Android APK. Give it a try on your devices and see if it works.

Upvotes: 0

Related Questions