前端手势控制图片插件书写一

Posted qdcnbj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端手势控制图片插件书写一相关的知识,希望对你有一定的参考价值。

1、前端图片处理需求场景
   前端图片处理应用在很多方面,在做业务过程中我也遇到了以下问题用到前端图片处理插件。
     头像上传
     背景图片上传
     信用卡的Diy卡面上传
     H5贴纸及合成
2、手势控制的数学知识
如果想要做图片旋转放大和拖动操作,一定会涉及到移动端的手势识别和手势操作。
在移动端控制图片操作中涉及到以下几个手势:单指拖动,单指缩放,单指旋转,双指缩放,双指旋转这五种手势 。
下面来介绍下如果使用向量来识别手势。
下图是单指在图片上旋转缩放时的示意图。只需要算出bs向量和bs‘向量的夹角和他们的模的比例即可,与双指不同的是,单指手势需要一个中心点的坐标作为base点,这样才能构造出一个向量。技术图片
下图是双指在图片上旋转缩放时的示意图。与单指同理。
技术图片
技术图片
所以我们需要使用式子来表示出向量的角度和模。
e.touches可以获取到touch事件的手指数量及手指坐标。
a、从touches对象中获取点。 
   Gesture. getPoint();
eg:getPoint(event,index)
return 
x: Math.round(event.touches[index].pageX),
y: Math.round(event.touches[index].pageY),

 

 
b、从点得到向量。
    Gesture. getVector()
eg:getVector(p1,p2)
let x = Math.round(p1.x - p2.x);
let y = Math.round(p1.y - p2.y);
return  x ,y ;

 

c、计算向量的模。
   Gesture. getVectorLength()
eg: getVectorLength(vct)
return Math.sqrt(vct.x * vct.x + vct.y * vct.y)

 

d、计算两个向量的夹角(向量的数量积)。
        Gesture. getVectorAngle();
eg: getVectorAngle(vct1, vct2)
//首先判断方向
let direction = vct1.x*vct2.y - vct2.x*vct1.y>0?1:-1;
// console.log(‘direction‘,direction)
let len1 = this.getVectorLength(vct1);
let len2 = this.getVectorLength(vct2);
let mr = len1*len2;
let dot;
let r;
if(mr === 0) return 0;
 
dot = vct1.x*vct2.x + vct1.y*vct2.y;
r = dot/mr;
console.log(r)
if(r>1)
r =1;

if(r<-1)
r=-1;

let angle = Math.acos(r)*direction*180/Math.PI;
return angle;

 

3、如何表示双指旋转(示例)
首先在touchstart事件开始时,获取到开始触摸时的双指坐标,计算出初始向量和向量的模
startPoint = gesture.getPoint(e, 0);
secondPoint = gesture.getPoint(e, 1);
vector1 = gesture.getVector(secondPoint, startPoint);
// console.error(vector1)
pinchStartLength = gesture.getVectorLength(vector1);

 

然后同理,在touchmove事件触发时计算出目前向量的坐标及向量的模。通过刚刚的公式来计算出两个向量的夹角。
 
最后在touchend结束的时候,双指会出现两个手指如果不同时离开屏幕的现象。这时要在touchstart事件中判断初始手指数量,
如果在touchmove的同时,手指数量突然小于初始数量时,及时return ,避免执行单指move的代码。

 绑定手指事件的实例代码:

let that = this;
target.addEventListener(‘touchstart‘, (e) => 
            e.stopPropagation()
            e.preventDefault()
            console.warn(‘start‘, e.touches)
            console.warn(‘target‘, e.currentTarget)
            this.fingers = e.touches.length;
            if (e.touches.length == 1) 
                this.startPoint = this.gesture.getPoint(e, 0);
                // console.log(‘startPoint‘, startPoint)
                //获取图片的初始位置。
                that.getPreTransformMatrix(target)
            
            else if (e.touches.length == 2) 
                this.startPoint = this.gesture.getPoint(e, 0);
                this.secondPoint = this.gesture.getPoint(e, 1);
                // console.log(‘startPoint‘, startPoint)
                // console.log(‘secondPoint‘, secondPoint)
                this.vector1 = this.gesture.getVector(this.secondPoint, this.startPoint);
                // console.error(vector1)
                this.pinchStartLength = this.gesture.getVectorLength(this.vector1);
                // console.log(pinchStartLength)
                that.getPreTransformMatrix(target)
            

        )
        target.addEventListener(‘touchmove‘, (e) => 
            let curFingers = e.touches.length;
            // alert(e.touches.length)
            if (curFingers < this.fingers) 
                // alert(fingers)
                return;
            
            // console.warn(‘move‘, e)
            if (e.touches.length == 1) 
                this.currentPoint = this.gesture.getPoint(e, 0);
                let detla;

                detla = 
                    deltaX: this.currentPoint.x - this.startPoint.x,
                    deltaY: this.currentPoint.y - this.startPoint.y,
                



                this.set(target, 
                    x: detla.deltaX,
                    y: detla.deltaY,
                    scale: 1,
                    rotate: 0,
                )

                // this.set($(‘#div_bg_img‘), this.limit(‘‘, $(‘body‘), dragTrans))
            
            else if (e.touches.length == 2) 
                // touchmove中计算实时的双指向量模;
                let curPoint = this.gesture.getPoint(e, 0);
                let curSecPoint = this.gesture.getPoint(e, 1);

                let vector2 = this.gesture.getVector(curSecPoint, curPoint);
                let pinchLength = this.gesture.getVectorLength(vector2);
                let angle = this.gesture.getVectorAngle(this.vector1, vector2)
                // console.log(‘pinch‘,  scale: pinchLength / pinchStartLength )
                // console.log(‘Rotate‘, angle)
                // console.log(‘vector1‘, vector1)
                // console.log(‘vector2‘, vector2)

                this.set(target, 
                    x: 0,
                    y: 0,
                    scale: pinchLength / this.pinchStartLength,
                    rotate: angle,
                )
                // this.set($(‘#div_bg_img‘), this.limit(‘‘, $(‘body‘), dragTrans))
            
        )
        target.addEventListener(‘touchend‘, (e) => 
            // console.log(‘dragTransEND‘, dragTrans)
            console.log(‘dragTransEND‘, e.touches.length)
            console.log(target.firstElementChild)
            let orientation = that.getPhotoOrientation(target.firstElementChild);
            that.drawImagePic(orientation)
        )

 

技术图片
技术图片

以上是关于前端手势控制图片插件书写一的主要内容,如果未能解决你的问题,请参考以下文章

前端手势控制图片插件书写二

前端手势控制图片插件书写四(图片上传及Ios图片方向问题)

前端怎么实现点击图片将图片放大而且图片可以手势随意缩放,最好附上代码,非常感谢

前端插件实现图片懒加载

ArcGIS快速制图插件介绍

Tomcat插件的配置和管理控制台的配置书写