AngularJS 仿微信图片手势缩放的实例


Posted in Javascript onSeptember 28, 2017

AngularJS 仿微信图片手势缩放的实例

前言:

AngularJS 仿微信图片手势缩放的实例

最近,公司做一个混合应用项目,涉及到一个图片缩放功能,类似微信那样支持touch事件。

亲测,实现方案很不错,所以放出来,和大家分享一下,希望有人能用得到。

核心思想就是用到了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;
};

上面代码中我们新建了一个directive,方便多个地方重用。

当我们建立好directive时候,该如何使用呢?

<img style="width:100%;" src="assets/images/floorplan.jpeg" ng-pinch-zoom>

我们只需要在img文件上设定一个属性即可,是不是很简单呢?

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Javascript 相关文章推荐
解决FireFox下[使用event很麻烦]的问题
Nov 26 Javascript
js判断数据类型如判断是否为数组是否为字符串等等
Jan 15 Javascript
jQuery对象的selector属性用法实例
Dec 27 Javascript
jQuery Ajax中的事件详细介绍
Apr 16 Javascript
JavaScript实现的Tween算法及缓冲特效实例代码
Nov 03 Javascript
jquery实现树形菜单完整代码
Dec 29 Javascript
javascript实现数组去重的多种方法
Mar 14 Javascript
微信小程序 devtool隐藏的秘密
Jan 21 Javascript
详解Angular 中 ngOnInit 和 constructor 使用场景
Jun 22 Javascript
详解Nuxt.js部署及踩过的坑
Aug 07 Javascript
axios携带cookie配置详解(axios+koa)
Dec 28 Javascript
JS数组扁平化(flat)方法总结详解
Jun 24 Javascript
AngularJS路由删除#符号解决的办法
Sep 28 #Javascript
深入理解React高阶组件
Sep 28 #Javascript
基于webpack 实用配置方法总结
Sep 28 #Javascript
XMLHttpRequest对象_Ajax异步请求重点(推荐)
Sep 28 #Javascript
JQuery 选择器、DOM节点操作练习实例
Sep 28 #jQuery
浅谈JavaScript find 方法不支持IE的问题
Sep 28 #Javascript
VueJS事件处理器v-on的使用方法
Sep 27 #Javascript
You might like
php去除重复字的实现代码
2011/09/16 PHP
PHP生成自定义长度随机字符串的函数分享
2014/05/04 PHP
四种php中webservice实现的简单架构方法及实例
2015/02/03 PHP
php生成curl命令行的方法
2015/12/14 PHP
PHP  Yii清理缓存的实现方法
2016/11/10 PHP
JS动画效果代码3
2008/04/03 Javascript
javascript 密码强弱度检测万能插件
2009/02/25 Javascript
javascript 操作cookies及正确使用cookies的属性
2009/10/15 Javascript
js 日期比较相关天数代码
2014/04/02 Javascript
JS+CSS相对定位实现的下拉菜单
2015/10/06 Javascript
修复jQuery tablesorter无法正确排序的bug(加千分位数字后)
2016/03/30 Javascript
JavaScript的this关键字的理解
2016/06/18 Javascript
完美实现八种js焦点轮播图(下篇)
2020/04/20 Javascript
jQuery EasyUi 验证功能实例解析
2017/01/06 Javascript
详解Vue微信公众号开发踩坑全记录
2017/08/21 Javascript
cordova入门基础教程及使用中遇到的一些问题总结
2017/11/14 Javascript
css和js实现弹出登录居中界面完整代码
2017/11/26 Javascript
基于jquery.page.js实现分页效果
2018/01/01 jQuery
用jQuery将JavaScript对象转换为querystring查询字符串的方法
2018/11/12 jQuery
详解基于Vue,Nginx的前后端不分离部署教程
2018/12/04 Javascript
Vue中props的详解
2019/05/16 Javascript
javascript设计模式 ? 访问者模式原理与用法实例分析
2020/04/26 Javascript
JavaScript如何操作css
2020/10/24 Javascript
[45:06]完美世界DOTA2联赛PWL S2 Magma vs InkIce 第二场 11.28
2020/12/02 DOTA
深入剖析Python的爬虫框架Scrapy的结构与运作流程
2016/01/20 Python
python 字典操作提取key,value的方法
2019/06/26 Python
Django2 连接MySQL及model测试实例分析
2019/12/10 Python
HTML5中的音频和视频媒体播放元素小结
2016/01/29 HTML / CSS
巴基斯坦电子产品购物网站:Home Shopping
2017/09/14 全球购物
英国网络托管和域名领导者:Web Hosting UK
2017/10/15 全球购物
机械专业毕业生推荐信范文
2013/11/25 职场文书
经贸专业毕业生求职信
2014/03/23 职场文书
公司法定代表人授权委托书
2014/09/29 职场文书
《文化苦旅》读后感:阅读,让人诗意地栖居在大地上
2019/12/24 职场文书
基于Go Int转string几种方式性能测试
2021/04/28 Golang
python百行代码实现汉服圈图片爬取
2021/11/23 Python