HTML5 圖片縮放功能

伽馬科技.攻城師發表於2016-04-15

騰訊新聞上用的外掛(xw.qq.com)

縮放外掛scale.js

(function(window, undefined) {
    var document = window.document,
        support = {
            transform3d: ("WebKitCSSMatrix" in window && "m11" in new WebKitCSSMatrix()),
            touch: ("ontouchstart" in window)
        };

    function getTranslate(x, y) {
        var distX = x,
            distY = y;
        return support.transform3d ? "translate3d(" + distX + "px, " + distY + "px, 0)" : "translate(" + distX + "px, " + distY + "px)";
    }

    function getPage(event, page) {
        return support.touch ? event.changedTouches[0][page] : event[page];
    }

    var ImagesZoom = function() {};

    ImagesZoom.prototype = {
        // 給初始化資料
        init: function(param) {
            var self = this,
                params = param || {};

            var imgList = document.querySelectorAll(params.elem + " img"),
                zoomMask = document.querySelector(".imgzoom_pack"),
                zoomImg = document.querySelector(".imgzoom_pack .imgzoom_img img"),
                zoomClose = document.querySelector(".imgzoom_pack .imgzoom_x"),
                imgSrc = "";

            self.buffMove = 3; //緩衝係數
            self.buffScale = 2; //放大係數
            self.finger = false; //觸控手指的狀態 false:單手指 true:多手指

            self._destroy();

            zoomClose.addEventListener("click", function() {
                zoomMask.style.cssText = "display:none";
                zoomImg.src = "";
                zoomImg.style.cssText = "";

                self._destroy();

                document.removeEventListener("touchmove", self.eventStop, false);
            }, false);

            for (var len = imgList.length, i = 0; i < len; i++) {
                imgList[i].addEventListener("click", function() {
                    imgSrc = this.getAttribute("src");
                    zoomMask.style.cssText = "display:block";
                    zoomImg.src = imgSrc;

                    zoomImg.onload = function() {
                        zoomImg.style.cssText = "margin-top:-" + (zoomImg.offsetHeight / 2) + "px";

                        // 禁止頁面滾動
                        document.addEventListener("touchmove", self.eventStop, false);

                        self.imgBaseWidth = zoomImg.offsetWidth;
                        self.imgBaseHeight = zoomImg.offsetHeight;

                        self.addEventStart({
                            wrapX: zoomMask.offsetWidth,
                            wrapY: zoomMask.offsetHeight,
                            mapX: zoomImg.width,
                            mapY: zoomImg.height
                        });
                    }
                }, false);
            }
        },
        addEventStart: function(param) {
            var self = this,
                params = param || {};

            self.element = document.querySelector(".imgzoom_pack img");

            //config set
            self.wrapX = params.wrapX || 0; //可視區域寬度
            self.wrapY = params.wrapY || 0; //可視區域高度
            self.mapX = params.mapX || 0; //地圖寬度
            self.mapY = params.mapY || 0; //地圖高度

            self.outDistY = (self.mapY - self.wrapY) / 2; //圖片超過一屏的時候有用

            self.width = self.mapX - self.wrapX; //地圖的寬度減去可視區域的寬度
            self.height = self.mapY - self.wrapY; //地圖的高度減去可視區域的高度

            self.element.addEventListener("touchstart", function(e) {
                self._touchstart(e);
            }, false);
            self.element.addEventListener("touchmove", function(e) {
                self._touchmove(e);
            }, false);
            self.element.addEventListener("touchend", function(e) {
                self._touchend(e);
            }, false);
        },
        // 重置座標資料
        _destroy: function() {
            this.distX = 0;
            this.distY = 0;
            this.newX = 0;
            this.newY = 0;

        },
        // 更新地圖資訊
        _changeData: function() {
            this.mapX = this.element.offsetWidth; //地圖寬度
            this.mapY = this.element.offsetHeight; //地圖高度
            // this.outDistY = (this.mapY - this.wrapY)/2; //當圖片高度超過螢幕的高度時候。圖片是垂直居中的,這時移動有個高度做為緩衝帶
            this.width = this.mapX - this.wrapX; //地圖的寬度減去可視區域的寬度
            this.height = this.mapY - this.wrapY; //地圖的高度減去可視區域的高度
        },
        _touchstart: function(e) {
            var self = this;

            self.tapDefault = false;
            // self.tapDefaultY = false;

            e.preventDefault();

            var touchTarget = e.targetTouches.length; //獲得觸控點數

            self._changeData(); //重新初始化圖片、可視區域資料,由於放大會產生新的計算

            if (touchTarget == 1) {
                // 獲取開始座標
                self.basePageX = getPage(e, "pageX");
                self.basePageY = getPage(e, "pageY");

                self.finger = false;
            } else {
                self.finger = true;

                self.startFingerDist = self.getTouchDist(e).dist;
                self.startFingerX = self.getTouchDist(e).x;
                self.startFingerY = self.getTouchDist(e).y;
            }
            /*console.log("pageX: " + getPage(e, "pageX"));
            console.log("pageY: " + getPage(e, "pageY"));*/
        },
        _touchmove: function(e) {
            var self = this;
            self.tapDefault = true;
            e.preventDefault();
            e.stopPropagation();

            // console.log("event.changedTouches[0].pageY: " + event.changedTouches[0].pageY);

            var touchTarget = e.targetTouches.length; //獲得觸控點數

            if (touchTarget == 1 && !self.finger) {

                self._move(e);
            }

            if (touchTarget >= 2) {
                self._zoom(e);
            }
        },
        _touchend: function(e) {
            var self = this;
            console.log(self.tapDefault)

            if (!self.finger && !self.tapDefault) {
                var zoomMask = document.querySelector(".imgzoom_pack"),
                    zoomImg = document.querySelector(".imgzoom_pack .imgzoom_img img");
                zoomMask.style.cssText = "display:none";
                zoomImg.src = "";
                zoomImg.style.cssText = "";

                self._destroy();

                document.removeEventListener("touchmove", self.eventStop, false);
                return
            };
            self._changeData(); //重新計算資料
            if (self.finger) {
                self.distX = -self.imgNewX;
                self.distY = -self.imgNewY;
            }

            if (self.distX > 0) {
                self.newX = 0;
            } else if (self.distX <= 0 && self.distX >= -self.width) {
                self.newX = self.distX;
                self.newY = self.distY;
            } else if (self.distX < -self.width) {
                self.newX = -self.width;
            }


            self.reset();
        },
        _move: function(e) {

            var self = this,
                pageX = getPage(e, "pageX"), //獲取移動座標
                pageY = getPage(e, "pageY");

            // 禁止預設事件
            // e.preventDefault();
            // e.stopPropagation();

            /*self.tapDefaultX = pageX - self.basePageX;
            self.tapDefaultY = pageY - self.basePageY;*/
            // 獲得移動距離
            self.distX = (pageX - self.basePageX) + self.newX;
            self.distY = (pageY - self.basePageY) + self.newY;

            if (self.distX > 0) {
                self.moveX = Math.round(self.distX / self.buffMove);
            } else if (self.distX <= 0 && self.distX >= -self.width) {
                self.moveX = self.distX;
            } else if (self.distX < -self.width) {
                self.moveX = -self.width + Math.round((self.distX + self.width) / self.buffMove);
            }
            self.movePos();
            self.finger = false;
        },
        // 圖片縮放
        _zoom: function(e) {
            var self = this;
            // e.preventDefault();
            // e.stopPropagation();

            var nowFingerDist = self.getTouchDist(e).dist, //獲得當前長度
                ratio = nowFingerDist / self.startFingerDist, //計算縮放比
                imgWidth = Math.round(self.mapX * ratio), //計算圖片寬度
                imgHeight = Math.round(self.mapY * ratio); //計算圖片高度

            // 計算圖片新的座標
            self.imgNewX = Math.round(self.startFingerX * ratio - self.startFingerX - self.newX * ratio);
            self.imgNewY = Math.round((self.startFingerY * ratio - self.startFingerY) / 2 - self.newY * ratio);

            if (imgWidth >= self.imgBaseWidth) {
                self.element.style.width = imgWidth + "px";
                self.refresh(-self.imgNewX, -self.imgNewY, "0s", "ease");
                self.finger = true;
            } else {
                if (imgWidth < self.imgBaseWidth) {
                    self.element.style.width = self.imgBaseWidth + "px";
                }
            }

            self.finger = true;
        },
        // 移動座標
        movePos: function() {
            var self = this;

            if (self.height < 0) {
                if (self.element.offsetWidth == self.imgBaseWidth) {
                    self.moveY = Math.round(self.distY / self.buffMove);
                    // console.log(self.moveY +"111")
                } else {
                    var moveTop = Math.round((self.element.offsetHeight - self.imgBaseHeight) / 2);
                    self.moveY = -moveTop + Math.round((self.distY + moveTop) / self.buffMove);
                    // console.log(self.moveY +"222")
                }
            } else {
                var a = Math.round((self.wrapY - self.imgBaseHeight) / 2),
                    b = self.element.offsetHeight - self.wrapY + Math.round(self.wrapY - self.imgBaseHeight) / 2;

                if (self.distY >= -a) {
                    self.moveY = Math.round((self.distY + a) / self.buffMove) - a;
                    // console.log(self.moveY +"333")
                } else if (self.distY <= -b) {
                    self.moveY = Math.round((self.distY + b) / self.buffMove) - b;
                    // console.log(self.moveY +"444")
                } else {
                    self.moveY = self.distY;
                    // console.log(self.moveY +"555")
                }
            }
            self.refresh(self.moveX, self.moveY, "0s", "ease");
        },
        // 重置資料
        reset: function() {
            var self = this,
                hideTime = ".2s";
            if (self.height < 0) {
                self.newY = -Math.round(self.element.offsetHeight - self.imgBaseHeight) / 2;
            } else {
                var a = Math.round((self.wrapY - self.imgBaseHeight) / 2),
                    b = self.element.offsetHeight - self.wrapY + Math.round(self.wrapY - self.imgBaseHeight) / 2;

                if (self.distY >= -a) {
                    self.newY = -a;
                } else if (self.distY <= -b) {
                    self.newY = -b;
                } else {
                    self.newY = self.distY;
                }
            }
            self.refresh(self.newX, self.newY, hideTime, "ease-in-out");
        },
        // 執行圖片移動
        refresh: function(x, y, timer, type) {
            this.element.style.webkitTransitionProperty = "-webkit-transform";
            this.element.style.webkitTransitionDuration = timer;
            this.element.style.webkitTransitionTimingFunction = type;
            this.element.style.webkitTransform = getTranslate(x, y);
        },
        // 獲取多點觸控
        getTouchDist: function(e) {
            var x1 = 0,
                y1 = 0,
                x2 = 0,
                y2 = 0,
                x3 = 0,
                y3 = 0,
                result = {};

            x1 = e.touches[0].pageX;
            x2 = e.touches[1].pageX;
            y1 = e.touches[0].pageY - document.body.scrollTop;
            y2 = e.touches[1].pageY - document.body.scrollTop;

            if (!x1 || !x2) return;

            if (x1 <= x2) {
                x3 = (x2 - x1) / 2 + x1;
            } else {
                x3 = (x1 - x2) / 2 + x2;
            }
            if (y1 <= y2) {
                y3 = (y2 - y1) / 2 + y1;
            } else {
                y3 = (y1 - y2) / 2 + y2;
            }

            result = {
                dist: Math.round(Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2))),
                x: Math.round(x3),
                y: Math.round(y3)
            };
            return result;
        },
        eventStop: function(e) {
            e.preventDefault();
            e.stopPropagation();
        }
    };

    window.ImagesZoom = new ImagesZoom();
})(this);
/*  |xGv00|e265149d8101b256799ca6fa116fac35 */
View Code

