11import React , { PureComponent } from 'react' ;
22import PropTypes from 'prop-types' ;
33
4+ import raf from 'raf' ;
5+ import tween from './tween.js'
6+
47/**
58 *
69 * @param {number } value
710 * @param {number } min
811 * @param {number } max
912 */
10-
1113function setScope ( value , min , max ) {
1214 if ( value < min ) { return min }
1315 if ( value > max ) { return max }
1416 return value ;
1517}
1618
19+ const msPerFrame = 1000 / 60 ;
20+ const maxAnimateTime = 1000 ;
21+
1722/**
1823 * 图片默认展示模式:宽度等于屏幕宽度,高度等比缩放;水平居中,垂直居中或者居顶(当高度大于屏幕高度时)
1924 * 图片实际尺寸: actualWith, actualHeight
@@ -78,6 +83,16 @@ class ImageContainer extends PureComponent {
7883 this . oldPointTop = 0 ; //计算手指中间点在图片上的位置(坐标值)
7984 this . _touchZoomDistanceStart = 0 ; //用于记录双指距离
8085
86+ this . animationID = 0 ;
87+ this . animateCurTime = 0 ;
88+ this . animateStartValue = {
89+ x : 0 ,
90+ y : 0 ,
91+ }
92+ this . animateFinalValue = {
93+ x : 0 ,
94+ y : 0 ,
95+ }
8196 }
8297
8398 componentWillMount ( ) {
@@ -86,12 +101,17 @@ class ImageContainer extends PureComponent {
86101
87102 componentWillUnmount ( ) {
88103 this . unloadImg ( ) ;
104+ if ( this . animationID ) {
105+ raf . cancel ( this . animationID ) ;
106+ }
89107 }
90108
91109 handleTouchStart = ( event ) => {
92110 console . info ( "handleTouchStart" )
93111 event . preventDefault ( ) ;
94-
112+ if ( this . animationID ) {
113+ raf . cancel ( this . animationID ) ;
114+ }
95115 switch ( event . touches . length ) {
96116 case 1 :
97117 let targetEvent = event . touches [ 0 ] ;
@@ -145,6 +165,8 @@ class ImageContainer extends PureComponent {
145165 diffX = targetEvent . clientX - this . startX ,
146166 diffY = targetEvent . clientY - this . startY ;
147167
168+ this . diffX = diffX ;
169+ this . diffY = diffY ;
148170 //判断是否移动
149171 if ( Math . abs ( diffX ) > 5 || Math . abs ( diffY ) > 5 ) {
150172 this . isTap = false ;
@@ -264,22 +286,85 @@ class ImageContainer extends PureComponent {
264286 } )
265287
266288 } else { //单指结束(ontouchend)
267- this . callHandleEnd ( ) ;
268- let diffTime = ( new Date ( ) ) . getTime ( ) - this . onTouchStartTime
289+ let diffTime = ( new Date ( ) ) . getTime ( ) - this . onTouchStartTime ,
290+ diffx = this . diffX ,
291+ diffy = this . diffY ;
292+ // diffx = this.state.left - this.startLeft,
293+ // diffy = this.state.top - this.startTop;
294+ console . info ( "diffx = %s, diffy = %s" , diffx , diffy ) ;
269295 if ( diffTime < 100 && this . isTap ) {
270296 this . context . onClose ( ) ;
297+ } else {
298+ this . callHandleEnd ( diffy < 30 ) ;
299+
300+ if ( diffTime < maxAnimateTime / 2 ) {
301+ let x , y ;
302+
303+ //使用相同速度算法
304+ x = diffx * maxAnimateTime / diffTime + this . startLeft ;
305+ y = diffy * maxAnimateTime / diffTime + this . startTop ;
306+ //使用 y = A * x + b; 其中 x = diffTime 两个点(500,1)(100, 5) 带入计算得出
307+ // x = diffx * (-3/400 * diffTime + 19/4) + this.startLeft;
308+ // y = diffy * (-3/400 * diffTime + 19/4) + this.startTop;
309+
310+ x = setScope ( x , this . originWidth - this . state . width , 0 ) ;
311+
312+ if ( this . state . height > this . props . screenHeight ) {
313+ y = setScope ( y , this . props . screenHeight - this . state . height , 0 ) ;
314+ } else {
315+ y = this . state . top ;
316+ }
317+ console . info ( "this.state.height = %s, screenHeight = %s," , this . state . height , this . props . screenHeight ) ;
318+ console . info ( "diffTime=%s, diffx = %s, diffy = %s, startLeft = %s, startTop=%s, x = %s, y = %s" , diffTime , diffx , diffy , this . startLeft , this . startTop , x , y ) ;
319+ this . animateStartValue = {
320+ x : this . state . left ,
321+ y : this . state . top ,
322+ }
323+ this . animateFinalValue = {
324+ x,
325+ y,
326+ }
327+ this . animateCurTime = 0 ;
328+ this . startAnimate ( ) ;
329+ }
271330 }
272331 }
273332 }
274333
275- // callHandleStart = () =>{
276- // if(!this.isCalledHandleStart){
277- // this.isCalledHandleStart = true;
278- // if(this.props.handleStart){
279- // this.props.handleStart();
280- // }
281- // }
282- // }
334+ startAnimate = ( ) => {
335+ this . animationID = raf ( ( ) => {
336+ let left = tween . easeOutQuart ( this . animateCurTime , this . animateStartValue . x , this . animateFinalValue . x , maxAnimateTime ) ,
337+ top = tween . easeOutQuart ( this . animateCurTime , this . animateStartValue . y , this . animateFinalValue . y , maxAnimateTime ) ;
338+
339+ this . setState ( {
340+ left,
341+ top
342+ } )
343+ //add Time
344+ this . animateCurTime += msPerFrame ;
345+ // console.info("startAnimate left= %s, top = %s, this.animateCurTime = %s", left, top, this.animateCurTime);
346+ //animate complete
347+ if ( this . animateCurTime > maxAnimateTime ) {
348+ this . setState ( ( prevState , props ) => {
349+ left = setScope ( prevState . left , this . originWidth - prevState . width , 0 ) ;
350+
351+ if ( prevState . height > props . screenHeight ) {
352+ top = setScope ( prevState . top , props . screenHeight - prevState . height , 0 ) ;
353+ } else {
354+ top = ( props . screenHeight - prevState . height ) / 2 ;
355+ }
356+ console . info ( "end animate left= %s, top = %s" , left , top ) ;
357+ return {
358+ left,
359+ top
360+ }
361+ } )
362+ } else {
363+ this . startAnimate ( ) ;
364+ }
365+ } )
366+ }
367+
283368 callHandleMove = ( diffX ) => {
284369 if ( ! this . isCalledHandleStart ) {
285370 this . isCalledHandleStart = true ;
@@ -290,11 +375,11 @@ class ImageContainer extends PureComponent {
290375 this . props . handleMove ( diffX ) ;
291376 }
292377
293- callHandleEnd = ( ) => {
378+ callHandleEnd = ( isAllowChange ) => {
294379 if ( this . isCalledHandleStart ) {
295380 this . isCalledHandleStart = false ;
296381 if ( this . props . handleEnd ) {
297- this . props . handleEnd ( ) ;
382+ this . props . handleEnd ( isAllowChange ) ;
298383 }
299384 }
300385 }
0 commit comments