AngularJS 仿微信圖片手勢(shì)縮放的實(shí)例
AngularJS 仿微信圖片手勢(shì)縮放的實(shí)例
前言:

最近,公司做一個(gè)混合應(yīng)用項(xiàng)目,涉及到一個(gè)圖片縮放功能,類似微信那樣支持touch事件。
親測(cè),實(shí)現(xiàn)方案很不錯(cuò),所以放出來,和大家分享一下,希望有人能用得到。
核心思想就是用到了CSS3的transform屬性, 不多說,我們看代碼:
'use strict';
/**
* @ngInject
*/
module.exports = function () {
var _directive = {
restrict : 'A',
scope : false,
link : _link
};
function _link(scope, element, attrs) {
var elWidth, elHeight;
// mode : 'pinch' or 'swipe'
var mode = '';
// distance between two touche points (mode : 'pinch')
var distance = 0;
var initialDistance = 0;
// image scaling
var scale = 1;
var relativeScale = 1;
var initialScale = 1;
var maxScale = parseInt(attrs.maxScale, 10);
if (isNaN(maxScale) || maxScale <= 1) {
maxScale = 3;
}
// position of the upper left corner of the element
var positionX = 0;
var positionY = 0;
var initialPositionX = 0;
var initialPositionY = 0;
// central origin (mode : 'pinch')
var originX = 0;
var originY = 0;
// start coordinate and amount of movement (mode : 'swipe')
var startX = 0;
var startY = 0;
var moveX = 0;
var moveY = 0;
var image = new Image();
image.onload = function() {
elWidth = element[0].clientWidth;
elHeight = element[0].clientHeight;
element.css({
'-webkit-transform-origin' : '0 0',
'transform-origin' : '0 0'
});
element.on('touchstart', touchstartHandler);
element.on('touchmove', touchmoveHandler);
element.on('touchend', touchendHandler);
};
if (attrs.ngSrc) {
image.src = attrs.ngSrc;
} else {
image.src = attrs.src;
}
/**
* @param {object} evt
*/
function touchstartHandler(evt) {
var touches = evt.originalEvent ? evt.originalEvent.touches : evt.touches;
startX = touches[0].clientX;
startY = touches[0].clientY;
initialPositionX = positionX;
initialPositionY = positionY;
moveX = 0;
moveY = 0;
}
/**
* @param {object} evt
*/
function touchmoveHandler(evt) {
var touches = evt.originalEvent ? evt.originalEvent.touches : evt.touches;
if (mode === '') {
if (touches.length === 1 && scale > 1) {
mode = 'swipe';
} else if (touches.length === 2) {
mode = 'pinch';
initialScale = scale;
initialDistance = getDistance(touches);
originX = touches[0].clientX -
parseInt((touches[0].clientX - touches[1].clientX) / 2, 10) -
element[0].offsetLeft - initialPositionX;
originY = touches[0].clientY -
parseInt((touches[0].clientY - touches[1].clientY) / 2, 10) -
element[0].offsetTop - initialPositionY;
}
}
if (mode === 'swipe') {
evt.preventDefault();
moveX = touches[0].clientX - startX;
moveY = touches[0].clientY - startY;
positionX = initialPositionX + moveX;
positionY = initialPositionY + moveY;
transformElement();
} else if (mode === 'pinch') {
evt.preventDefault();
distance = getDistance(touches);
relativeScale = distance / initialDistance;
scale = relativeScale * initialScale;
positionX = originX * (1 - relativeScale) + initialPositionX + moveX;
positionY = originY * (1 - relativeScale) + initialPositionY + moveY;
transformElement();
}
}
/**
* @param {object} evt
*/
function touchendHandler(evt) {
var touches = evt.originalEvent ? evt.originalEvent.touches : evt.touches;
if (mode === '' || touches.length > 0) {
return;
}
if (scale < 1) {
scale = 1;
positionX = 0;
positionY = 0;
} else if (scale > maxScale) {
scale = maxScale;
relativeScale = scale / initialScale;
positionX = originX * (1 - relativeScale) + initialPositionX + moveX;
positionY = originY * (1 - relativeScale) + initialPositionY + moveY;
} else {
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);
mode = '';
}
/**
* @param {Array} touches
* @return {number}
*/
function getDistance(touches) {
var d = Math.sqrt(Math.pow(touches[0].clientX - touches[1].clientX, 2) +
Math.pow(touches[0].clientY - touches[1].clientY, 2));
return parseInt(d, 10);
}
/**
* @param {number} [duration]
*/
function transformElement(duration) {
var transition = duration ? 'all cubic-bezier(0,0,.5,1) ' + duration + 's' : '';
var matrixArray = [scale, 0, 0, scale, positionX, positionY];
var matrix = 'matrix(' + matrixArray.join(',') + ')';
element.css({
'-webkit-transition' : transition,
transition : transition,
'-webkit-transform' : matrix + ' translate3d(0,0,0)',
transform : matrix
});
}
}
return _directive;
};
上面代碼中我們新建了一個(gè)directive,方便多個(gè)地方重用。
當(dāng)我們建立好directive時(shí)候,該如何使用呢?
<img style="width:100%;" src="assets/images/floorplan.jpeg" ng-pinch-zoom>
我們只需要在img文件上設(shè)定一個(gè)屬性即可,是不是很簡(jiǎn)單呢?
如有疑問請(qǐng)留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
利用Ionic2 + angular4實(shí)現(xiàn)一個(gè)地區(qū)選擇組件
ionic是一個(gè)移動(dòng)端開發(fā)框架,使用hybird技術(shù),只要使用前端開發(fā)技術(shù)就可以開發(fā)出電腦端,安卓端和ios端的站點(diǎn)程序。下面這篇文章主要給大家介紹了關(guān)于利用Ionic2 + angular4實(shí)現(xiàn)一個(gè)地區(qū)選擇組件的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。2017-07-07
Angular實(shí)現(xiàn)svg和png圖片下載實(shí)現(xiàn)
這篇文章主要介紹了Angular實(shí)現(xiàn)svg和png圖片下載實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
詳解angularjs 學(xué)習(xí)之 scope作用域
本篇文章主要介紹了詳解angularjs 學(xué)習(xí)之 scope作用域,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-01-01
Angularjs的ng-repeat中去除重復(fù)數(shù)據(jù)的方法
這篇文章主要介紹了Angularjs的ng-repeat中去除重復(fù)數(shù)據(jù)的方法,涉及AngularJS針對(duì)重復(fù)數(shù)據(jù)的遍歷與過濾技巧,需要的朋友可以參考下2016-08-08
詳解AngularJS中$http緩存以及處理多個(gè)$http請(qǐng)求的方法
$http 是 AngularJS 中的一個(gè)核心服務(wù),用于讀取遠(yuǎn)程服務(wù)器的數(shù)據(jù),通過本文給大家介紹AngularJS中$http緩存以及處理多個(gè)$http請(qǐng)求的方法,希望的朋友一起學(xué)習(xí)吧2016-02-02
AngularJS基礎(chǔ) ng-model-options 指令簡(jiǎn)單示例
本文主要介紹AngularJS ng-model-options 指令,這里對(duì)ng-model-options指令的基本資料進(jìn)行整理,有需要的小伙伴可以參考下2016-08-08

