0

I am working on creating a scratch card script in javascript mouse event handlers is working properly on pc but it is not on my touch phone. on pc , i hold down the left mouse button and move it around to scratch the card. on touch phone , It scratches only if i keep touching and releasing my finger on the phone screen.

;(function() {
  var global = this;
  function ScratchCard(element, options, ownerDocument) {

    // apply default arguments.
    var defaultOptions = {
      'color': 'gray',
      'radius': 20
    };
    if (options) {
      for (var key in defaultOptions) {
        if (!(key in options)) {
          options[key] = defaultOptions[key];
        }
      }
    } else {
      options = defaultOptions;
    }
    ownerDocument = ownerDocument || global.document;
    
    // canvas validate.
    var canvas = document.createElement('canvas');
    if (typeof canvas.getContext != 'function')
      return console.log('Canvas not supported.');

    // apply canvas offset & size of element
    var rect = element.getBoundingClientRect();
    canvas.width = rect.width || rect.right - rect.left
    canvas.height = rect.height || rect.bottom - rect.top;
    canvas.style.top = rect.top + 'px';
    canvas.style.left = rect.left + 'px';
    canvas.style.position = 'absolute';
    canvas.style.zIndex = +element.style.zIndex + 1;

    // fill the canvas
    var context = canvas.getContext('2d');
    context.fillStyle = options.color;
    context.fillRect(0, 0, canvas.width, canvas.height);
    context.globalCompositeOperation = "destination-out";
    context.strokeStyle = "rgba(0,0,0,1)";

    // add mouse events to canvas
    // TODO: supply touch events
    // TODO: scratch from the outside
    function scratchStart(event) {
      if (event.button != 0) // not left button
        return;

      var x = event.offsetX || event.layerX;
      var y = event.offsetY || event.layerY;

      context.beginPath();
      context.arc(x, y, options.radius, 0, Math.PI * 2);
      context.fill();

      canvas.addEventListener('mousemove', scratchMove);
      canvas.addEventListener('touchmove', scratchMove);
      document.addEventListener('mouseup', scratchEnd);
      document.addEventListener('touchend', scratchEnd);
    }

    function scratchMove(event) {
      var x = event.offsetX || event.layerX;
      var y = event.offsetY || event.layerY;

      context.beginPath();
      context.arc(x, y, options.radius, 0, Math.PI * 2);
      context.fill();
    }

    function scratchEnd(event) {
      canvas.removeEventListener('mousemove', scratchMove);
      canvas.removeEventListener('touchmove', scratchMove);
      document.removeEventListener('mouseup', scratchEnd);
      document.removeEventListener('touchend', scratchEnd);

    }

    canvas.addEventListener('mousedown', scratchStart);
    canvas.addEventListener('touchstart', scratchStart);

    // disable element interaction
    ['MozUserSelect',
     'msUserSelect',
     'oUserSelect',
     'webkitUserSelect',
     'pointerEvents']
      .filter(function (cssProp) {
        return cssProp in element.style;
      }).forEach(function (cssProp) {
        element.style[cssProp] = 'none';
      });

    // append canvas to body.
    document.body.appendChild(canvas);
  }

  if (typeof module == 'object' && module.exports) {
    // Node.js module
    module.exports = ScratchCard;
  } else if (typeof define == 'function' && (define.amd || define.cmd)) {
    // AMD or CMD module
    define(ScratchCard);
  } else if (typeof jQuery == 'function' && typeof jQuery.extend == 'function') {
    // jQuery plugin
    jQuery.fn.extend({
      'ScratchCard': function (options) {
        return this.each(function (element) {
          ScratchCard(element, options);
        });
      }
    });
  } else if (typeof angular == 'object' && typeof angular.module == 'function') {
    // AngularJS module
    // TODO: modify it to a directive.
    angular.module('ScratchCard', [])
      .value('ScratchCard', ScratchCard);
  } else {
    // Apply to a global variable.
    if (global.ScratchCard) {
      (function (oldScratchCard) {
        ScratchCard.noConflict = function () {
          global.ScratchCard = oldScratchCard;
          return ScratchCard;
        };
      }) (global.ScratchCard);
    }
    global.ScratchCard = ScratchCard;
  }
}).call(this);
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
  <!--<script type="text/javascript" src="jquery-1.11.2.min.js"></script> -->
  <!-- <script type="text/javascript" src="touch.js"></script> -->
  <title>ScratchCard Demo</title>
  <style>
  div {
   display: inline-block;
   padding: 5px;
   border: 1px solid black;
  }
  p {
   margin: 0;
   /*padding: 5px;*/
   font-size: 20px;
  }

  img {
    width: 200px;
    height: 200px;
    border:10px solid #557FFF;
  }
  </style>
</head>
<body>
  
  <div><p id="scratchable"><img src="sc4.jpg"></img></p></div>
  <script src="ScratchCard.js"></script>
  <script>ScratchCard(document.querySelector('p'));</script>
  <script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-60834029-1', 'auto');
  ga('send', 'pageview');

  </script>
</body>
</html>

I do not know what is wrong with this code but i really need help on that one.

wfareed
  • 139
  • 2
  • 17

1 Answers1

0

To ensure you don't end up with unintended behavior, detect what device is being used and only add event listeners for that device. If you are using touchscreen, then do not add mouse event listeners, and vice-versa.

The rest looks technically correct, you are using touchstart to create the touchmove event listener, then on touchend you remove the touchmove listener. The touchmove would be the only event that contains the scratchMove code, so that should all be good.

I would mostly concentrate on the first paragraph here and only set up event listeners that are related to the device/environment.

In your javascript, you can add this assignment:

var isTouch = 'ontouchstart' in document.documentElement;

Then in each place you are assigning the events, do this:

   if(isTouch) {
      canvas.addEventListener('touchmove', scratchMove);
      document.addEventListener('touchend', scratchEnd);
   } else {
      canvas.addEventListener('mousemove', scratchMove);
      document.addEventListener('mouseup', scratchEnd);
   }
gmiley
  • 6,531
  • 1
  • 13
  • 25
  • But i want to be able to use the code for both devices , PC and touch screen phone. – wfareed May 30 '16 at 00:21
  • You could use it for both, it would detect at run-time which device is currently loading the page and only use the events appropriate for that device at run-time. – gmiley May 30 '16 at 00:23
  • So the code here is correct ? if so , why it is not functioning properly ?? – wfareed May 30 '16 at 00:26
  • Because, like I said, the events could be getting crossed due to having both click and touch events. Some devices might register both and may be firing the events in an unpredictable way. See my edit above. – gmiley May 30 '16 at 00:31
  • in var isTouch is documentElement here is canvas ?? – wfareed May 30 '16 at 18:19
  • It is checking to see if `ontouchstart` is an available event for the current instance. It is basically checking to see if you are loading the site on a device that has the `ontouchscreen` event available to it. – gmiley May 30 '16 at 20:15
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/113357/discussion-between-wfareed-and-gmiley). – wfareed May 30 '16 at 22:40