2016-03-30 17 views
1

Ich habe ein Problem mit Canvas nicht mousedown Ereignisse auf dem Tablet registrieren, habe ich seit einer Weile versucht, aber nichts funktioniert, auch die Maus zu Touchstart im Code ändern, Umsetzung hammer.js, jQuery Mobile, wäre jede Hilfe dankbar sein, auf dem Desktop funktioniert alles, ein etwas einfach nicht, die Touch-Gestenmousedown Ereignis nicht feuern auf Tablet/Handy, HTML5 Canvas

var gestures = function(config){ 

var conf = { 
    debug: true, 
    draw: true, 
    drawColor: "##f8f07e", 
    drawWidth: 5, 
    autoTrack: true, 
    allowRotation: true, 
    inverseShape: true, 
    points: 33 
}; 

var d; 
var ctx; 
var tracking = false; 
var ob = this; 

this.gestures = []; 
this.points = []; 

this.construct = function(){ 
    d = doc_size(); 
    //copying configuration 
    for(var opt in config){ 
     conf[opt] = config[opt]; 
    } 

    if(document.getElementById("gestures_canvas")) 
    { 
     ctx = document.getElementById("gestures_canvas").getContext("2d"); 
    } 
    else if(conf.draw) 
    { 
     //create canvas for drawing 

     var canvas = document.createElement("canvas"); 
     canvas.setAttribute("width", d.width + "px"); 
     canvas.setAttribute("height", d.height + "px"); 
     canvas.style.position = "fixed"; 
     canvas.style.top = "0px"; 
     canvas.style.left = "0px"; 
     canvas.id = "gestures_canvas"; 
     ctx = canvas.getContext("2d"); 
     document.body.appendChild(canvas); 
    } 
    if(conf.autoTrack || conf.draw) 
    { 
     add_event(document.body, "mousedown", this.Down); 
     add_event(document.body, "mouseup", this.Up); 




     tracking = true; 
    } 

    this.reset(); 
}; 




this.pauseTracking = function(){ 
    tracking = false; 
}; 

this.resumeTracking = function(){ 
    tracking = true; 
}; 

this.addGesture = function(name, points, callback){ 
    if(conf.inverseShape){ 
     var inverse = []; 
     for(var i = points.length-1; i >= 0; i--) 
     { 
      inverse.push(points[i]); 
     } 
     var gesture = {}; 
     gesture.name = name; 
     gesture.callback = callback; 
     var map = resample(inverse, inverse.length, conf); 

     gesture.map = vectorize(map, conf.allowRotation); 
     this.gestures.push(gesture); 

    } 

    var gesture = {}; 
    gesture.name = name; 
    gesture.callback = callback; 
    var map = resample(points, points.length, conf); 
    gesture.map = vectorize(map, conf.allowRotation); 
    this.gestures.push(gesture); 
}; 

this.resolve = function(points){ 

    if(points.length > 1) 
    { 
     this.reset(); 
     var map = resample(points, points.length, conf); 

     var ivect = vectorize(map, conf.allowRotation); 

     var maxScore = 0; 
     var match = "none"; 
     for(var i = 0; i < this.gestures.length; i++) 
     { 
      var dist = optCosDist(this.gestures[i].map, ivect); 
      var score = 1/dist; 

      if(score > maxScore) 
      { 
       maxScore = score; 
       match = this.gestures[i]; 
      } 
     } 
     if(match.callback) 
     { 
      match.callback(match.name); 
     } 
    } 
}; 

this.reset = function(){ 
    this.points = []; 
}; 

this.clear = function(){ 
    ctx.clearRect(0, 0, d.width, d.height); 
}; 

//gesture auto tracking 
//mouse down 
this.Down = function(event){ 
    ob.reset(); 
    if(conf.draw) 
    { 
     ctx.clearRect(0, 0, d.width, d.height); 
     ctx.lineWidth = conf.drawWidth; 
     ctx.strokeStyle = conf.drawColor; 
     ctx.lastX = event.clientX; 
     ctx.lastY = event.clientY; 
    } 
    if(conf.autoTrack && tracking) 
    { 
     var point = {}; 
     point.x = event.clientX; 
     point.y = event.clientY; 
     ob.points.push(point); 
    } 
    add_event(document.body, "mousedown", ob.Move); 
}; 

//mouse move 
this.Move = function(event){ 
    if(conf.draw) 
    { 
     ctx.beginPath(); 
     ctx.moveTo(ctx.lastX, ctx.lastY); 
     ctx.lineTo(event.clientX, event.clientY); 
     ctx.stroke(); 
     ctx.lastX = event.clientX; 
     ctx.lastY = event.clientY; 
    } 
    if(conf.autoTrack && tracking) 
    { 
     var point = {}; 
     point.x = event.clientX; 
     point.y = event.clientY; 
     ob.points.push(point); 
    } 
}; 
//mouse up 
this.Up = function(event){ 
    if(conf.autoTrack && tracking) 
    { 
     ob.resolve(ob.points); 
    } 
    remove_event(document.body, "mousemove", ob.Move); 
}; 


//some helping internal functions 

var optCosDist = function(gestureV, inputV){ 
    var a = 0; 
    var b = 0; 

    for(i = 0; i < gestureV.length; i += 2) 
    { 
     a = a + gestureV[i]*inputV[i] + gestureV[i+1]*inputV[i+1]; 
     b = b + gestureV[i]*inputV[i+1] - gestureV[i+1]*inputV[i]; 
    } 
    var angle = Math.atan2(b,a); 

    return Math.acos(a*Math.cos(angle) + b*Math.sin(angle)); 
}; 

//distance [PROTRACTOR] 
var Distance = function(u, v){ 
    var x = (u.x - v.x); 
    var y = (u.y - v.y); 
    return Math.sqrt((x*x)+(y*y)); 
}; 

var pathLength = function(points, n){ 
    var distance = 0; 
    for(i = 1; i < n; i++) 
    { 
     distance = distance + Distance(points[i-1], points[i]); 
    } 
    return distance; 
}; 

var resample = function(points, n){ 
    var subLength = pathLength(points, n)/(conf.points-1); 
    var distance = 0; 
    var newpoints = []; 
    var elem ={}; 
    elem.x = points[0].x; 
    elem.y = points[0].y; 
    newpoints.push(elem); 

    var i = 1; 
    while (i < points.length && newpoints.length < (conf.points-1)) 
    { 
     var subdist = Distance(points[i-1], points[i]); 
     if((distance + subdist) >= subLength) 
     { 
      var elem2 = {}; 
      elem2.x = points[i-1].x + ((subLength - distance)/subdist)*(points[i].x - points[i-1].x); 
      elem2.y = points[i-1].y + ((subLength - distance)/subdist)*(points[i].y - points[i-1].y); 
      //add point 
      newpoints.push(elem2); 
      points.splice(i,0,elem2); 
      distance = 0; 
     } 
     else 
     { 
      distance = distance + subdist; 
     } 
     i = i + 1; 
    } 
    var elem3 = {}; 
    //adding last point 
    elem3.x = points[points.length-1].x; 
    elem3.y = points[points.length-1].y; 
    newpoints.push(elem3); 

    return newpoints; 
}; 

var centroid = function(points){ 
    var center = {}; 
    center.x = 0; 
    center.y = 0; 

    for(i = 0; i < points.length; i++) 
    { 
     center.x = center.x + points[i].x; 
     center.y = center.y + points[i].y; 
    } 
    center.x = center.x/(points.length-1); 
    center.y = center.y/(points.length-1); 
    return center; 
}; 

var translate = function(points,center){ 
    for(var i = 0; i < points.length; i++) 
    { 
     points[i].x = points[i].x - center.x; 
     points[i].y = points[i].y - center.y; 
    } 
    return points; 
}; 

var vectorize = function(points, sensit){ 
    var vector = []; 

    var center = centroid(points); 
    var points = translate(points, center); 

    var lenkis = Math.atan2(points[1].x, points[1].y); 
    var delta = lenkis; 
    if(sensit) 
    { 
     var base = (Math.PI/4)*Math.floor((lenkis+(Math.PI/8))*(4/Math.PI)); 
     delta = base-lenkis; 
    } 
    var summa = 0; 
    for(var i = 0; i < points.length; i++) 
    { 
     var newx = points[i].x*Math.cos(delta) - points[i].y*Math.sin(delta); 
     var newy = points[i].x*Math.sin(delta) + points[i].y*Math.cos(delta); 
     vector.push(newx); 
     vector.push(newy); 
     summa = summa + newx*newx + newy*newy; 
    } 

    var magnitude = Math.sqrt(summa); 
    for(var i = 0; i < vector.length; i++) 
    { 
     vector[i] = vector[i]/magnitude; 
    } 
    return vector; 
}; 

//get document dimensions 
var doc_size = function(){ 
    var docsize = new Object(); 
    docsize.width = 0; 
    docsize.height = 0; 
    docsize.width = Math.max(
     Math.max(document.body.scrollWidth, document.documentElement.scrollWidth), 
     Math.max(document.body.offsetWidth, document.documentElement.offsetWidth), 
     Math.max(document.body.clientWidth, document.documentElement.clientWidth) 
    ); 
    docsize.height = Math.max(
     Math.max(document.body.scrollHeight, document.documentElement.scrollHeight), 
     Math.max(document.body.offsetHeight, document.documentElement.offsetHeight), 
     Math.max(document.body.clientHeight, document.documentElement.clientHeight) 
    ); 
    return docsize; 
}; 

//add event 
var add_event = function(element, type, listener){ 
    if(element.addEventListener) 
    { 
     element.addEventListener(type, listener, false); 
    } 
    else 
    { 
     element.attachEvent('on' + type, listener); 
    } 
}; 

//remove event 
var remove_event = function(element, type, listener){ 
    if(element.removeEventListener) 
     element.removeEventListener(type, listener, false); 
    else 
     element.detachEvent('on' + type, listener); 
}; 

this.construct(); 

}

