Jump to content

Canvas mobile


Recommended Posts

I assume you can use the canvas, just get the right

screen size set up, log the mouse movements when mouse is down,

draw the pixels on the canvas, and upload the canvas data by ajax

to the server afterwards....process it and save as image,

and load it back to the client again as confirmation.

 

Write the client part in javascript, use a htmlframe with a <canvas id="mycanvas">

and write the mouse handlers in JS too, and then use an ajaxcall

to the htmlframe, picking up that in ajaxevent, when uploading the 

canvas data.

 

Load the JS into the htmlframe on formshow e.g. This works very well,

and is the only good solution when needing to capture mouse movements,

as far as I know.

Link to comment
Share on other sites


//example JS code for capturing mouse events, load this into htmlfram
//turn screenmask off by UniSession.AddJS('myMask.hide();'); after saving canvas data

<canvas id="mycanvas">

<script type="text/javascript">
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext("2d");
var mDown = false;
var myMask = new Ext.LoadMask(MainForm.myHTMLFrame, {msg:"Saving data ..."});

function drawStuff() {
//do your canvas drawing here...
ctx.moveTo(...)
}

function relMouseCoords(event){
var totalOffsetX = 0;
var totalOffsetY = 0;
var canvasX = 0;
var canvasY = 0;
var currentElement = this;

do{
totalOffsetX += currentElement.offsetLeft - currentElement.scrollLeft;
totalOffsetY += currentElement.offsetTop - currentElement.scrollTop;
}
while(currentElement = currentElement.offsetParent);

canvasX = event.pageX - totalOffsetX;
canvasY = event.pageY - totalOffsetY;

return {x:canvasX, y:canvasY}
}
HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords;


$("#mycanvas").mousemove(function(event){
//store mouse movements
if(mDown){
coords = canvas.relMouseCoords(event);
push(myArray, {x: coords.x, y: coords.y});
drawStuff();
}
});

$("#mycanvas").mousedown(function(event){
//skip right mouse up
if(event.which===3) return;
//start logging
mDown = true;
});

$("#mycanvas").mouseup(function(event){
//skip right mouse up
if(event.which===3) return;
//turn screenmask on...
myMask.show();
ajaxRequest(MainForm.myHTMLFrame, ['saveCanvasData'], { myArray... });
});


window.addEventListener('resize', updateCanvas, true);
function updateCanvas() {
canvas.width = MainForm.myHTMLFrame.getWidth();
canvas.height = MainForm.myHTMLFrame.getHeight();
drawStuff();

}
updateCanvas();

</script>



 

Link to comment
Share on other sites

Hi Sandro;

 

The basic idea is that as the mouse moves, it reports x and y coordinates,

and you push these into an array.

 

THen in drawStuff() you simply draw these pixels, by drawing

lines between them, as you loop through the array,

something like this:

 

ctx.beginPath();

ctx.strokeStyle = "#000000"; //black color
ctx.lineWidth = 0.8;
ctx.lineCap = 'square';
 

for(i=0;i<myArray.length-1;i++){

ctx.moveTo(myArray.x, myArray.y);
ctx.lineTo(myArray[i+1].x, myArray[i+1].y);
}

 

ctx.stroke();

ctx.closePath();

 

Basic Javscript is not difficult at all, and you will get used to the syntax in no time,

and W3Schools have all the info you need.

 

My impression is that Javascript is a very powerful language, I simply love it !

It is amazing what you can do, and with a knowledge of JS combined with

Unigui, you can create almost anything.. :)

 

Best to just dive into it ! :)

 

And the communication between JS in the client and Unigui, is so simple

and easy to set up, it is like a walk in the park compared to creating things

piece by piece in PHP for instance, and also much easier than Node &

various JS frameworks like backbone.JS, sails.JS etc, even though you

have JS on both sides there.

 

Tip: Use docpad, with LiveReload, when you make JS code.

 

I do that, and when I click Ctrl-S, the browser is updated in the

background, and with the console you get easy debugging.

 

This way it is so FAST to develop client code with JS, it is fun

and you learn JS fast too, because of this close feedback loop.

 

 

Anyway, after the signature is ok, you just upload this to the server,

meaning that array, and save it, and reconstruct the signature

image based on that pixel data.

Link to comment
Share on other sites

