First Evaluation

Files modified in this directory. https://github.com/vchilkuri/vchilkuri.github.io/blob/master/src/ccNetViz.js

  let offset = 2.0 * nodeStyle.maxSize; //added offset for screenspace GSoC 17
  /* GSoc 17 code for touch events */
    this.enableTouch = function(image){
          if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
              // some code only for small devices..
              //alert(44);
              /*var image = new Image();
              image.src = this.image();*/
              var width = canvas.width;
        var height = canvas.height;
        if ( $( "#body" ).length ){
          $( "#container" ).css('position','absolute');
          $( "#container" ).css('visibility','hidden');
        }

              if ( $( "#mycanvas" ).length ) {
                  //$( "#mycanvas" ).remove();
                  /*
                  $('<canvas>').attr({
                      id: 'mycanvas'
                  }).css({
                      width: width + 'px',
                      height: height + 'px',
                  }).appendTo('#body');
                  $('#mycanvas').css("border","1px solid black");*/
                  //canvas already exists
              }
              else{
          if ( $( "#body" ).length ){
            $('<canvas>').attr({
              id: 'mycanvas'
            }).css({
              width: width + 'px',
              height: height + 'px',
            }).appendTo('#body');

            $('#mycanvas').css("border","1px solid black");
          }
              }

        if ( $( "#body" ).length ){
          var gesturableImg = new ImgTouchCanvas({
            canvas: document.getElementById('mycanvas'),
            path: this.image(),
            desktop: true
          });
        }
          }
    }
  /* code to enable touch events ends */

The code below is the function defined to add all the touch events. The mouse events were added again to modify them by comparing it with similar touch events.