Antwort

0

ich habe, dies zu tun in letzter Zeit, so dass Sie erfordert kann hier in meine Fußstapfen treten.

Um Ihr Spiel arbeiten auf mobilen Geräten zu bekommen, werden Sie 2 Schritte folgen müssen:

  • A) Ändern Sie alle mousedown, mousemove und mouseup Ereignisse touchstart, touchmove und touchend (gerade ersetzen Sie sie im Editor über Find & Ersetzen).
  • B) Ersetzen Sie jede Instanz event.clientX und event.clientY mit den folgenden:

clientX ↓

(event.targetTouches[0] ? event.targetTouches[0].pageX : event.changedTouches[event.changedTouches.length-1].pageX) 

Und clientY ↓

(event.targetTouches[0] ? event.targetTouches[0].pageY : event.changedTouches[event.changedTouches.length-1].pageY) 

Und wieder, benutzen Sie einfach & finden Ersetzen.

Die oben genannten Befehle sind lang/kompliziert, weilontouchend enthält keine targetTouches Objekt, und die obigen Beispiele für alle Kontexten (Berührungsstart, Berührungsbewegungs, und touchend) sank in kann über & finden Ersetzen und wird auf alle Android-Versionen arbeiten.

Eine letzte Sache, Sie müssen möglicherweise event.preventDefault() am Ende jedes Touchstart/TouchMove Event-Handler setzen, um zu verhindern, dass der mobile Browser denkt, dass die Seite scrollt.

