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高级程序设计(第3版)学习笔记6 初识js对象
Oct 11 Javascript
html+javascript实现可拖动可提交的弹出层对话框效果
Aug 05 Javascript
javascript移出节点removeChild()使用介绍
Apr 03 Javascript
JavaScript实现跨浏览器的添加及删除事件绑定函数实例
Aug 04 Javascript
jquery实现超简洁的TAB选项卡效果代码
Aug 28 Javascript
Document.body.scrollTop的值总为零的快速解决办法
Jun 09 Javascript
原生js获取元素样式的简单方法
Aug 06 Javascript
jQuery Easyui使用(二)之可折叠面板动态加载无效果的解决方法
Aug 17 Javascript
老生常谈的跨域处理
Jan 11 Javascript
JavaScript使用delete删除数组元素用法示例【数组长度不变】
Jan 17 Javascript
Vue学习笔记进阶篇之vue-cli安装及介绍
Jul 18 Javascript
angularjs数组判断是否含有某个元素的实例
Feb 27 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数组函数序列之asort() - 对数组的元素值进行升序排序,保持索引关系
2011/11/02 PHP
[原创]ThinkPHP让../Public在模板不解析(直接输出)的方法
2015/10/09 PHP
Linux服务器下PHPMailer发送邮件失败的问题解决
2017/03/04 PHP
PHP mysqli事务操作常用方法分析
2017/07/22 PHP
仿服务器端脚本方式的JS模板实现方法
2007/04/27 Javascript
百度留言本js 大家可以参考下
2009/10/13 Javascript
JS实现一键回顶功能示例代码
2013/10/28 Javascript
jquery+ajax验证不通过也提交表单问题处理
2014/12/12 Javascript
JQuery中serialize()用法实例分析
2015/02/06 Javascript
详解JavaScript的策略模式编程
2015/06/24 Javascript
理解Javascript图片预加载
2016/02/23 Javascript
jQuery中Nicescroll滚动条插件的用法
2016/11/10 Javascript
jquery uploadify如何取消已上传成功文件
2017/02/08 Javascript
angularjs实现的购物金额计算工具示例
2018/05/08 Javascript
jQuery选择器选中最后一个元素,倒数第二个元素操作示例
2018/12/10 jQuery
layui 解决form表单点击无反应的问题
2019/10/25 Javascript
如何手写一个简易的 Vuex
2020/10/10 Javascript
python 实现堆排序算法代码
2012/06/05 Python
python实现JAVA源代码从ANSI到UTF-8的批量转换方法
2015/08/10 Python
python3.5 + PyQt5 +Eric6 实现的一个计算器代码
2017/03/11 Python
Python设计模式之代理模式实例详解
2019/01/19 Python
使用Python制作一个打字训练小工具
2019/10/01 Python
利用PyCharm操作Github(仓库新建、更新,代码回滚)
2019/12/18 Python
关于pytorch处理类别不平衡的问题
2019/12/31 Python
Python中无限循环需要什么条件
2020/05/27 Python
重构Python代码的六个实例
2020/11/25 Python
虚拟环境及venv和virtualenv的区别说明
2021/02/05 Python
HTML5 CSS3打造相册效果附源码下载
2014/06/16 HTML / CSS
台湾旅游网站:灿星旅游
2018/10/11 全球购物
C#可否对内存进行直接的操作
2015/02/26 面试题
竞聘医务工作人员的自我评价分享
2013/11/04 职场文书
2014年3.15团委活动总结
2014/03/16 职场文书
医院深入开展党的群众路线教育实践活动实施方案
2014/08/27 职场文书
防灾减灾标语
2014/10/07 职场文书
Vue3.0 手写放大镜效果
2021/07/25 Vue.js
docker-compose部署Yapi的方法
2022/04/08 Servers