移动端H5部分区域缩放并移动

最近开发个项目,需要实现div内容的缩放(包含图片等内容),但不影响其他内容

开始没头绪,网上找了许多都是在index.html中实现,不满足我的需求在react里面实现

 

找了很久,总算发现一个写的不错的,能够满足在纯html中实现,也可以在react中实现的东西

 

我的react代码

import React from 'react'
import {Link,withRouter} from 'react-router-dom'
import CommonASK from './CommonASK'
class ShowPic extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            showmodel:true
        }
    }

    componentDidMount(){
       


        // let zoomview = (function (root, factory) {
        //     if(typeof exports === 'object' && typeof module === 'object')
        //         module.exports = factory();
        //     // else if(typeof define === 'function' && define.amd)
        //     //     define([], factory);
        //     else if(typeof exports === 'object')
        //         exports["Zoom"] = factory();
        //     else
        //         root["Zoom"] = factory();
        // })(this,function(){
        
            /**
             * 简洁的元素缩放功能。
             * @param {[type]} el     要缩放的元素
             * @param {[type]} option {windth:元素宽度(必须),height:元素高度(必须),minScale:最小缩放比例,maxScale:最大缩放比例,top:原始位置,left:原始位置}
             */
            function Zoom(el,option){
                if (!option || !option.width || !option.height) {
                    throw "dom的尺寸参数错误";
                }
                option = Object.assign({
                    minScale:1,
                    maxScale:3,
                    top:50,
                    left:50
                }, option);
        
                this.el = el;
                
                this.lastSapce = 0;
                this.touchState = 0;
                this.lastPoint = null
                this.targetPoint = null;
        
                //放大缩小的倍数 当前缩放倍数 
                this.minScale = option.minScale || 1;
                this.maxScale = option.maxScale || 10;
                
                //dom的尺寸参数
                this.width = option.width ;
                this.height = option.height;
                this.top = option.top ;
                this.left = option.left;
                this.scale = 1;
        
                //初始位置 以及 初始宽高
                this.originTop = option.top;
                this.originLeft = option.left;
                this.originW = this.width;
                this.originH = this.height;
                //图片中心点 
                this.centerX = this.left + this.originW / 2;
                this.centerY = this.top + this.originH / 2;	
        
                this.el.style.position = 'absolute';
        
                this.init();
                return this;
            }
        
        
            Zoom.prototype.getTouches = function (event){
                let touches = event.touches;
                if (!touches) {
                    touches = event.originalEvent.touches;
                }
                return touches;
            }
        
            Zoom.prototype.getTouchsDistance = function(t1,t2){
        
                let dx = parseInt(t1.pageX - t2.pageX);
                let dy = parseInt(t1.pageY - t2.pageY);
        
                let d = Math.pow((dx *dx + dy * dy), 0.5);
        
                return d.toFixed(5);
            }
        
            Zoom.prototype.restView = function(){
                this.el.style.width = this.width + 'px';
                this.el.style.height = this.height + 'px';
                this.el.style.top = this.top + 'px';
                this.el.style.left = this.left + 'px';
            }
        
        
            Zoom.prototype.init = function(){
        
        
                this.el.addEventListener('touchmove',this.touchmoveHandler);
                this.el.addEventListener('touchstart',this.touchmoveHandler);
                this.el.addEventListener('touchend',this.touchEndHandler);
                this.el.addEventListener('touchcancel',this.touchEndHandler);
                this.el.addEventListener('touchstart',this.dbclickHandler);
                this.el.zoom = this;
        
            }
            Zoom.prototype.dbclickHandler = function(event){
                event.stopPropagation();
                event.preventDefault();
                let el = event.currentTarget;
                let zoom = el.zoom;
                let time = new Date(event.timeStamp).getTime(); 
                let touchs = zoom.getTouches(event);
                if (touchs.length == 1) {
                    if (!el.lastClickTime) {
                        el.lastClickTime = time;
                    }else{
                        if (time - el.lastClickTime < 300) {
                            el.lastClickTime = 0;
                            if (zoom.scale != 1) {
                                zoom.setScale(1);
                            }else if(zoom.scale == 1){
                                zoom.setScale(2);
                            }		
                        }else{
                            el.lastClickTime = time;
                        }
                    }
                }
                zoom.touchStartTime = new Date().getTime();
                return false;
            }
            Zoom.prototype.drage = function(touch){
                if (this.lastPoint == null) {
                    this.lastPoint = {
                        x:touch.pageX,
                        y:touch.pageY,
                    }
                }else{
                    let dx = parseInt(touch.pageX - this.lastPoint.x);
                    let dy = parseInt(touch.pageY - this.lastPoint.y);
        
        
                    this.lastPoint.x = touch.pageX;
                    this.lastPoint.y = touch.pageY;
        
                    this.left += dx;
                    this.top += dy;
        
                    this.setTransform(false);
                }
            }
        
            Zoom.prototype.zoom = function(touchs){
        
                this.lastPoint = null;
                let t1 = touchs[0];
                let t2 = touchs[1];
        
                let x1 = t1.pageX;
                let x2 = t2.pageX;
                let y1 = t1.pageY;
                let y2 = t2.pageY;
        
                let d = this.getTouchsDistance(t1,t2);
        
                if (this.touchState == 0) {
                    this.lastSapce = d;
                    this.touchState = 1;
        
                    this.pointX = (x2 + (x1 - x2) / 2 - this.left)/this.scale;
                    this.pointY = (y2 + (y1 - y2) / 2 - this.top)/this.scale;
        
        
        
                }else if(this.touchState == 1){
        
                    let scaleChange = ((d / this.lastSapce) - 1) * 2;
        
                    let scale = this.scale + scaleChange / 2;
        
                    this.setScale(scale,this.pointX,this.pointY);
        
                    this.lastSapce = d;
                }
            }
        
            Zoom.prototype.touchmoveHandler = function(event){
        
                event.stopPropagation();
                event.preventDefault();
                let el = event.currentTarget;
                let zoom = el.zoom;
                let touchs = zoom.getTouches(event);
                if (touchs.length == 1) {
                    zoom.drage(touchs[0]);//拖动处理
                }else if (touchs.length >= 2) {
                    zoom.lastPoint = null;//终止拖动事件
                    zoom.zoom(touchs);//缩放处理
        
                }
        
                return false;
            }
        
            Zoom.prototype.touchEndHandler = function(event){
                let zoom = event.currentTarget.zoom;
        
                zoom.touchState = 0;
                zoom.lastPoint = null;
                zoom.lastSapce = 0;
        
                let minSpace = 20;
                let parentWidth = zoom.el.parentElement.offsetWidth;
                let parentHight =zoom.el.parentElement.offsetHeight;
                let scale = zoom.scale;
        
                if(scale < zoom.minScale){
                    scale = zoom.minScale;
                }
                if(scale > zoom.maxScale){
                    scale = zoom.maxScale;
                }
        
                if(scale != zoom.scale){
                    zoom.preSetScale(scale,zoom.lastPointX,zoom.lastPointY);
                }
        
                if((zoom.left + zoom.width) < minSpace){
                        zoom.left = - zoom.width + minSpace;
                }
                if(zoom.left >= (parentWidth - minSpace)){
                        zoom.left = parentWidth - minSpace;
                }
        
                if((zoom.top + zoom.height) < minSpace){
                    zoom.top = - zoom.height + minSpace;
                }
                if(zoom.top >= (parentHight - minSpace)){
                    zoom.top = parentHight - minSpace;
                }
        
        
                
                zoom.setTransform(true);
        
                return;
            }
            Zoom.prototype.setTransform = function (needAnimation,originX,originY){
                let distanceX = this.left - this.originLeft;
                let distanceY = this.top - this.originTop;
                let scale = this.scale;
                originX = originX == undefined ? (this.originTop + 'px') : originX;
                originY = originY == undefined ? (this.originLeft + 'px') : originY;
                this.el.style.transformOrigin = 'left top';
                this.el.style.transform = 'matrix('+scale+',0,0,'+scale+','+distanceX+','+distanceY+')';
                if(needAnimation == true){
                    this.el.style.transition = 'all .3s ease-in-out 0s'
                }else{
                    this.el.style.transition = ''
                }		
            }
            
            Zoom.prototype.destroy = function(){
        
                this.el.removeEventListener('touchmove',this.touchmoveHandler);
                this.el.removeEventListener('touchstart',this.touchmoveHandler);
                this.el.removeEventListener('touchend',this.touchEndHandler);
                this.el.removeEventListener('touchcancel',this.touchEndHandler);
        
                this.el.zoom = null;
            }
            //初始化放大倍数
            Zoom.prototype.setScale = function(scale,pointX,pointY){
                this.preSetScale(scale,pointX,pointY);
                this.setTransform(false);
            }
        
            Zoom.prototype.preSetScale = function(scale,pointX,pointY){
        
                if (scale < 0.1) {
                    scale = 0.1;
                }
        
                if (pointX ==undefined) {
                    this.left = this.centerX - this.originW / 2 - this.originW/2*(scale - 1);
                    this.top = this.centerY - this.originH / 2 - this.originH/2*(scale - 1);
        
                    this.width = scale * this.originW;
                    this.height = scale * this.originH;
        
                    this.scale = scale;
                }else{
                    this.width = scale * this.originW;
                    this.height = scale * this.originH;
        
                    this.left = this.left - pointX * (scale - this.scale);
                    this.top = this.top - pointY * (scale - this.scale);
        
                    this.lastPointX = pointX;
                    this.lastPointY = pointY;
        
                    this.scale = scale;
                }
        
            }
            
            // return Zoom;
        // });

        let zoomEl = document.getElementById('zoomEl');
    	let zoom = new Zoom(zoomEl, { 'top': zoomEl.offsetTop+50, 'left': zoomEl.offsetLeft+50, 'width': 400, 'height': 400 });
    	zoom.setScale(1)

    }

    render(){
        let {svgname} = this.props.match.params;
        return (
            <div style={{padding:'2rem'}}>
               <CommonASK />
                <div className="box">
                    <div id="zoomEl">
                        <img src={`static/svg/${svgname}.svg`} style={{width:300}}/>
                        <p>斯蒂芬规划局,美女成本vv法国皇帝三星发布成功v你尝尝</p>
                    </div>
                </div>


               {this.state.showmodel && <div onClick={()=>this.setState({showmodel:false})} style={{width:"100%",height: "100%",position: "fixed",top:"0rem",left:0,backgroundColor:" #000",opacity: 0.8,zIndex:999}}>
                    <div>
                        <img src="static/movehandle.png" alt="" className="handleimg" style={{position: "absolute",top: "4rem",
                        left: "5rem",width: "4rem" }}/>
                        <p style={{textAlign: "center",position: "absolute",top: "10rem",left: "3rem",color: "#FFF",fontSize: "1.5rem",width: "20rem"}}>上下左右滑动查看</p>
                        <p style={{textAlign: "center",position: "absolute",top: "13rem",left: "3rem",color:" #FFF",fontSize: "1.5rem",width: "20rem"}}>双击放大查看</p>
                    </div>
                </div>}
            </div>
           
        )
    }
}

