微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

AngularJS1.x学习仿微信图片手势缩放效果实现

最近,公司做一个混合应用项目,涉及到一个图片缩放功能,类似微信那样支持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,.5,1) ' + duration + 's' : '';
            var matrixArray = [scale,0,scale,positionX,positionY];
            var matrix      = 'matrix(' + matrixArray.join(',') + ')';

            element.css({
                '-webkit-transition' : transition,transition           : transition,'-webkit-transform'  : matrix + ' translate3d(0,0)',transform            : matrix
            });
        }
    }

    return _directive;
};

上面代码中我们新建了一个directive,方便多个地方重用。

当我们建立好directive时候,该如何使用呢?

<img style="width:100%;" src="assets/images/floorplan.jpeg" ng-pinch-zoom>

我们只需要在img文件上设定一个属性即可,是不是很简单呢?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