anchor.diff:  
       zoomCamera() {
   
  -      var factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * zoomSpeed;
  -
  -      if ( factor != 1.0 && factor > 0.0 ) {
  +      if (_state == STATE.TOUCH_ZOOM_PAN) {
  +
  +        var factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;
  +
  +        _touchZoomDistanceStart = _touchZoomDistanceEnd;
   
           _eye.scale( factor );
   
  -        if ( staticMoving ) {
  -
  -          _zoomStart.setFrom(_zoomEnd);
  -
  -        } else {
  -
  -          _zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;
  +      } else {
  +
  +        var factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * zoomSpeed;
  +
  +        if ( factor != 1.0 && factor > 0.0 ) {
  +
  +          _eye.scale( factor );
  +
  +          if ( staticMoving ) {
  +
  +            _zoomStart.setFrom(_zoomEnd);
  +
  +          } else {
  +
  +            _zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;
  +
  +          }
   
           }
   
  
positive.code:       switch ( event.touches.length ) {
  
          case 1:
            _rotateStart = getMouseProjectionOnBall( event.touches[ 0 ].page.x, event.touches[ 0 ].page.y );
            _rotateEnd.setFrom(_rotateStart);
            break;
          case 2:
            _zoomStart = _zoomEnd = getMouseOnScreen( event.touches[ 0 ].page.x, event.touches[ 0 ].page.y );
            break;
          case 3:
            _panStart = _panEnd = getMouseOnScreen( event.touches[ 0 ].page.x, event.touches[ 0 ].page.y );
            break;
  
        }
  
      }
  
negative.code:           _rotateEnd = getMouseProjectionOnBall( event.touches[ 0 ].page.x, event.touches[ 0 ].page.y );
            break;
          case 2:
            var dx = event.touches[ 0 ].page.x - event.touches[ 1 ].page.x;
            var dy = event.touches[ 0 ].page.y - event.touches[ 1 ].page.y;
            _touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );
  
            var x = ( event.touches[ 0 ].page.x + event.touches[ 1 ].page.x ) / 2;
            var y = ( event.touches[ 0 ].page.y + event.touches[ 1 ].page.y ) / 2;
            _panEnd = getMouseOnScreen( x, y );
            break;
          default:
            _state = STATE.NONE;
            break;
  
        }
  
      }
  
      touchend( TouchEvent event ) {
  
        if ( !enabled ) { return; }
  
        switch ( event.touches.length ) {
  
          case 1:
            _rotateEnd = getMouseProjectionOnBall( event.touches[ 0 ].page.x, event.touches[ 0 ].page.y );
            _rotateStart.setFrom( _rotateEnd );
            break;
  
          case 2:
            _touchZoomDistanceStart = _touchZoomDistanceEnd = 0.0;
  
            var x = ( event.touches[ 0 ].page.x + event.touches[ 1 ].page.x ) / 2;
            var y = ( event.touches[ 0 ].page.y + event.touches[ 1 ].page.y ) / 2;
            _panEnd =  getMouseOnScreen( x, y );
            _panStart.setFrom( _panEnd );
            break;
  
        }
  
        _state = STATE.NONE;
      }
  
      void unlisten() {
  