Skip to content

Commit 14a9c14

Browse files
committed
feat(pull-to-refresh): new system-like PTR behavior in iOS theme
1 parent fef522e commit 14a9c14

File tree

3 files changed

+99
-86
lines changed

3 files changed

+99
-86
lines changed

src/core/components/pull-to-refresh/pull-to-refresh-class.js

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class PullToRefresh extends Framework7Class {
2929
// Done
3030
ptr.done = function done() {
3131
const $transitionTarget = isMaterial ? $preloaderEl : $el;
32-
$transitionTarget.transitionEnd(() => {
32+
$transitionTarget.once('transitionend', () => {
3333
$el.removeClass('ptr-transitioning ptr-pull-up ptr-pull-down ptr-closing');
3434
$el.trigger('ptr:done');
3535
ptr.emit('local::done ptrDone', $el[0]);
@@ -107,6 +107,20 @@ class PullToRefresh extends Framework7Class {
107107
triggerDistance = 38;
108108
}
109109

110+
function setPreloaderProgress(progress = 0) {
111+
const $bars = $preloaderEl.find('.preloader-inner-line');
112+
const perBarProgress = 1 / $bars.length;
113+
114+
$bars.forEach((barEl, barIndex) => {
115+
const barProgress = (progress - barIndex * perBarProgress) / perBarProgress;
116+
barEl.style.opacity = Math.max(Math.min(barProgress, 1), 0) * 0.27;
117+
});
118+
}
119+
120+
function unsetPreloaderProgress() {
121+
$preloaderEl.find('.preloader-inner-line').css('opacity', '');
122+
}
123+
110124
function handleTouchStart(e) {
111125
if (isTouched) {
112126
if (device.os === 'android') {
@@ -168,6 +182,9 @@ class PullToRefresh extends Framework7Class {
168182

169183
if (!isMoved) {
170184
$el.removeClass('ptr-transitioning');
185+
if (isIos) {
186+
setPreloaderProgress(0);
187+
}
171188
let targetIsScrollable;
172189
scrollHeight = $el[0].scrollHeight;
173190
offsetHeight = $el[0].offsetHeight;
@@ -251,12 +268,27 @@ class PullToRefresh extends Framework7Class {
251268
.transform(`rotate(${180 * (Math.abs(touchesDiff) / 66) + 100}deg)`);
252269
} else {
253270
// eslint-disable-next-line
254-
if (ptr.bottom) {
271+
if (ptr.bottom || isIos) {
255272
$el.children().transform(`translate3d(0,${translate}px,0)`);
256273
} else {
274+
// eslint-disable-next-line
257275
$el.transform(`translate3d(0,${translate}px,0)`);
258276
}
277+
if (isIos) {
278+
$preloaderEl.transform(`translate3d(0,0px,0)`);
279+
}
259280
}
281+
} else if (isIos && !ptr.bottom) {
282+
$preloaderEl.transform(`translate3d(0,${scrollTop}px,0)`);
283+
}
284+
285+
let progress;
286+
if (isIos && !refresh) {
287+
progress =
288+
useTranslate || forceUseTranslate
289+
? Math.abs(touchesDiff) ** 0.85 / triggerDistance
290+
: Math.abs(touchesDiff) / (triggerDistance * 2);
291+
setPreloaderProgress(progress);
260292
}
261293

262294
if (
@@ -266,6 +298,7 @@ class PullToRefresh extends Framework7Class {
266298
) {
267299
refresh = true;
268300
$el.addClass('ptr-pull-up').removeClass('ptr-pull-down');
301+
unsetPreloaderProgress();
269302
} else {
270303
refresh = false;
271304
$el.removeClass('ptr-pull-up').addClass('ptr-pull-down');
@@ -315,8 +348,8 @@ class PullToRefresh extends Framework7Class {
315348
if (isMaterial) {
316349
$preloaderEl.transform('').find('.ptr-arrow').transform('');
317350
} else {
318-
// eslint-disable-next-line
319-
if (ptr.bottom) {
351+
$preloaderEl.transform('');
352+
if (ptr.bottom || isIos) {
320353
$el.children().transform('');
321354
} else {
322355
$el.transform('');
@@ -358,7 +391,7 @@ class PullToRefresh extends Framework7Class {
358391
if (isMaterial) {
359392
$preloaderEl.transform('').find('.ptr-arrow').transform('');
360393
} else {
361-
// eslint-disable-next-line
394+
$preloaderEl.transform('');
362395
if (ptr.bottom) {
363396
$el.children().transform('');
364397
} else {
@@ -396,6 +429,9 @@ class PullToRefresh extends Framework7Class {
396429

397430
if (!mousewheelMoved) {
398431
$el.removeClass('ptr-transitioning');
432+
if (isIos) {
433+
setPreloaderProgress(0);
434+
}
399435
let targetIsScrollable;
400436
scrollHeight = $el[0].scrollHeight;
401437
offsetHeight = $el[0].offsetHeight;
@@ -468,12 +504,22 @@ class PullToRefresh extends Framework7Class {
468504
$el.children().transform(`translate3d(0,${translate}px,0)`);
469505
} else {
470506
$el.transform(`translate3d(0,${translate}px,0)`);
507+
if (isIos) {
508+
$preloaderEl.transform(`translate3d(0,${-translate}px,0)`);
509+
}
471510
}
472511
}
473512

513+
let progress;
514+
if (isIos && !refresh) {
515+
progress = Math.abs(translate) / triggerDistance;
516+
setPreloaderProgress(progress);
517+
}
518+
474519
if (Math.abs(translate) > triggerDistance) {
475520
refresh = true;
476521
$el.addClass('ptr-pull-up').removeClass('ptr-pull-down');
522+
unsetPreloaderProgress();
477523
} else {
478524
refresh = false;
479525
$el.removeClass('ptr-pull-up').addClass('ptr-pull-down');
Lines changed: 47 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,63 @@
11
.ios {
22
.ptr-preloader {
3-
margin-top: calc(-1 * var(--f7-ptr-size));
3+
margin-bottom: calc(-1 * var(--f7-ptr-size));
44
width: 100%;
55
left: 0;
6-
}
7-
.ptr-arrow {
8-
position: absolute;
9-
left: 50%;
10-
top: 50%;
11-
background: no-repeat center;
12-
z-index: 10;
13-
transform: rotate(0deg) translate3d(0, 0, 0);
14-
transition-duration: 300ms;
15-
transition-property: transform, opacity;
16-
width: 12px;
17-
height: 20px;
18-
margin-left: -6px;
19-
margin-top: -10px;
20-
visibility: visible;
21-
color: var(--f7-preloader-color);
22-
&:after {
23-
.core-icons-font();
24-
width: 12px;
25-
height: 20px;
26-
line-height: 20px;
27-
font-size: 10px;
28-
content: 'ptr_arrow_ios';
6+
top: 0;
7+
position: relative;
8+
.preloader {
9+
visibility: visible;
2910
}
3011
}
31-
.ptr-content:not(.ptr-refreshing) {
12+
13+
.ptr-content:not(.ptr-refreshing):not(.ptr-pull-up) {
3214
.ptr-preloader .preloader,
3315
.ptr-preloader .preloader-inner {
3416
animation: none;
3517
}
3618
}
37-
.ptr-transitioning,
38-
.ptr-refreshing {
39-
transition-duration: 300ms;
40-
transition-property: transform;
19+
.ptr-content:not(.ptr-refreshing):not(.ptr-pull-up):not(.ptr-pull-down),
20+
.ptr-content.ptr-closing {
21+
.preloader-inner-line {
22+
opacity: 0 !important;
23+
}
4124
}
25+
26+
.ptr-transitioning,
4227
.ptr-refreshing {
43-
transform: translate3d(0, var(--f7-ptr-size), 0);
44-
.ptr-arrow {
45-
visibility: hidden;
28+
> * {
29+
transition-duration: 300ms;
30+
transition-property: transform;
4631
}
47-
.ptr-preloader .preloader {
48-
visibility: visible;
32+
}
33+
34+
.ptr-transitioning {
35+
.preloader-inner-line {
36+
transition-duration: 100ms;
4937
}
5038
}
39+
5140
.ptr-pull-up {
52-
.ptr-arrow {
53-
transform: rotate(180deg) translate3d(0, 0, 0);
41+
.preloader {
42+
animation: ios-ptr-preloader-spin 1s ease-out forwards;
5443
}
5544
}
56-
.ptr-no-navbar,
57-
.ptr-with-navbar-large-transparent,
58-
.ptr-with-navbar-transparent {
59-
margin-top: calc(-1 * var(--f7-ptr-size));
60-
height: calc(100% + var(--f7-ptr-size));
61-
.ptr-preloader {
62-
margin-top: 0;
45+
46+
.ptr-refreshing:not(.ptr-bottom) {
47+
transform: none;
48+
> * {
49+
transform: translate3d(0, var(--f7-ptr-size), 0);
50+
}
51+
> .ptr-preloader {
52+
transform: translate3d(0, 0, 0);
6353
}
6454
}
55+
6556
.ptr-bottom {
6657
.ptr-preloader {
67-
margin-top: 0;
68-
margin-bottom: calc(-1 * var(--f7-ptr-size));
58+
margin-bottom: 0;
59+
margin-top: calc(-1 * var(--f7-ptr-size));
60+
position: relative;
6961
}
7062
&.ptr-transitioning,
7163
&.ptr-refreshing {
@@ -79,44 +71,18 @@
7971
> * {
8072
transform: translate3d(0, calc(-1 * var(--f7-ptr-size)), 0);
8173
}
82-
}
83-
.ptr-arrow {
84-
transform: rotate(180deg) translate3d(0, 0, 0);
85-
}
86-
&.ptr-pull-up {
87-
.ptr-arrow {
88-
transform: rotate(0deg) translate3d(0, 0, 0);
74+
> .ptr-preloader {
75+
transform: translate3d(0, 0, 0);
8976
}
9077
}
9178
}
92-
.ptr-with-navbar-large-transparent,
93-
.ptr-with-navbar-transparent {
94-
.ptr-preloader {
95-
.preloader,
96-
.ptr-arrow {
97-
opacity: 0;
98-
transition-duration: 300ms;
99-
transition-property: transform, opacity;
100-
}
101-
}
102-
&.ptr-pull-down,
103-
&.ptr-pull-up,
104-
&.ptr-refreshing {
105-
.ptr-preloader {
106-
.preloader,
107-
.ptr-arrow {
108-
opacity: 1;
109-
}
110-
}
111-
}
112-
&.ptr-closing {
113-
.ptr-preloader {
114-
.preloader,
115-
.ptr-arrow {
116-
opacity: 0;
117-
transition-duration: 300ms;
118-
}
119-
}
120-
}
79+
}
80+
81+
@keyframes ios-ptr-preloader-spin {
82+
from {
83+
transform: rotate(0deg);
84+
}
85+
to {
86+
transform: rotate(135deg);
12187
}
12288
}

src/core/components/pull-to-refresh/pull-to-refresh.less

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
position: relative;
66
top: var(--f7-ptr-top, 0);
77
height: var(--f7-ptr-size);
8+
pointer-events: none;
89
.preloader {
910
position: absolute;
1011
left: 50%;

0 commit comments

Comments
 (0)