Here is an example of JS code which works in docpad, as signature.js:

 $(document).ready( function() {
  //canvas id="mycanvas">
  //<script type="text/javascript">

  var canvas = document.getElementById("mycanvas");
  var ctx = canvas.getContext("2d");
  var mDown = false;
  var myArray = [];
  var coords = [];
      
  function drawStuff() {
  	//do your canvas drawing here...
  	 ctx.beginPath();
     ctx.fillStyle = "#EEEEEE";    
     ctx.rect(0,0,canvas.width, canvas.height);
     ctx.fill();
     
     ctx.beginPath();
     ctx.strokeStyle = "#000000"; //black color
     ctx.lineWidth = 0.8;
     ctx.lineCap = 'square';
     var i = 0;
     for(i=0;i<(myArray.length-1);i++){
       ctx.moveTo(myArray[i].x, myArray[i].y);
       ctx.lineTo(myArray[i+1].x, myArray[i+1].y);
     }
     ctx.stroke();     
     ctx.closePath();
    } 
    
   function relMouseCoords(event){
    var totalOffsetX = 0;
    var totalOffsetY = 0;
    var canvasX = 0;
    var canvasY = 0;
    var currentElement = this;

    do{
        totalOffsetX += currentElement.offsetLeft - currentElement.scrollLeft;
        totalOffsetY += currentElement.offsetTop - currentElement.scrollTop;
    }
    while(currentElement = currentElement.offsetParent);

    canvasX = event.pageX - totalOffsetX;
    canvasY = event.pageY - totalOffsetY;

    return {x:canvasX, y:canvasY}
  }
  HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords;
    
  
   $("#mycanvas").mousemove(function(event){
      //store mouse movements
      if(mDown){
      coords = canvas.relMouseCoords(event);
      myArray.push({x:  coords.x, y : coords.y});
      drawStuff();
      }
   });
    
   $("#mycanvas").mousedown(function(event){
   	//skip right mouse up
  	if(event.which===3) return;
     //start logging
     mDown = true;
     drawStuff();
   }); 
   
  $("#mycanvas").mouseup(function(event){
  	//skip right mouse up
  	if(event.which===3) return;
  	mDown = false;
  	 //turn screenmask on...
     //myMask.show();
     //ajaxRequest(MainForm.myHTMLFrame, ['saveCanvasData'], { myArray... });
   }); 
   
  
  window.addEventListener('resize', updateCanvas, true);
  function updateCanvas() {
    //canvas.width = MainForm.myHTMLFrame.getWidth();
    //canvas.height = MainForm.myHTMLFrame.getHeight(); 
    drawStuff();
    
  }
  updateCanvas();
   
//</script>
  });

In addition to this, you have this index.html:

---
title: "Welcome!"
layout: "default"
isPage: true
---


<canvas id="mycanvas" style="border:0px solid #990000;">
</canvas>

And this eco layout file:

<html>
<head>
   <title><%= @document.title %> | My Website</title>
   <%- @getBlock("meta").toHTML() %>
</head>
<body>
    <%- @content %>
    <%- @getBlock("scripts").add(["/vendor/jquery.js","/scripts/signature.js",]).toHTML() %>

</body>
</html>

Notice that jQuery is there too.

 

Of course you have to modify this code, to split the paths you draw,

so not all pixels are connected, and then create the upload code.

 

If you want me to do it for you, we can maybe work out a deal,

but this should not be too hard to finish.

Link to comment
Share on other sites

I experimented a little with the drawing routine, and came up with a simple solution

where you push invalid pixel data to split the paths:

 function drawStuff() {
     //first clear the canvas and draw a thin border
     ctx.beginPath();
     ctx.strokeStyle = "#000000"; //black color
     ctx.lineCap = 'square';
     ctx.lineWidth = 0.5;
     ctx.fillStyle = "#FFFFFF";    
     ctx.rect(0,0,canvas.width, canvas.height);
     ctx.fill();
     ctx.stroke(); 
     ctx.closePath();
     //loop through the pixel data
     ctx.beginPath();
     for(var i=0;i<(myArray.length-1);i++){
       //when we encounter illegal pixel data, close the path	
       if(myArray[i].x === -1){
       	 ctx.stroke();     
         ctx.closePath();
	 ctx.beginPath();
	 } else 
	//skip to valid pixel data and draw paths
	if(myArray[i+1].x != -1) {
         ctx.moveTo(myArray[i].x, myArray[i].y);
         ctx.lineTo(myArray[i+1].x, myArray[i+1].y);
       }
     } 
     //close last path
     ctx.stroke();     
     ctx.closePath();
   } 

And you do this in the mouseup event: 

 $("#mycanvas").mouseup(function(event){
     //skip right mouse up
     if(event.which===3) return;
     mDown = false;
     document.getElementById("mycanvas").style.cursor = 'default'; 
     //push invalid pixel data to mark end of path
     myArray.push({x:  -1, y : -1});
     drawStuff();
     //turn screenmask on...
     //myMask.show();
     //ajaxRequest(MainForm.myHTMLFrame, ['saveCanvasData'], { myArray... });
   }); 

In addition I have added a line to the mousedown event, changing cursor style:

$("#mycanvas").mousedown(function(event){
     //skip right mouse up
     if(event.which===3) return;
     //start logging
     mDown = true;
     
     document.getElementById("mycanvas").style.cursor = 'pointer'; 
     drawStuff();
   }); 

Testing this quickly, it seems to work. Of course this must be

debugged re events and statuses etc. As the mouse leaves

the canvas, the mouseup event will not be triggered, so you

have to add a mouseout event - I guess - and set mDown=false

to avoid a mouse "hang-up"...etc. - like this:

 $("#mycanvas").mouseout(function(event){
  	if(event.which===3) return;
  	mDown = false;
  	myArray.push({x:  -1, y : -1});
        document.getElementById("mycanvas").style.cursor = 'default'; 
  	drawStuff();
   }); 

One can use this to create a simple CAPTCHA routine, where

e.g. the user must draw a line between two shapes, to continue.

  • Upvote 1
Link to comment
Share on other sites

  • 4 weeks later...

Hi,

 

That should be no problem.

 

But make sure you got this:

 

 
<script type="text/javascript">    <-----------------
 
 
And not only <script> as the link you mentioned.
Link to comment
Share on other sites

  • 1 year later...
×
×
  • Create New...