export default withRouter(ShowPic)

实现了图文缩放,且不影响其他内容

在HTML中代码:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>zoom</title>
    <link rel="stylesheet" href="">
    <script src="./zoom.js" type="text/javascript"></script>
    <style type="text/css">
    html,
    body {
        height: 100%;
        width: 100%;
        padding: 0;
        margin: 0;
        overflow: hidden;
    }

    .box {
        width: 90%;
        height: 90%;
        margin: 10% 5%;
        background: #999;
        overflow: hidden;
        position:relative;/*重点*/
    }

    #zoomEl {
	    position: absolute;/*重点*/
	    width: 200px;
	    height: 200px;
	    left: calc(50% - 100px);
	    top: calc(50% - 100px);
	    background-color: red;
	    background-image: url(./a.png);
	    background-repeat: round;
	    display: inline-block;
	}
    </style>
</head>

<body style="background-color: #ddd;">
    <div class="box">
        <div id="zoomEl"></div>
    </div>


    <script type="text/javascript">
    	let zoomEl = document.getElementById('zoomEl');
    	let zoom = new Zoom(zoomEl, { 'top': zoomEl.offsetTop, 'left': zoomEl.offsetLeft, 'width': 200, 'height': 200 });
    	zoom.setScale(1.5)
    </script>
