Skip to content

Instantly share code, notes, and snippets.

@ktknest
Last active July 10, 2018 07:51
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save ktknest/5276f368c92bc1ce4dda to your computer and use it in GitHub Desktop.
Save ktknest/5276f368c92bc1ce4dda to your computer and use it in GitHub Desktop.
pinch zoom in/out directive for AngularJS
/**
* NOTICE:
* This directive is old version!!
* Please check this repository:
* https://github.com/ktknest/angular-pinch-zoom
* /
// sample: http://codepen.io/ktknest/full/LDljw/
angular.module('app', [])
/**
* @ngdoc directive
* @name pinchZoom
* @restrict A
* @scope false
*
* @description
* 要素のピンチアウト・インでの拡大・縮小、拡大時のスワイプ動作を提供
*
**/
.directive('pinchZoom', function() {
var _directive = {
restrict : 'A',
scope : false,
link : _link
};
function _link(scope, element, attrs) {
var elWidth = element[0].offsetWidth;
var elHeight = element[0].offsetHeight;
// モード(pinch or swipe)
var mode = '';
// ピンチ時の2点間の距離
var distance = 0;
var initialDistance = 0;
// 拡大率
var scale = 1;
var relativeScale = 1;
var initialScale = 1;
var MAX_SCALE = 3;
// 要素の左上端の座標
var positionX = 0;
var positionY = 0;
var initialPositionX = 0;
var initialPositionY = 0;
// ピンチ時の中心座標
var originX = 0;
var originY = 0;
// スワイプ時のスタート座標・移動量
var startX = 0;
var startY = 0;
var moveX = 0;
var moveY = 0;
element.css({
'-webkit-transform-origin' : '0 0',
'transform-origin' : '0 0'
});
element.on('touchstart', function(evt) {
startX = evt.touches[0].pageX;
startY = evt.touches[0].pageY;
initialPositionX = positionX;
initialPositionY = positionY;
moveX = 0;
moveY = 0;
mode = '';
if (evt.touches.length === 2) {
initialScale = scale;
initialDistance = getDistance(evt);
originX = evt.touches[0].pageX -
parseInt((evt.touches[0].pageX - evt.touches[1].pageX) / 2, 10) -
element[0].offsetLeft - initialPositionX;
originY = evt.touches[0].pageY -
parseInt((evt.touches[0].pageY - evt.touches[1].pageY) / 2, 10) -
element[0].offsetTop - initialPositionY;
}
});
element.on('touchmove', function(evt) {
evt.preventDefault();
if (mode === 'swipe' && scale > 1) {
moveX = evt.touches[0].pageX - startX;
moveY = evt.touches[0].pageY - startY;
positionX = initialPositionX + moveX;
positionY = initialPositionY + moveY;
transformElement();
} else if (mode === 'pinch') {
distance = getDistance(evt);
relativeScale = distance / initialDistance;
scale = relativeScale * initialScale;
positionX = originX * (1 - relativeScale) + initialPositionX + moveX;
positionY = originY * (1 - relativeScale) + initialPositionY + moveY;
transformElement();
} else {
if (evt.touches.length === 1) {
mode = 'swipe';
} else if (evt.touches.length === 2) {
mode = 'pinch';
}
}
transformElement();
});
element.on('touchend', function(evt) {
if (mode === 'pinch') {
if (scale < 1) {
scale = 1;
positionX = 0;
positionY = 0;
} else if (scale > MAX_SCALE) {
scale = MAX_SCALE;
relativeScale = scale / initialScale;
positionX = originX * (1 - relativeScale) + initialPositionX + moveX;
positionY = originY * (1 - relativeScale) + initialPositionY + moveY;
}
}
if (scale > 1) {
if (positionX > 0) {
positionX = 0;
} else if (positionX < elWidth * (1 - scale)) {
positionX = elWidth * (1 - scale);
}
if (positionY > 0) {
positionY = 0;
} else if (positionY < elHeight * (1 - scale)) {
positionY = elHeight * (1 - scale);
}
}
transformElement(0.1);
});
function getDistance(evt) {
var d = Math.sqrt(Math.pow(evt.touches[0].pageX - evt.touches[1].pageX, 2) +
Math.pow(evt.touches[0].pageY - evt.touches[1].pageY, 2));
return parseInt(d, 10);
}
function transformElement(duration) {
var transition = duration ? 'all cubic-bezier(0,0,.5,1) ' + duration + 's' : '',
matrixArray = [scale, 0, 0, scale, positionX, positionY],
matrix = 'matrix(' + matrixArray.join(',') + ')';
element.css({
'-webkit-transition' : transition,
'transition' : transition,
'-webkit-transform' : matrix + ' translate3d(0,0,0)',
'transform' : matrix
});
}
}
return _directive;
});
@Evgeny-
Copy link

Evgeny- commented Oct 28, 2014

Thank you, very useful.

P.S. If you cant declarate sizes of image, you may need add this code to the _link function.

element.on('load', function () {
    elWidth = element[0].clientWidth;
    elHeight = element[0].clientHeight;
});

@leocfox
Copy link

leocfox commented Oct 31, 2014

Hey when I turn the device to landscape the image can't be scrolled.

@sagidayan
Copy link

Is there a way that this directive wont disable the scrolling ability?

@ktknest
Copy link
Author

ktknest commented Oct 17, 2015

I made a repository of this directive.Please check it.
https://github.com/ktknest/angular-pinch-zoom

@ktknest
Copy link
Author

ktknest commented Oct 17, 2015

@Evgeny-
Thanks a lot!
I updated this directive based on your advice.

@ktknest
Copy link
Author

ktknest commented Oct 17, 2015

@leocfox @sagidayan
I fixed bug that can not be scrolled.

@vinothtcsgit
Copy link

how to find zooming in or out ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment