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算法题 求任意一个1-9位不重复的N位数在该组合中的大小排列序号
Jul 21 Javascript
使用jquery读取html5 localstorage的值的方法
Jan 04 Javascript
详解jQuery事件
Jan 13 Javascript
整理关于Bootstrap排版的慕课笔记
Mar 29 Javascript
JS设置随机出现2个数字的实例代码
Jul 19 Javascript
angular $watch 一个变量的变化(实例讲解)
Aug 02 Javascript
jQuery实现的滑块滑动导航效果示例
Jun 04 jQuery
jQuery easyui datagird编辑行删除行功能的实现代码
Sep 20 jQuery
如何能分清npm cnpm npx nvm
Jan 17 Javascript
jquery实现动态改变css样式的方法分析
May 27 jQuery
Vue结合路由配置递归实现菜单栏功能
Jun 16 Javascript
详解vue父子组件状态同步的最佳方式
Sep 10 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
一个简单的自动发送邮件系统(一)
2006/10/09 PHP
PHP与SQL注入攻击[二]
2007/04/17 PHP
PHP数组遍历的几种常见方式总结
2019/02/15 PHP
PHP+Mysql分布式事务与解决方案深入理解
2021/02/27 PHP
JS的IE和Firefox兼容性集锦
2006/12/11 Javascript
javascript div 遮罩层封锁整个页面
2009/07/10 Javascript
汉化英文版的Dreamweaver CS5并自动提示jquery
2010/11/25 Javascript
js如何判断不同系统的浏览器类型
2013/10/28 Javascript
js和html5实现手机端刮刮卡抽奖效果完美兼容android/IOS
2013/11/18 Javascript
node.js中的Socket.IO使用实例
2014/11/04 Javascript
jQuery+ajax实现动态执行脚本的方法
2015/01/27 Javascript
关于cookie的初识和运用(js和jq)
2016/04/07 Javascript
HTML5+jQuery插件Quicksand实现超酷的星际争霸2兵种分类展示效果(附demo源码下载)
2016/05/25 Javascript
利用AngularJs实现京东首页轮播图效果
2016/09/08 Javascript
详解利用Angular实现多团队模块化SPA开发框架
2017/11/27 Javascript
微信小程序实现购物页面左右联动
2019/02/15 Javascript
react实现antd线上主题动态切换功能
2019/08/12 Javascript
Vue实现剪切板图片压缩功能
2020/02/04 Javascript
微信小程序云函数添加数据到数据库的方法
2020/03/04 Javascript
vue使用exif获取图片经纬度的示例代码
2020/12/11 Vue.js
[03:06]V社市场总监Dota2项目负责人Erik专访:希望更多中国玩家加入DOTA2
2014/07/11 DOTA
linux系统使用python监控apache服务器进程脚本分享
2014/01/15 Python
Python实现从url中提取域名的几种方法
2014/09/26 Python
Python3遍历目录树实现方法
2015/05/22 Python
Python实现数据库编程方法详解
2015/06/09 Python
python图像常规操作
2017/11/11 Python
python中is与双等于号“==”的区别示例详解
2017/11/21 Python
Python退出时强制运行一段代码的实现方法
2020/04/29 Python
Python爬虫谷歌Chrome F12抓包过程原理解析
2020/06/04 Python
详解python os.path.exists判断文件或文件夹是否存在
2020/11/16 Python
SCHIESSER荷兰官方网站:德国内衣专家
2020/10/09 全球购物
社区戒毒工作方案
2014/06/04 职场文书
教师个人年度总结
2015/02/11 职场文书
小学生运动会广播
2015/08/19 职场文书
关于食品安全的演讲稿范文(三篇)
2019/10/21 职场文书
Python中super().__init__()测试以及理解
2021/12/06 Python