</body>

</html>

zoom.js文件

(function (root, factory) {
    if(typeof exports === 'object' && typeof module === 'object')
        module.exports = factory();
    else if(typeof define === 'function' && define.amd)
        define([], factory);
    else if(typeof exports === 'object')
        exports["Zoom"] = factory();
    else
        root["Zoom"] = factory();
})(this,function(){

	/**
	 * 简洁的元素缩放功能。
	 * @param {[type]} el     要缩放的元素
	 * @param {[type]} option {windth:元素宽度(必须),height:元素高度(必须),minScale:最小缩放比例,maxScale:最大缩放比例,top:原始位置,left:原始位置}
	 */
	function Zoom(el,option){
		if (!option || !option.width || !option.height) {
			throw "dom的尺寸参数错误";
		}
		option = Object.assign({
			minScale:1,
			maxScale:3,
			top:0,
			left:0
		}, option);

		this.el = el;
		
		this.lastSapce = 0;
		this.touchState = 0;
		this.lastPoint = null
		this.targetPoint = null;

		//放大缩小的倍数 当前缩放倍数 
		this.minScale = option.minScale || 1;
		this.maxScale = option.maxScale || 10;
		
		//dom的尺寸参数
		this.width = option.width ;
		this.height = option.height;
		this.top = option.top ;
		this.left = option.left;
		this.scale = 1;

		//初始位置 以及 初始宽高
		this.originTop = option.top;
		this.originLeft = option.left;
		this.originW = this.width;
		this.originH = this.height;
		//图片中心点 
		this.centerX = this.left + this.originW / 2;
		this.centerY = this.top + this.originH / 2;	

		this.el.style.position = 'absolute';

		this.init();
		return this;
	}


	Zoom.prototype.getTouches = function (event){
		let touches = event.touches;
		if (!touches) {
			touches = event.originalEvent.touches;
		}
		return touches;
	}

	Zoom.prototype.getTouchsDistance = function(t1,t2){

		let dx = parseInt(t1.pageX - t2.pageX);
		let dy = parseInt(t1.pageY - t2.pageY);

		let d = Math.pow((dx *dx + dy * dy), 0.5);

		return d.toFixed(5);
	}

	Zoom.prototype.restView = function(){
		this.el.style.width = this.width + 'px';
		this.el.style.height = this.height + 'px';
		this.el.style.top = this.top + 'px';
		this.el.style.left = this.left + 'px';
	}


	Zoom.prototype.init = function(){


		this.el.addEventListener('touchmove',this.touchmoveHandler);
		this.el.addEventListener('touchstart',this.touchmoveHandler);
		this.el.addEventListener('touchend',this.touchEndHandler);
		this.el.addEventListener('touchcancel',this.touchEndHandler);
		this.el.addEventListener('touchstart',this.dbclickHandler);
		this.el.zoom = this;

	}
	Zoom.prototype.dbclickHandler = function(event){
		event.stopPropagation();
		event.preventDefault();
		let el = event.currentTarget;
		let zoom = el.zoom;
		let time = new Date(event.timeStamp).getTime(); 
		let touchs = zoom.getTouches(event);
		if (touchs.length == 1) {
			if (!el.lastClickTime) {
				el.lastClickTime = time;
			}else{
				if (time - el.lastClickTime < 300) {
					el.lastClickTime = 0;
					if (zoom.scale != 1) {
						zoom.setScale(1);
					}else if(zoom.scale == 1){
						zoom.setScale(2);
					}		
				}else{
					el.lastClickTime = time;
				}
			}
		}
		zoom.touchStartTime = new Date().getTime();
		return false;
	},
	Zoom.prototype.drage = function(touch){
		if (this.lastPoint == null) {
			this.lastPoint = {
				x:touch.pageX,
				y:touch.pageY,
			}
		}else{
			let dx = parseInt(touch.pageX - this.lastPoint.x);
			let dy = parseInt(touch.pageY - this.lastPoint.y);


			this.lastPoint.x = touch.pageX;
			this.lastPoint.y = touch.pageY;

			this.left += dx;
			this.top += dy;

			this.setTransform(false);
		}
	}

	Zoom.prototype.zoom = function(touchs){

		this.lastPoint = null;
		let t1 = touchs[0];
		let t2 = touchs[1];

		let x1 = t1.pageX;
		let x2 = t2.pageX;
		let y1 = t1.pageY;
		let y2 = t2.pageY;

		let d = this.getTouchsDistance(t1,t2);

		if (this.touchState == 0) {
			this.lastSapce = d;
			this.touchState = 1;

			this.pointX = (x2 + (x1 - x2) / 2 - this.left)/this.scale;
			this.pointY = (y2 + (y1 - y2) / 2 - this.top)/this.scale;



		}else if(this.touchState == 1){

			let scaleChange = ((d / this.lastSapce) - 1) * 2;

			let scale = this.scale + scaleChange / 2;

			this.setScale(scale,this.pointX,this.pointY);

			this.lastSapce = d;
		}
	}

	Zoom.prototype.touchmoveHandler = function(event){

		event.stopPropagation();
		event.preventDefault();
		let el = event.currentTarget;
		let zoom = el.zoom;
		let touchs = zoom.getTouches(event);
		if (touchs.length == 1) {
			zoom.drage(touchs[0]);//拖动处理
		}else if (touchs.length >= 2) {
			zoom.lastPoint = null;//终止拖动事件
			zoom.zoom(touchs);//缩放处理

		}

		return false;
	}

	Zoom.prototype.touchEndHandler = function(event){
		let zoom = event.currentTarget.zoom;

		zoom.touchState = 0;
		zoom.lastPoint = null;
		zoom.lastSapce = 0;

		let minSpace = 20;
		let parentWidth = zoom.el.parentElement.offsetWidth;
		let parentHight =zoom.el.parentElement.offsetHeight;
		let scale = zoom.scale;

		if(scale < zoom.minScale){
			scale = zoom.minScale;
		}
		if(scale > zoom.maxScale){
			scale = zoom.maxScale;
		}

		if(scale != zoom.scale){
			zoom.preSetScale(scale,zoom.lastPointX,zoom.lastPointY);
		}

		if((zoom.left + zoom.width) < minSpace){
				zoom.left = - zoom.width + minSpace;
		}
		if(zoom.left >= (parentWidth - minSpace)){
				zoom.left = parentWidth - minSpace;
		}

		if((zoom.top + zoom.height) < minSpace){
			zoom.top = - zoom.height + minSpace;
		}
		if(zoom.top >= (parentHight - minSpace)){
			zoom.top = parentHight - minSpace;
		}


		
		zoom.setTransform(true);

		return;
	}
	Zoom.prototype.setTransform = function (needAnimation,originX,originY){
		let distanceX = this.left - this.originLeft;
		let distanceY = this.top - this.originTop;
		let scale = this.scale;
		originX = originX == undefined ? (this.originTop + 'px') : originX;
		originY = originY == undefined ? (this.originLeft + 'px') : originY;
		this.el.style.transformOrigin = 'left top';
		this.el.style.transform = 'matrix('+scale+',0,0,'+scale+','+distanceX+','+distanceY+')';
		if(needAnimation == true){
			this.el.style.transition = 'all .3s ease-in-out 0s'
		}else{
			this.el.style.transition = ''
		}		
	}
	
	Zoom.prototype.destroy = function(){

		this.el.removeEventListener('touchmove',this.touchmoveHandler);
		this.el.removeEventListener('touchstart',this.touchmoveHandler);
		this.el.removeEventListener('touchend',this.touchEndHandler);
		this.el.removeEventListener('touchcancel',this.touchEndHandler);

		this.el.zoom = null;
	}
	//初始化放大倍数
	Zoom.prototype.setScale = function(scale,pointX,pointY){
		this.preSetScale(scale,pointX,pointY);
		this.setTransform(false);
	}

	Zoom.prototype.preSetScale = function(scale,pointX,pointY){

		if (scale < 0.1) {
			scale = 0.1;
		}

		if (pointX ==undefined) {
			this.left = this.centerX - this.originW / 2 - this.originW/2*(scale - 1);
			this.top = this.centerY - this.originH / 2 - this.originH/2*(scale - 1);

			this.width = scale * this.originW;
			this.height = scale * this.originH;

			this.scale = scale;
		}else{
			this.width = scale * this.originW;
			this.height = scale * this.originH;

			this.left = this.left - pointX * (scale - this.scale);
			this.top = this.top - pointY * (scale - this.scale);

			this.lastPointX = pointX;
			this.lastPointY = pointY;

			this.scale = scale;
		}

	}

	return Zoom;
});

 

 

效果图:

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

随风小薇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值