Html程式碼

<div class="content">
  <img src='圖片URL'/>
</div>
<
div class="imgzoom_pack" style="display: none;"> <div class="imgzoom_x">X</div> <div class="imgzoom_img"><img class="pp" src=""></div> </div>

Css程式碼

.imgzoom_pack {
            width: 100%;
            height: 100%;
            position: fixed;
            top: 0px;
            bottom: 0px;
            left: 0px;
            right: 0px;
            background: rgba(0, 0, 0, .7);
        }

        .imgzoom_pack .imgzoom_x {
            color: #fff;
            height: 30px;
            width: 30px;
            line-height: 30px;
            background: #000;
            text-align: center;
            position: absolute;
            right: 5px;
            top: 5px;
            z-index: 10;
            cursor: pointer;
        }

        .imgzoom_pack .imgzoom_img {
            width: 100%;
            height: 100%;
            position: absolute;
            left: 0;
            top: 0;
            overflow: hidden;
        }

        .imgzoom_pack .imgzoom_img img {
            width: 100%;
            position: absolute;
            top: 50%;
        }

用法

$(function () {
                $(".content img").on("click", function () {
                $(".imgzoom_img>img").attr("src", $(this).attr("src"));
                $(".imgzoom_img>img").css("marginTop", "-" + ($(this).height() / 2) + "px");
                $(".imgzoom_pack").show();

            });
            $(".imgzoom_x").on("click", function () {
                $(".imgzoom_pack").hide();
                $(".imgzoom_img>img").attr("src", "");
            });
            
            window.ImagesZoom.init({
                "elem": ".content"
            })
        })

 

相關文章