Skip to content

Commit c23dbe1

Browse files
李钿李钿
authored andcommitted
增加放大图片后单指拖动动效
1 parent 69b3dc7 commit c23dbe1

File tree

2 files changed

+107
-16
lines changed

2 files changed

+107
-16
lines changed

src/components/ImageContainer.jsx

Lines changed: 99 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
import React, { PureComponent } from 'react';
22
import 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-
1113
function 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
}

src/components/ListContainer.jsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ class ListContainer extends PureComponent {
6767

6868
handleMove = (diffX) =>{
6969
// console.info("ListContainer handleStart diffX = %s",diffX);
70+
//限制最大 diffx 值
71+
if(Math.abs(diffX) > this.props.screenWidth){
72+
if(diffX < 0){diffX = - this.props.screenWidth}
73+
if(diffX > 0){diffX = this.props.screenWidth}
74+
}
75+
7076
if(this.state.left >= 0 && diffX > 0){
7177
diffX = this.easing(diffX);
7278
} else if(this.state.left <= - this.maxLeft && diffX < 0){
@@ -78,11 +84,11 @@ class ListContainer extends PureComponent {
7884
})
7985
}
8086

81-
handleEnd = () =>{
87+
handleEnd = (isAllowChange) =>{
8288
let index, left, diffTime = (new Date()).getTime() - this.startTime;
8389

8490
//快速拖动情况下切换图片
85-
if(diffTime < DEDAULT_TIME_DIFF){
91+
if(isAllowChange && diffTime < DEDAULT_TIME_DIFF){
8692
if(this.state.left < this.startLeft){
8793
index = this.props.index + 1;
8894
} else{

0 commit comments

Comments
 (0)