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 相关文章推荐
Javascript实例教程(19) 使用HoTMetal(1)
Dec 23 Javascript
javascript 写类方式之一
Jul 05 Javascript
jQuery函数的等价原生函数代码示例
May 27 Javascript
javascript通过navigator.userAgent识别各种浏览器
Oct 25 Javascript
通过action传过来的值在option获取进行验证的方法
Nov 14 Javascript
轻松掌握JavaScript中的Math object数学对象
May 26 Javascript
浅谈JavaScript中小数和大整数的精度丢失
May 31 Javascript
JS实现含有中文字符串的友好截取功能分析
Mar 13 Javascript
Node.js简单入门前传
Aug 21 Javascript
nginx配置React静态页面的方法教程
Nov 03 Javascript
express启用https使用小记
May 21 Javascript
js获取图片的base64编码并压缩
Dec 05 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
239军机修复记
2021/03/02 无线电
IIS6+PHP5+MySQL5+Zend Optimizer+phpMyAdmin安装配置图文教程 2009年
2009/06/08 PHP
tp5(thinkPHP5框架)时间查询操作实例分析
2019/05/29 PHP
JavaScript中“+=”的应用
2007/02/02 Javascript
DOM相关内容速查手册
2007/02/07 Javascript
jquery.alert 弹出式复选框实现代码
2009/06/15 Javascript
实现连缀调用的map方法(prototype)
2009/08/05 Javascript
用nodejs写的一个简单项目打包工具
2013/05/11 NodeJs
js读取被点击次数的简单实例(从数据库中读取)
2014/03/07 Javascript
jQuery获取复选框被选中数量及判断选择值的方法详解
2016/05/25 Javascript
React.Js添加与删除onScroll事件的方法详解
2017/11/03 Javascript
JS 中可以提升幸福度的小技巧(可以识别更多另类写法)
2018/07/28 Javascript
在js代码拼接dom对象到页面上的模板总结
2018/10/21 Javascript
node crawler如何添加promise支持
2020/02/01 Javascript
javascript实现点击产生随机图形
2021/01/25 Javascript
[06:57]DOTA2-DPC中国联赛 正赛 Ehome vs PSG.LGD 选手采访
2021/03/11 DOTA
wxpython 学习笔记 第一天
2009/02/09 Python
python逐行读取文件内容的三种方法
2014/01/20 Python
pip 错误unused-command-line-argument-hard-error-in-future解决办法
2014/06/01 Python
对python使用http、https代理的实例讲解
2018/05/07 Python
利用python-pypcap抓取带VLAN标签的数据包方法
2019/07/23 Python
python文字转语音的实例代码分析
2019/11/12 Python
python绘制BA无标度网络示例代码
2019/11/21 Python
python paramiko远程服务器终端操作过程解析
2019/12/14 Python
Pytorch 实现focal_loss 多类别和二分类示例
2020/01/14 Python
Python selenium如何打包静态网页并下载
2020/08/12 Python
python高级特性简介
2020/08/13 Python
Python利用imshow制作自定义渐变填充柱状图(colorbar)
2020/12/10 Python
Urban Outfitters美国官网:美国生活方式品牌
2016/08/26 全球购物
英国健身专家:WIT Fitness
2021/02/09 全球购物
2014学生会工作总结报告
2014/12/02 职场文书
继承公证书格式
2015/01/26 职场文书
小学六一主持词开场白
2015/05/28 职场文书
2015中秋祝酒词
2015/08/12 职场文书
Spring Data JPA框架持久化存储数据到数据库
2022/04/28 Java/Android
SpringBoot使用AOP实现统计全局接口访问次数详解
2022/06/16 Java/Android