/* Touch events function start GSoC 17*/
    class ImgTouchCanvas {
        constructor(options){
            if( !options || !options.canvas || !options.path) {
                throw 'ImgZoom constructor: missing arguments canvas or path';
            }

            this.canvas         = options.canvas;
            this.canvas.width   = this.canvas.clientWidth;
            this.canvas.height  = this.canvas.clientHeight;
            this.context        = this.canvas.getContext('2d');

            this.desktop = options.desktop || false; //non touch events

            this.position = {
                x: 0,
                y: 0
            };
            this.scale = {
                x: 0.5,
                y: 0.5
            };
            this.imgTexture = new Image();
            this.imgTexture.src = options.path;

            this.lastZoomScale = null;
            this.lastX = null;
            this.lastY = null;

            this.mdown = false; //desktop drag

            this.init = false;
            this.checkRequestAnimationFrame();
            requestAnimationFrame(this.animate.bind(this));

            this.setEventListeners();
        }

        animate() {
            //set scale such as image cover all the canvas
            if(!this.init) {
                if(this.imgTexture.width) {
                    var scaleRatio = null;
                    if(this.canvas.clientWidth > this.canvas.clientHeight) {
                        scaleRatio = this.canvas.clientWidth / this.imgTexture.width;
                    }
                    else {
                        scaleRatio = this.canvas.clientHeight / this.imgTexture.height;
                    }

                    this.scale.x = scaleRatio;
                    this.scale.y = scaleRatio;
                    this.init = true;
                }
            }

            this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);

            this.context.drawImage(
                this.imgTexture,
                this.position.x, this.position.y,
                this.scale.x * this.imgTexture.width,
                this.scale.y * this.imgTexture.height);

            requestAnimationFrame(this.animate.bind(this));
        }


        gesturePinchZoom(event) {
            var zoom = false;

            if( event.targetTouches.length >= 2 ) {
                var p1 = event.targetTouches[0];
                var p2 = event.targetTouches[1];
                var zoomScale = Math.sqrt(Math.pow(p2.pageX - p1.pageX, 2) + Math.pow(p2.pageY - p1.pageY, 2)); //euclidian distance

                if( this.lastZoomScale ) {
                    zoom = zoomScale - this.lastZoomScale;
                }

                this.lastZoomScale = zoomScale;
            }

            return zoom;
        }

        doZoom(zoom) {
            if(!zoom) return;

            //new scale
            var currentScale = this.scale.x;
            var newScale = this.scale.x + zoom/100;


            //some helpers
            var deltaScale = newScale - currentScale;
            var currentWidth    = (this.imgTexture.width * this.scale.x);
            var currentHeight   = (this.imgTexture.height * this.scale.y);
            var deltaWidth  = this.imgTexture.width*deltaScale;
            var deltaHeight = this.imgTexture.height*deltaScale;


            //by default scale doesnt change position and only add/remove pixel to right and bottom
            //so we must move the image to the left to keep the image centered
            //ex: coefX and coefY = 0.5 when image is centered <=> move image to the left 0.5x pixels added to the right
            var canvasmiddleX = this.canvas.clientWidth / 2;
            var canvasmiddleY = this.canvas.clientHeight / 2;
            var xonmap = (-this.position.x) + canvasmiddleX;
            var yonmap = (-this.position.y) + canvasmiddleY;
            var coefX = -xonmap / (currentWidth);
            var coefY = -yonmap / (currentHeight);
            var newPosX = this.position.x + deltaWidth*coefX;
            var newPosY = this.position.y + deltaHeight*coefY;

            //edges cases
            var newWidth = currentWidth + deltaWidth;
            var newHeight = currentHeight + deltaHeight;

            if( newWidth < this.canvas.clientWidth ) return;
            if( newPosX > 0 ) { newPosX = 0; }
            if( newPosX + newWidth < this.canvas.clientWidth ) { newPosX = this.canvas.clientWidth - newWidth;}

            if( newHeight < this.canvas.clientHeight ) return;
            if( newPosY > 0 ) { newPosY = 0; }
            if( newPosY + newHeight < this.canvas.clientHeight ) { newPosY = this.canvas.clientHeight - newHeight; }


            //finally affectations
            this.scale.x    = newScale;
            this.scale.y    = newScale;
            this.position.x = newPosX;
            this.position.y = newPosY;
        }

        doMove(relativeX, relativeY) {
            if(this.lastX && this.lastY) {
                var deltaX = relativeX - this.lastX;
                var deltaY = relativeY - this.lastY;
                var currentWidth = (this.imgTexture.width * this.scale.x);
                var currentHeight = (this.imgTexture.height * this.scale.y);

                this.position.x += deltaX;
                this.position.y += deltaY;


                //edge cases
                if( this.position.x > 0 ) {
                this.position.x = 0;
                }
                else if( this.position.x + currentWidth < this.canvas.clientWidth ) {
                this.position.x = this.canvas.clientWidth - currentWidth;
                }
                if( this.position.y > 0 ) {
                this.position.y = 0;
                }
                else if( this.position.y + currentHeight < this.canvas.clientHeight ) {
                this.position.y = this.canvas.clientHeight - currentHeight;
                }
            }

            this.lastX = relativeX;
            this.lastY = relativeY;
        }

        setEventListeners() {
            // touch
            this.canvas.addEventListener('touchstart', function(e) {
                this.lastX          = null;
                this.lastY          = null;
                this.lastZoomScale  = null;
            }.bind(this));

            this.canvas.addEventListener('touchmove', function(e) {
                e.preventDefault();

                if(e.targetTouches.length == 2) { //pinch
                    this.doZoom(this.gesturePinchZoom(e));
                }
                else if(e.targetTouches.length == 1) {
                    var relativeX = e.targetTouches[0].pageX - this.canvas.getBoundingClientRect().left;
                    var relativeY = e.targetTouches[0].pageY - this.canvas.getBoundingClientRect().top;
                    this.doMove(relativeX, relativeY);
                }
            }.bind(this));

            if(this.desktop) {
                // keyboard+mouse
                window.addEventListener('keyup', function(e) {
                    if(e.keyCode == 187 || e.keyCode == 61) { //+
                        this.doZoom(5);
                    }
                    else if(e.keyCode == 54) {//-
                        this.doZoom(-5);
                    }
                }.bind(this));

                window.addEventListener('mousedown', function(e) {
                    this.mdown = true;
                    this.lastX = null;
                    this.lastY = null;
                }.bind(this));

                window.addEventListener('mouseup', function(e) {
                    this.mdown = false;
                }.bind(this));

                window.addEventListener('mousemove', function(e) {
                    var relativeX = e.pageX - this.canvas.getBoundingClientRect().left;
                    var relativeY = e.pageY - this.canvas.getBoundingClientRect().top;

                    if(e.target == this.canvas && this.mdown) {
                        this.doMove(relativeX, relativeY);
                    }

                    if(relativeX <= 0 || relativeX >= this.canvas.clientWidth || relativeY <= 0 || relativeY >= this.canvas.clientHeight) {
                        this.mdown = false;
                    }
                }.bind(this));
            }
        }

        checkRequestAnimationFrame() {
            var lastTime = 0;
            var vendors = ['ms', 'moz', 'webkit', 'o'];
            for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
                window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
                window.cancelAnimationFrame =
                    window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
            }

            if (!window.requestAnimationFrame) {
                window.requestAnimationFrame = function(callback, element) {
                    var currTime = new Date().getTime();
                    var timeToCall = Math.max(0, 16 - (currTime - lastTime));
                    var id = window.setTimeout(function() { callback(currTime + timeToCall); },
                        timeToCall);
                    lastTime = currTime + timeToCall;
                    return id;
                };
            }

            if (!window.cancelAnimationFrame) {
                window.cancelAnimationFrame = function(id) {
                    clearTimeout(id);
                };
            }
        }
    };

  /* touch event function ends*/

results matching ""

    No results matching ""