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 相关文章推荐
用jquery ajax获取网站Alexa排名的代码
Dec 12 Javascript
JQuery之focus函数使用介绍
Aug 20 Javascript
jquery选择器之内容过滤选择器详解
Jan 27 Javascript
iframe里的页面禁止右键事件的方法
Jun 10 Javascript
node.js连接mongoDB数据库 快速搭建自己的web服务
Apr 17 Javascript
js设置文字颜色的方法示例
Dec 30 Javascript
深入理解React高阶组件
Sep 28 Javascript
iview给radio按钮组件加点击事件的实例
Sep 30 Javascript
微信小程序支付前端源码
Aug 29 Javascript
Vue加载json文件的方法简单示例
Jan 28 Javascript
vue2配置scss的方法步骤
Jun 06 Javascript
Vue最新防抖方案(必看篇)
Oct 30 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
phpmailer发送gmail邮件实例详解
2013/06/24 PHP
浅谈PHP实现大流量下抢购方案
2017/12/15 PHP
如何使用JS获取IE上传文件路径(IE7,8)
2013/07/08 Javascript
jquery放大镜效果超漂亮噢
2013/11/15 Javascript
深入浅出分析javaScript中this用法
2015/05/09 Javascript
jQuery验证插件validate使用方法详解
2020/09/13 Javascript
AngularJS基础 ng-model 指令详解及示例代码
2016/08/02 Javascript
bootstrap table小案例
2016/10/21 Javascript
javascript鼠标跟随运动3种效果(眼球效果,苹果菜单,方向跟随)
2016/10/27 Javascript
基于JS分页控件实现简单美观仿淘宝分页按钮效果
2016/11/07 Javascript
jQuery源码分析之sizzle选择器详解
2017/02/13 Javascript
js Canvas绘制圆形时钟效果
2017/02/17 Javascript
微信小程序dom操作的替代思路实例分析
2018/12/06 Javascript
微信小程序实现上传word、txt、Excel、PPT等文件功能
2019/05/23 Javascript
为nuxt项目写一个面包屑cli工具实现自动生成页面与面包屑配置
2019/09/29 Javascript
在pycharm中开发vue的方法步骤
2020/03/04 Javascript
详解Vue之事件处理
2020/07/10 Javascript
vue打包npm run build时候界面报错的解决
2020/08/13 Javascript
[01:07:02]DOTA2-DPC中国联赛 正赛 iG vs PSG.LGD BO3 第三场 2月26日
2021/03/11 DOTA
Python黑魔法Descriptor描述符的实例解析
2016/06/02 Python
python设计模式大全
2016/06/27 Python
wxpython中自定义事件的实现与使用方法分析
2016/07/21 Python
Python生成随机密码的方法
2017/06/16 Python
python使用tensorflow保存、加载和使用模型的方法
2018/01/31 Python
python最长回文串算法
2018/06/04 Python
详解python单元测试框架unittest
2018/07/02 Python
在python中对变量判断是否为None的三种方法总结
2019/01/23 Python
啥是佩奇?使用Python自动绘画小猪佩奇的代码实例
2019/02/20 Python
利用django创建一个简易的博客网站的示例
2020/09/29 Python
CSS3弹性盒模型开发笔记(一)
2016/04/26 HTML / CSS
2019年Java 最常见的 面试题
2016/10/19 面试题
爷爷追悼会答谢词
2014/01/24 职场文书
幼儿园校园小喇叭广播稿
2014/10/17 职场文书
预备党员群众意见
2015/06/01 职场文书
使用canvas实现雪花飘动效果的示例代码
2021/03/30 HTML / CSS
Matlab如何实现矩阵复制扩充
2021/06/02 Python