Hoffe, das hilft!

+0

sie alle Gefolgt Schritte zu einem T, konnte es immer noch nicht, nicht allzu sicher zu arbeiten, wo ich falsch gehe, ist es immer noch mit all den Veränderungen funktioniert auf dem Desktop, funktioniert immer noch nicht auf Tablet/Handy –

+0

Fügen Sie eine 'window.onerror = Funktion (a, b, c) {Alarm (a + b + c); } 'um festzustellen, ob auf den mobilen Geräten Fehler auftreten –

0

Ich schaffte es, dies zu arbeiten, steckte etwas Code in den Kopf, um mobile zu erkennen und das Gestenskript zu verwenden, und dann verwendet der Desktop das Mausskript, ein bisschen ein Jerry Rig Code, aber es funktioniert, wenn jemand kann helfen, es schön machen nehmen Sie bitte Kontakt

if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm(os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent) 
|| /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s)|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp(i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac(|\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt(|\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg(g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v)|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v)|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-|)|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(navigator.userAgent.substr(0,4))){ isMobile = true;} 

----------end of head code--------------- 

if(isMobile==true){ 
var gestures = function(config){ 
var conf = { 
    debug: true, 
    draw: true, 
    drawColor: "#000000", 
    drawWidth: 5, 
    autoTrack: true, 
    allowRotation: true, 
    inverseShape: true, 
    points: 33 
}; 

var d; 
var ctx; 
var tracking = false; 
var ob = this; 

this.gestures = []; 
this.points = []; 

this.construct = function(){ 
    d = doc_size(); 
    //copying configuration 
    for(var opt in config){ 
     conf[opt] = config[opt]; 
    } 

    if(document.getElementById("gestures_canvas")) 
    { 
     ctx = document.getElementById("gestures_canvas").getContext("2d"); 
    } 
    else if(conf.draw) 
    { 
     //create canvas for drawing 
     var canvas = document.createElement("canvas"); 
     canvas.setAttribute("width", d.width + "px"); 
     canvas.setAttribute("height", d.height + "px"); 
     canvas.style.position = "absolute"; 
     canvas.style.top = "0px"; 
     canvas.style.left = "0px"; 
     canvas.id = "gestures_canvas"; 
     ctx = canvas.getContext("2d"); 
     document.body.appendChild(canvas); 
    } 
    if(conf.autoTrack || conf.draw) 
    { 
     add_event(document.body, "touchstart", this.Down); 
     add_event(document.body, "touchend", this.Up); 
     tracking = true; 
    } 

    this.reset(); 
}; 

this.pauseTracking = function(){ 
    tracking = false; 
}; 

this.resumeTracking = function(){ 
    tracking = true; 
}; 

this.addGesture = function(name, points, callback){ 
    if(conf.inverseShape){ 
     var inverse = []; 
     for(var i = points.length-1; i >= 0; i--) 
     { 
      inverse.push(points[i]); 
     } 
     var gesture = {}; 
     gesture.name = name; 
     gesture.callback = callback; 
     var map = resample(inverse, inverse.length, conf); 

     gesture.map = vectorize(map, conf.allowRotation); 
     this.gestures.push(gesture); 

    } 

    var gesture = {}; 
    gesture.name = name; 
    gesture.callback = callback; 
    var map = resample(points, points.length, conf); 
    gesture.map = vectorize(map, conf.allowRotation); 
    this.gestures.push(gesture); 
}; 

this.resolve = function(points){ 

    if(points.length > 1) 
    { 
     this.reset(); 
     var map = resample(points, points.length, conf); 

     var ivect = vectorize(map, conf.allowRotation); 

     var maxScore = 0; 
     var match = "none"; 
     for(var i = 0; i < this.gestures.length; i++) 
     { 
      var dist = optCosDist(this.gestures[i].map, ivect); 
      var score = 1/dist; 

      if(score > maxScore) 
      { 
       maxScore = score; 
       match = this.gestures[i]; 
      } 
     } 
     if(match.callback) 
     { 
      match.callback(match.name); 
     } 
    } 
}; 

this.reset = function(){ 
    this.points = []; 
}; 

this.clear = function(){ 
    ctx.clearRect(0, 0, d.width, d.height); 
}; 

//gesture auto tracking 
//mouse down 
this.Down = function(event){ 
    ob.reset(); 
    if(conf.draw) 
    { 
     ctx.clearRect(0, 0, d.width, d.height); 
     ctx.lineWidth = conf.drawWidth; 
     ctx.strokeStyle = conf.drawColor; 
     ctx.lastX = (event.targetTouches[0] ? event.targetTouches[0].pageX :  event.changedTouches[event.changedTouches.length-1].pageX) 
;ctx.lastY = (event.targetTouches[0] ? event.targetTouches[0].pageY :  event.changedTouches[event.changedTouches.length-1].pageY) 
; 
    } 
    if(conf.autoTrack && tracking) 
    { 
     var point = {}; 
     point.x = (event.targetTouches[0] ? event.targetTouches[0].pageX : event.changedTouches[event.changedTouches.length-1].pageX) 
; 
     point.y = (event.targetTouches[0] ? event.targetTouches[0].pageY : event.changedTouches[event.changedTouches.length-1].pageY) 
; 
     ob.points.push(point); 
    } 
    add_event(document.body, "touchmove", ob.Move); 
}; 

//mouse move 
this.Move = function(event){ 
    if(conf.draw) 
    { 
     ctx.beginPath(); 
     ctx.moveTo(ctx.lastX, ctx.lastY); 
     ctx.lineTo((event.targetTouches[0] ? event.targetTouches[0].pageX :  event.changedTouches[event.changedTouches.length-1].pageX) 
, (event.targetTouches[0] ? event.targetTouches[0].pageY : event.changedTouches[event.changedTouches.length-1].pageY) 
); 
      ctx.stroke(); 
     ctx.lastX = (event.targetTouches[0] ? event.targetTouches[0].pageX : event.changedTouches[event.changedTouches.length-1].pageX) 
; 
     ctx.lastY = (event.targetTouches[0] ? event.targetTouches[0].pageY : event.changedTouches[event.changedTouches.length-1].pageY) 
; 
    } 
    if(conf.autoTrack && tracking) 
    { 
     var point = {}; 
     point.x = (event.targetTouches[0] ? event.targetTouches[0].pageX : event.changedTouches[event.changedTouches.length-1].pageX) 
; 
     point.y = (event.targetTouches[0] ? event.targetTouches[0].pageY : event.changedTouches[event.changedTouches.length-1].pageY) 
    ; 
     ob.points.push(point); 
    } 
}; 
//mouse up 
this.Up = function(event){ 
    if(conf.autoTrack && tracking) 
    { 
     ob.resolve(ob.points); 
    } 
    remove_event(document.body, "touchmove", ob.Move); 
}; 


//some helping internal functions 

var optCosDist = function(gestureV, inputV){ 
    var a = 0; 
    var b = 0; 

    for(i = 0; i < gestureV.length; i += 2) 
    { 
     a = a + gestureV[i]*inputV[i] + gestureV[i+1]*inputV[i+1]; 
     b = b + gestureV[i]*inputV[i+1] - gestureV[i+1]*inputV[i]; 
    } 
    var angle = Math.atan2(b,a); 

    return Math.acos(a*Math.cos(angle) + b*Math.sin(angle)); 
}; 

//distance [PROTRACTOR] 
var Distance = function(u, v){ 
    var x = (u.x - v.x); 
    var y = (u.y - v.y); 
    return Math.sqrt((x*x)+(y*y)); 
}; 

var pathLength = function(points, n){ 
    var distance = 0; 
    for(i = 1; i < n; i++) 
    { 
     distance = distance + Distance(points[i-1], points[i]); 
    } 
    return distance; 
}; 

var resample = function(points, n){ 
    var subLength = pathLength(points, n)/(conf.points-1); 
    var distance = 0; 
    var newpoints = []; 
    var elem ={}; 
    elem.x = points[0].x; 
    elem.y = points[0].y; 
    newpoints.push(elem); 

    var i = 1; 
    while (i < points.length && newpoints.length < (conf.points-1)) 
    { 
     var subdist = Distance(points[i-1], points[i]); 
     if((distance + subdist) >= subLength) 
     { 
      var elem2 = {}; 
      elem2.x = points[i-1].x + ((subLength - distance)/subdist)*(points[i].x - points[i-1].x); 
      elem2.y = points[i-1].y + ((subLength - distance)/subdist)*(points[i].y - points[i-1].y); 
      //add point 
      newpoints.push(elem2); 
      points.splice(i,0,elem2); 
      distance = 0; 
     } 
     else 
     { 
      distance = distance + subdist; 
     } 
     i = i + 1; 
    } 
    var elem3 = {}; 
    //adding last point 
    elem3.x = points[points.length-1].x; 
    elem3.y = points[points.length-1].y; 
    newpoints.push(elem3); 

    return newpoints; 
}; 

var centroid = function(points){ 
    var center = {}; 
    center.x = 0; 
    center.y = 0; 

    for(i = 0; i < points.length; i++) 
    { 
     center.x = center.x + points[i].x; 
     center.y = center.y + points[i].y; 
    } 
    center.x = center.x/(points.length-1); 
    center.y = center.y/(points.length-1); 
    return center; 
}; 

var translate = function(points,center){ 
    for(var i = 0; i < points.length; i++) 
    { 
     points[i].x = points[i].x - center.x; 
     points[i].y = points[i].y - center.y; 
    } 
    return points; 
}; 

var vectorize = function(points, sensit){ 
    var vector = []; 

    var center = centroid(points); 
    var points = translate(points, center); 

    var lenkis = Math.atan2(points[1].x, points[1].y); 
    var delta = lenkis; 
    if(sensit) 
    { 
     var base = (Math.PI/4)*Math.floor((lenkis+(Math.PI/8))*(4/Math.PI)); 
     delta = base-lenkis; 
    } 
    var summa = 0; 
    for(var i = 0; i < points.length; i++) 
    { 
     var newx = points[i].x*Math.cos(delta) - points[i].y*Math.sin(delta); 
     var newy = points[i].x*Math.sin(delta) + points[i].y*Math.cos(delta); 
     vector.push(newx); 
     vector.push(newy); 
     summa = summa + newx*newx + newy*newy; 
    } 

    var magnitude = Math.sqrt(summa); 
    for(var i = 0; i < vector.length; i++) 
    { 
     vector[i] = vector[i]/magnitude; 
    } 
    return vector; 
}; 

//get document dimensions 
var doc_size = function(){ 
    var docsize = new Object(); 
    docsize.width = 0; 
    docsize.height = 0; 
    docsize.width = Math.max(
     Math.max(document.body.scrollWidth, document.documentElement.scrollWidth), 
     Math.max(document.body.offsetWidth, document.documentElement.offsetWidth), 
     Math.max(document.body.clientWidth, document.documentElement.clientWidth) 
    ); 
    docsize.height = Math.max(
     Math.max(document.body.scrollHeight, document.documentElement.scrollHeight), 
     Math.max(document.body.offsetHeight, document.documentElement.offsetHeight), 
     Math.max(document.body.clientHeight, document.documentElement.clientHeight) 
    ); 
    return docsize; 
}; 

//add event 
var add_event = function(element, type, listener){ 
    if(element.addEventListener) 
    { 
     element.addEventListener(type, listener, false); 
    } 
    else 
    { 
     element.attachEvent('on' + type, listener); 
    } 
}; 

//remove event 
var remove_event = function(element, type, listener){ 
    if(element.removeEventListener) 
     element.removeEventListener(type, listener, false); 
    else 
     element.detachEvent('on' + type, listener); 
}; 

this.construct(); 
} 
} else { 
var gestures = function(config){ 

var conf = { 
    debug: true, 
    draw: true, 
    drawColor: "#000000", 
    drawWidth: 5, 
    autoTrack: true, 
    allowRotation: true, 
    inverseShape: true, 
    points: 33 
}; 

var d; 
var ctx; 
var tracking = false; 
var ob = this; 

this.gestures = []; 
this.points = []; 

this.construct = function(){ 
    d = doc_size(); 
    //copying configuration 
    for(var opt in config){ 
     conf[opt] = config[opt]; 
    } 

    if(document.getElementById("gestures_canvas")) 
    { 
     ctx = document.getElementById("gestures_canvas").getContext("2d"); 
    } 
    else if(conf.draw) 
    { 
     //create canvas for drawing 
     var canvas = document.createElement("canvas"); 
     canvas.setAttribute("width", d.width + "px"); 
     canvas.setAttribute("height", d.height + "px"); 
     canvas.style.position = "absolute"; 
     canvas.style.top = "0px"; 
     canvas.style.left = "0px"; 
     canvas.id = "gestures_canvas"; 
     ctx = canvas.getContext("2d"); 
     document.body.appendChild(canvas); 
    } 
    if(conf.autoTrack || conf.draw) 
    { 
     add_event(document.body, "mousedown", this.Down); 
     add_event(document.body, "mouseup", this.Up); 
     tracking = true; 
    } 

    this.reset(); 
}; 

this.pauseTracking = function(){ 
    tracking = false; 
}; 

this.resumeTracking = function(){ 
    tracking = true; 
}; 

this.addGesture = function(name, points, callback){ 
    if(conf.inverseShape){ 
     var inverse = []; 
     for(var i = points.length-1; i >= 0; i--) 
     { 
      inverse.push(points[i]); 
     } 
     var gesture = {}; 
     gesture.name = name; 
     gesture.callback = callback; 
     var map = resample(inverse, inverse.length, conf); 

     gesture.map = vectorize(map, conf.allowRotation); 
     this.gestures.push(gesture); 

    } 

    var gesture = {}; 
    gesture.name = name; 
    gesture.callback = callback; 
    var map = resample(points, points.length, conf); 
    gesture.map = vectorize(map, conf.allowRotation); 
    this.gestures.push(gesture); 
}; 

this.resolve = function(points){ 

    if(points.length > 1) 
    { 
     this.reset(); 
     var map = resample(points, points.length, conf); 

     var ivect = vectorize(map, conf.allowRotation); 

     var maxScore = 0; 
     var match = "none"; 
     for(var i = 0; i < this.gestures.length; i++) 
     { 
      var dist = optCosDist(this.gestures[i].map, ivect); 
      var score = 1/dist; 

      if(score > maxScore) 
      { 
       maxScore = score; 
       match = this.gestures[i]; 
      } 
     } 
     if(match.callback) 
     { 
      match.callback(match.name); 
     } 
    } 
}; 

this.reset = function(){ 
    this.points = []; 
}; 

this.clear = function(){ 
    ctx.clearRect(0, 0, d.width, d.height); 
}; 

//gesture auto tracking 
//mouse down 
this.Down = function(event){ 
    ob.reset(); 
    if(conf.draw) 
    { 
     ctx.clearRect(0, 0, d.width, d.height); 
     ctx.lineWidth = conf.drawWidth; 
     ctx.strokeStyle = conf.drawColor; 
     ctx.lastX = event.clientX; 
     ctx.lastY = event.clientY; 
    } 
    if(conf.autoTrack && tracking) 
    { 
     var point = {}; 
     point.x = event.clientX; 
     point.y = event.clientY; 
     ob.points.push(point); 
    } 
    add_event(document.body, "mousemove", ob.Move); 
}; 

//mouse move 
this.Move = function(event){ 
    if(conf.draw) 
    { 
     ctx.beginPath(); 
     ctx.moveTo(ctx.lastX, ctx.lastY); 
     ctx.lineTo(event.clientX, event.clientY); 
     ctx.stroke(); 
     ctx.lastX = event.clientX; 
     ctx.lastY = event.clientY; 
    } 
    if(conf.autoTrack && tracking) 
    { 
     var point = {}; 
     point.x = event.clientX; 
     point.y = event.clientY; 
     ob.points.push(point); 
    } 
}; 
//mouse up 
this.Up = function(event){ 
    if(conf.autoTrack && tracking) 
    { 
     ob.resolve(ob.points); 
    } 
    remove_event(document.body, "mousemove", ob.Move); 
}; 


//some helping internal functions 

var optCosDist = function(gestureV, inputV){ 
    var a = 0; 
    var b = 0; 

    for(i = 0; i < gestureV.length; i += 2) 
    { 
     a = a + gestureV[i]*inputV[i] + gestureV[i+1]*inputV[i+1]; 
     b = b + gestureV[i]*inputV[i+1] - gestureV[i+1]*inputV[i]; 
    } 
    var angle = Math.atan2(b,a); 

    return Math.acos(a*Math.cos(angle) + b*Math.sin(angle)); 
}; 

//distance [PROTRACTOR] 
var Distance = function(u, v){ 
    var x = (u.x - v.x); 
    var y = (u.y - v.y); 
    return Math.sqrt((x*x)+(y*y)); 
}; 

var pathLength = function(points, n){ 
    var distance = 0; 
    for(i = 1; i < n; i++) 
    { 
     distance = distance + Distance(points[i-1], points[i]); 
    } 
    return distance; 
}; 

var resample = function(points, n){ 
    var subLength = pathLength(points, n)/(conf.points-1); 
    var distance = 0; 
    var newpoints = []; 
    var elem ={}; 
    elem.x = points[0].x; 
    elem.y = points[0].y; 
    newpoints.push(elem); 

    var i = 1; 
    while (i < points.length && newpoints.length < (conf.points-1)) 
    { 
     var subdist = Distance(points[i-1], points[i]); 
     if((distance + subdist) >= subLength) 
     { 
      var elem2 = {}; 
      elem2.x = points[i-1].x + ((subLength - distance)/subdist)*(points[i].x - points[i-1].x); 
      elem2.y = points[i-1].y + ((subLength - distance)/subdist)*(points[i].y - points[i-1].y); 
      //add point 
      newpoints.push(elem2); 
      points.splice(i,0,elem2); 
      distance = 0; 
     } 
     else 
     { 
      distance = distance + subdist; 
     } 
     i = i + 1; 
    } 
    var elem3 = {}; 
    //adding last point 
    elem3.x = points[points.length-1].x; 
    elem3.y = points[points.length-1].y; 
    newpoints.push(elem3); 

    return newpoints; 
}; 

var centroid = function(points){ 
    var center = {}; 
    center.x = 0; 
    center.y = 0; 

    for(i = 0; i < points.length; i++) 
    { 
     center.x = center.x + points[i].x; 
     center.y = center.y + points[i].y; 
    } 
    center.x = center.x/(points.length-1); 
    center.y = center.y/(points.length-1); 
    return center; 
}; 

var translate = function(points,center){ 
    for(var i = 0; i < points.length; i++) 
    { 
     points[i].x = points[i].x - center.x; 
     points[i].y = points[i].y - center.y; 
    } 
    return points; 
}; 

var vectorize = function(points, sensit){ 
    var vector = []; 

    var center = centroid(points); 
    var points = translate(points, center); 

    var lenkis = Math.atan2(points[1].x, points[1].y); 
    var delta = lenkis; 
    if(sensit) 
    { 
     var base = (Math.PI/4)*Math.floor((lenkis+(Math.PI/8))*(4/Math.PI)); 
     delta = base-lenkis; 
    } 
    var summa = 0; 
    for(var i = 0; i < points.length; i++) 
    { 
     var newx = points[i].x*Math.cos(delta) - points[i].y*Math.sin(delta); 
     var newy = points[i].x*Math.sin(delta) + points[i].y*Math.cos(delta); 
     vector.push(newx); 
     vector.push(newy); 
     summa = summa + newx*newx + newy*newy; 
    } 

    var magnitude = Math.sqrt(summa); 
    for(var i = 0; i < vector.length; i++) 
    { 
     vector[i] = vector[i]/magnitude; 
    } 
    return vector; 
}; 

//get document dimensions 
var doc_size = function(){ 
    var docsize = new Object(); 
    docsize.width = 0; 
    docsize.height = 0; 
    docsize.width = Math.max(
     Math.max(document.body.scrollWidth, document.documentElement.scrollWidth), 
     Math.max(document.body.offsetWidth, document.documentElement.offsetWidth), 
     Math.max(document.body.clientWidth, document.documentElement.clientWidth) 
    ); 
    docsize.height = Math.max(
     Math.max(document.body.scrollHeight, document.documentElement.scrollHeight), 
     Math.max(document.body.offsetHeight, document.documentElement.offsetHeight), 
     Math.max(document.body.clientHeight, document.documentElement.clientHeight) 
    ); 
    return docsize; 
}; 

//add event 
var add_event = function(element, type, listener){ 
    if(element.addEventListener) 
    { 
     element.addEventListener(type, listener, false); 
    } 
    else 
    { 
     element.attachEvent('on' + type, listener); 
    } 
}; 

//remove event 
var remove_event = function(element, type, listener){ 
    if(element.removeEventListener) 
     element.removeEventListener(type, listener, false); 
    else 
     element.detachEvent('on' + type, listener); 
}; 

this.construct(); 
} 
}