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 相关文章推荐
学习ExtJS TextField常用方法
Oct 07 Javascript
JavaScript 直接操作本地文件的实现代码
Dec 01 Javascript
juqery 学习之四 筛选查找
Nov 30 Javascript
jQuery on方法传递参数示例
Dec 09 Javascript
如何改进javascript代码的性能
Apr 02 Javascript
jQuery自定义滚动条完整实例
Jan 08 Javascript
AngularJS控制器controller给模型数据赋初始值的方法
Jan 04 Javascript
使用jQuery实现页面定时弹出广告效果
Aug 24 jQuery
浅谈AngularJS中使用$resource(已更新)
Sep 14 Javascript
vue下拉列表功能实例代码
Apr 08 Javascript
使用Layui搭建后台管理界面的操作方法
Sep 20 Javascript
Vue3配置axios跨域实现过程解析
Nov 25 Vue.js
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 处理图片的类实现代码
2009/10/23 PHP
PHP文件打开、关闭、写入的判断与执行代码
2011/05/24 PHP
Windows和Linux中php代码调试工具Xdebug的安装与配置详解
2014/05/08 PHP
PHP使用preg_split()分割特殊字符(元字符等)的方法分析
2017/02/04 PHP
jQuery 添加/移除CSS类实现代码
2010/02/11 Javascript
JQuery团队打造的javascript单元测试工具QUnit介绍
2010/02/26 Javascript
JavaScript 函数参数是传值(byVal)还是传址(byRef) 分享
2013/07/02 Javascript
jquery弹出框的用法示例(2)
2013/08/26 Javascript
Iframe实现跨浏览器自适应高度解决方法
2014/09/02 Javascript
javascript实现按回车键切换焦点
2015/02/09 Javascript
深入解析Backbone.js框架的依赖库Underscore.js的作用
2016/05/07 Javascript
javascript简单实现等比例缩小图片的方法
2016/07/27 Javascript
微信小程序 video组件详解
2016/10/25 Javascript
微信开发 使用picker封装省市区三级联动模板
2016/10/28 Javascript
Vue.js实战之利用vue-router实现跳转页面
2017/04/01 Javascript
javascript 取小数点后几位几种方法总结
2017/08/02 Javascript
详解swipe使用及竖屏页面滚动方法
2018/06/28 Javascript
Vue-cli3简单使用(图文步骤)
2019/04/30 Javascript
js神秘的电报密码 哈弗曼编码实现
2019/09/10 Javascript
解决vue-router 切换tab标签关闭时缓存问题
2020/07/22 Javascript
[35:39]完美世界DOTA2联赛PWL S2 FTD.C vs Rebirth 第二场 11.22
2020/11/24 DOTA
用pandas按列合并两个文件的实例
2018/04/12 Python
django中间键重定向实例方法
2019/11/10 Python
python3中sys.argv的实例用法
2020/04/24 Python
为什么说python适合写爬虫
2020/06/11 Python
Python Web项目Cherrypy使用方法镜像
2020/11/05 Python
html特殊符号示例 html特殊字符编码对照表
2014/01/14 HTML / CSS
html5超简单的localStorage实现记住密码的功能实现
2017/09/07 HTML / CSS
汽车运用工程毕业生自荐信
2013/10/29 职场文书
工程管理英文求职信
2014/03/18 职场文书
职务说明书范文
2014/05/07 职场文书
公司授权委托书格式范文
2014/10/02 职场文书
党的群众路线教育实践活动个人剖析材料
2014/10/07 职场文书
2014年人民调解工作总结
2014/12/08 职场文书
OpenCV绘制圆端矩形的示例代码
2021/08/30 Python
MySQL数据库如何使用Shell进行连接
2022/04/12 MySQL