@lynx-example/lynx-ui-swiper 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Basic/index.tsx +109 -0
- package/Basic/styles.css +49 -0
- package/BasicDynamic/index.tsx +130 -0
- package/BasicDynamic/styles.css +47 -0
- package/BasicUpdateSize/index.tsx +131 -0
- package/BasicUpdateSize/styles.css +47 -0
- package/Bounces/index.tsx +73 -0
- package/Bounces/styles.css +41 -0
- package/CHANGELOG.md +8 -0
- package/Common/Button/index.tsx +48 -0
- package/Common/Button/styles.css +41 -0
- package/Common/Card/index.tsx +21 -0
- package/Common/Card/styles.css +21 -0
- package/Common/Indicator/index.tsx +24 -0
- package/Common/Indicator/styles.css +21 -0
- package/Custom/index.tsx +87 -0
- package/Custom/styles.css +47 -0
- package/CustomScale/index.tsx +116 -0
- package/CustomScale/styles.css +41 -0
- package/CustomTinder/Card.tsx +24 -0
- package/CustomTinder/index.tsx +111 -0
- package/CustomTinder/styles.css +61 -0
- package/DifferentHeight/Button.tsx +33 -0
- package/DifferentHeight/index.tsx +95 -0
- package/DifferentHeight/styles.css +50 -0
- package/Direction/index.tsx +127 -0
- package/Direction/styles.css +41 -0
- package/EmptyDataBug/index.tsx +371 -0
- package/EmptyDataBug/styles.css +75 -0
- package/Indicator/index.tsx +67 -0
- package/Indicator/styles.css +41 -0
- package/Lazy/index.tsx +83 -0
- package/Lazy/styles.css +41 -0
- package/Loop/index.tsx +77 -0
- package/Loop/styles.css +41 -0
- package/RTL/Button.tsx +33 -0
- package/RTL/index.tsx +133 -0
- package/RTL/styles.css +41 -0
- package/RTLCustom/index.tsx +115 -0
- package/RTLCustom/styles.css +41 -0
- package/RTLLoop/Button.tsx +33 -0
- package/RTLLoop/index.tsx +116 -0
- package/RTLLoop/styles.css +41 -0
- package/RTLLoopLynxRTL/Button.tsx +33 -0
- package/RTLLoopLynxRTL/index.tsx +116 -0
- package/RTLLoopLynxRTL/styles.css +41 -0
- package/WithGap/Button.tsx +33 -0
- package/WithGap/index.tsx +118 -0
- package/WithGap/styles.css +47 -0
- package/dist/SwiperBasic.lynx.bundle +0 -0
- package/dist/SwiperBasic.web.bundle +1 -1
- package/dist/SwiperBasicDynamic.lynx.bundle +0 -0
- package/dist/SwiperBasicDynamic.web.bundle +1 -1
- package/dist/SwiperBasicUpdateSize.lynx.bundle +0 -0
- package/dist/SwiperBasicUpdateSize.web.bundle +1 -1
- package/dist/SwiperCustomTinder.lynx.bundle +0 -0
- package/dist/SwiperCustomTinder.web.bundle +1 -1
- package/dist/SwiperDifferentHeight.lynx.bundle +0 -0
- package/dist/SwiperDifferentHeight.web.bundle +1 -1
- package/dist/SwiperEmptyDataBug.lynx.bundle +0 -0
- package/dist/SwiperEmptyDataBug.web.bundle +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
@import "@lynx-js/luna-styles/index.css";
|
|
2
|
+
|
|
3
|
+
.button {
|
|
4
|
+
height: 48px;
|
|
5
|
+
display: flex;
|
|
6
|
+
border-radius: 9999px;
|
|
7
|
+
justify-content: center;
|
|
8
|
+
align-items: center;
|
|
9
|
+
background-color: var(--neutral-ambient);
|
|
10
|
+
transition: opacity 0.15s ease-in-out;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.button.ui-active {
|
|
14
|
+
opacity: 0.5;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.button .text {
|
|
18
|
+
color: var(--content);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.button.primary {
|
|
22
|
+
background-color: var(--primary);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.button.primary .text {
|
|
26
|
+
color: var(--primary-content);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.text {
|
|
30
|
+
font-size: 15px;
|
|
31
|
+
line-height: 18px;
|
|
32
|
+
text-align: center;
|
|
33
|
+
font-weight: 600;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.sub-text {
|
|
37
|
+
font-size: 11px;
|
|
38
|
+
line-height: 14px;
|
|
39
|
+
text-align: center;
|
|
40
|
+
color: var(--content-muted);
|
|
41
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Copyright 2026 The Lynx Authors. All rights reserved.
|
|
2
|
+
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
+
// LICENSE file in the root directory of this source tree.
|
|
4
|
+
|
|
5
|
+
import {} from '@lynx-js/react'
|
|
6
|
+
import type { CSSProperties } from '@lynx-js/types'
|
|
7
|
+
import './styles.css'
|
|
8
|
+
|
|
9
|
+
export function Card({
|
|
10
|
+
index,
|
|
11
|
+
style,
|
|
12
|
+
}: {
|
|
13
|
+
index: number
|
|
14
|
+
style?: CSSProperties
|
|
15
|
+
}) {
|
|
16
|
+
return (
|
|
17
|
+
<view className='card' style={style}>
|
|
18
|
+
<text className='card-text'>{index}</text>
|
|
19
|
+
</view>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
@import "@lynx-js/luna-styles/index.css";
|
|
2
|
+
|
|
3
|
+
.card {
|
|
4
|
+
width: 100%;
|
|
5
|
+
height: 100%;
|
|
6
|
+
display: flex;
|
|
7
|
+
align-items: center;
|
|
8
|
+
justify-content: center;
|
|
9
|
+
background-color: var(--canvas);
|
|
10
|
+
|
|
11
|
+
border-radius: 8px;
|
|
12
|
+
box-shadow:
|
|
13
|
+
0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
|
14
|
+
0 4px 6px -4px rgba(0, 0, 0, 0.1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.card-text {
|
|
18
|
+
color: var(--primary);
|
|
19
|
+
font-size: 64px;
|
|
20
|
+
font-weight: 600;
|
|
21
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Copyright 2026 The Lynx Authors. All rights reserved.
|
|
2
|
+
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
+
// LICENSE file in the root directory of this source tree.
|
|
4
|
+
|
|
5
|
+
import './styles.css'
|
|
6
|
+
|
|
7
|
+
export function Indicator({
|
|
8
|
+
current,
|
|
9
|
+
count,
|
|
10
|
+
}: {
|
|
11
|
+
current: number
|
|
12
|
+
count: number
|
|
13
|
+
}) {
|
|
14
|
+
return (
|
|
15
|
+
<view class='indicator-container'>
|
|
16
|
+
{Array.from({ length: count }).map((_, index) => (
|
|
17
|
+
<view
|
|
18
|
+
key={index}
|
|
19
|
+
class={`indicator-item ${index === current ? 'active' : ''}`}
|
|
20
|
+
/>
|
|
21
|
+
))}
|
|
22
|
+
</view>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
@import "@lynx-js/luna-styles/index.css";
|
|
2
|
+
|
|
3
|
+
.indicator-container {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: row;
|
|
6
|
+
align-items: center;
|
|
7
|
+
justify-content: center;
|
|
8
|
+
height: 48px;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.indicator-item {
|
|
12
|
+
width: 8px;
|
|
13
|
+
height: 8px;
|
|
14
|
+
border-radius: 50%;
|
|
15
|
+
background: var(--primary-content-faded);
|
|
16
|
+
margin: 4px;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.indicator-item.active {
|
|
20
|
+
background: var(--primary-content);
|
|
21
|
+
}
|
package/Custom/index.tsx
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// Copyright 2026 The Lynx Authors. All rights reserved.
|
|
2
|
+
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
+
// LICENSE file in the root directory of this source tree.
|
|
4
|
+
|
|
5
|
+
import { root, useRef } from '@lynx-js/react'
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
Swiper,
|
|
9
|
+
SwiperItem,
|
|
10
|
+
interpolate,
|
|
11
|
+
interpolateJS,
|
|
12
|
+
} from '@lynx-js/lynx-ui'
|
|
13
|
+
import type { SwiperRef } from '@lynx-js/lynx-ui'
|
|
14
|
+
|
|
15
|
+
import './styles.css'
|
|
16
|
+
|
|
17
|
+
const colorsArr: string[] = ['red', 'green', 'yellow', 'purple']
|
|
18
|
+
|
|
19
|
+
function customAnimation(value: number, _index: number) {
|
|
20
|
+
'main thread'
|
|
21
|
+
|
|
22
|
+
const scale = interpolate(value, [-1, 0, 1], [0.5, 1, 0.5])
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
transform: `scale(${scale})`,
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function customAnimationFirstScreen(value: number, _index: number) {
|
|
30
|
+
const scale = interpolateJS(value, [-1, 0, 1], [0.5, 1, 0.5])
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
transform: `scale(${scale})`,
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function SwiperEntry(): JSX.Element {
|
|
38
|
+
const swiperRef = useRef<SwiperRef>(null)
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<view id='container'>
|
|
42
|
+
<Swiper
|
|
43
|
+
ref={swiperRef}
|
|
44
|
+
data={colorsArr}
|
|
45
|
+
itemWidth={250}
|
|
46
|
+
duration={500}
|
|
47
|
+
initialIndex={0}
|
|
48
|
+
mode='normal'
|
|
49
|
+
modeConfig={{
|
|
50
|
+
align: 'center',
|
|
51
|
+
}}
|
|
52
|
+
main-thread:customAnimation={customAnimation}
|
|
53
|
+
customAnimationFirstScreen={customAnimationFirstScreen}
|
|
54
|
+
>
|
|
55
|
+
{({ item, index, realIndex }) => (
|
|
56
|
+
<SwiperItem index={index} key={realIndex} realIndex={realIndex}>
|
|
57
|
+
<view
|
|
58
|
+
class='block-view'
|
|
59
|
+
style={{
|
|
60
|
+
width: '100%',
|
|
61
|
+
height: '250px',
|
|
62
|
+
backgroundColor: item,
|
|
63
|
+
display: 'flex',
|
|
64
|
+
justifyContent: 'center',
|
|
65
|
+
alignItems: 'center',
|
|
66
|
+
}}
|
|
67
|
+
>
|
|
68
|
+
<view
|
|
69
|
+
style={{
|
|
70
|
+
backgroundColor: 'white',
|
|
71
|
+
width: '4px',
|
|
72
|
+
height: '4px',
|
|
73
|
+
}}
|
|
74
|
+
>
|
|
75
|
+
</view>
|
|
76
|
+
</view>
|
|
77
|
+
<text class='image-text'>Number.{index}</text>
|
|
78
|
+
</SwiperItem>
|
|
79
|
+
)}
|
|
80
|
+
</Swiper>
|
|
81
|
+
</view>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
root.render(<SwiperEntry />)
|
|
86
|
+
|
|
87
|
+
export default SwiperEntry
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
.image {
|
|
2
|
+
width: 100%;
|
|
3
|
+
height: 100%;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.image-text {
|
|
7
|
+
position: absolute;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.container {
|
|
11
|
+
width: 100%;
|
|
12
|
+
height: 100%;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.title-container {
|
|
16
|
+
margin-top: 10px;
|
|
17
|
+
margin-bottom: 5px;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.title-text {
|
|
21
|
+
font-size: 16px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.button {
|
|
25
|
+
border: 1px solid;
|
|
26
|
+
border-radius: 4px;
|
|
27
|
+
width: 150px;
|
|
28
|
+
background-color: red;
|
|
29
|
+
margin: 4px 8px;
|
|
30
|
+
padding: 4px 8px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.button-text {
|
|
34
|
+
color: white;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.operation {
|
|
38
|
+
display: flex;
|
|
39
|
+
align-items: center;
|
|
40
|
+
flex-wrap: wrap;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.block {
|
|
44
|
+
display: flex;
|
|
45
|
+
width: 100%;
|
|
46
|
+
margin: 10px;
|
|
47
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// Copyright 2026 The Lynx Authors. All rights reserved.
|
|
2
|
+
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
+
// LICENSE file in the root directory of this source tree.
|
|
4
|
+
|
|
5
|
+
import { root, useRef } from '@lynx-js/react'
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
Swiper,
|
|
9
|
+
SwiperItem,
|
|
10
|
+
interpolate,
|
|
11
|
+
interpolateJS,
|
|
12
|
+
} from '@lynx-js/lynx-ui'
|
|
13
|
+
import type { SwiperRef } from '@lynx-js/lynx-ui'
|
|
14
|
+
|
|
15
|
+
import './styles.css'
|
|
16
|
+
|
|
17
|
+
const colorsArr: string[] = ['red', 'green', 'yellow', 'purple']
|
|
18
|
+
|
|
19
|
+
const ITEM_WIDTH = 250
|
|
20
|
+
|
|
21
|
+
function customAnimation(value: number, _index: number) {
|
|
22
|
+
'main thread'
|
|
23
|
+
|
|
24
|
+
const scale = interpolate(value, [-1, 0, 1], [0.8, 1, 0.8])
|
|
25
|
+
// const scale = 1
|
|
26
|
+
|
|
27
|
+
const centerOffset = ((lynx.__globalProps.screenWidth
|
|
28
|
+
?? SystemInfo.pixelWidth / SystemInfo.pixelRatio) - ITEM_WIDTH) / 2
|
|
29
|
+
const translateX = interpolate(value, [-1, 0, 1], [
|
|
30
|
+
-ITEM_WIDTH + centerOffset,
|
|
31
|
+
centerOffset,
|
|
32
|
+
ITEM_WIDTH + centerOffset,
|
|
33
|
+
], 'extend')
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
transform: `translateX(${translateX}px) scale(${scale})`,
|
|
37
|
+
'transform-origin': 'center',
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function customAnimationFirstScreen(value: number, _index: number) {
|
|
42
|
+
const scale = interpolateJS(value, [-1, 0, 1], [0.8, 1, 0.8])
|
|
43
|
+
// const scale = 1
|
|
44
|
+
const centerOffset = ((lynx.__globalProps.screenWidth
|
|
45
|
+
?? SystemInfo.pixelWidth / SystemInfo.pixelRatio) - ITEM_WIDTH) / 2
|
|
46
|
+
const translateX = interpolateJS(value, [-1, 0, 1], [
|
|
47
|
+
-ITEM_WIDTH + centerOffset,
|
|
48
|
+
centerOffset,
|
|
49
|
+
ITEM_WIDTH + centerOffset,
|
|
50
|
+
], 'extend')
|
|
51
|
+
|
|
52
|
+
console.log(
|
|
53
|
+
'customAnimationFirstScreen',
|
|
54
|
+
value,
|
|
55
|
+
scale,
|
|
56
|
+
translateX,
|
|
57
|
+
centerOffset,
|
|
58
|
+
)
|
|
59
|
+
return {
|
|
60
|
+
transform: `translateX(${translateX}px) scale(${scale})`,
|
|
61
|
+
'transform-origin': 'center',
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function SwiperEntry(): JSX.Element {
|
|
66
|
+
const swiperRef = useRef<SwiperRef>(null)
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<view id='container'>
|
|
70
|
+
<Swiper
|
|
71
|
+
ref={swiperRef}
|
|
72
|
+
data={colorsArr}
|
|
73
|
+
itemWidth={ITEM_WIDTH}
|
|
74
|
+
itemHeight={200}
|
|
75
|
+
duration={500}
|
|
76
|
+
initialIndex={0}
|
|
77
|
+
mode='custom'
|
|
78
|
+
modeConfig={{
|
|
79
|
+
align: 'center',
|
|
80
|
+
}}
|
|
81
|
+
main-thread:customAnimation={customAnimation}
|
|
82
|
+
customAnimationFirstScreen={customAnimationFirstScreen}
|
|
83
|
+
>
|
|
84
|
+
{({ item, index, realIndex }) => (
|
|
85
|
+
<SwiperItem index={index} key={realIndex} realIndex={realIndex}>
|
|
86
|
+
<view
|
|
87
|
+
class='block-view'
|
|
88
|
+
style={{
|
|
89
|
+
width: '100%',
|
|
90
|
+
height: '100%',
|
|
91
|
+
backgroundColor: item,
|
|
92
|
+
display: 'flex',
|
|
93
|
+
justifyContent: 'center',
|
|
94
|
+
alignItems: 'center',
|
|
95
|
+
}}
|
|
96
|
+
>
|
|
97
|
+
<view
|
|
98
|
+
style={{
|
|
99
|
+
backgroundColor: 'white',
|
|
100
|
+
width: '4px',
|
|
101
|
+
height: '4px',
|
|
102
|
+
}}
|
|
103
|
+
>
|
|
104
|
+
</view>
|
|
105
|
+
</view>
|
|
106
|
+
<text class='image-text'>Number.{index}</text>
|
|
107
|
+
</SwiperItem>
|
|
108
|
+
)}
|
|
109
|
+
</Swiper>
|
|
110
|
+
</view>
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
root.render(<SwiperEntry />)
|
|
115
|
+
|
|
116
|
+
export default SwiperEntry
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
.image {
|
|
2
|
+
width: 100%;
|
|
3
|
+
height: 100%;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.image-text {
|
|
7
|
+
position: absolute;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.container {
|
|
11
|
+
width: 100%;
|
|
12
|
+
height: 100%;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.title-container {
|
|
16
|
+
margin-top: 10px;
|
|
17
|
+
margin-bottom: 5px;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.title-text {
|
|
21
|
+
font-size: 16px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.button {
|
|
25
|
+
border: 1px solid;
|
|
26
|
+
border-radius: 4px;
|
|
27
|
+
width: 150px;
|
|
28
|
+
background-color: red;
|
|
29
|
+
margin: 4px 8px;
|
|
30
|
+
padding: 4px 8px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.button-text {
|
|
34
|
+
color: white;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.operation {
|
|
38
|
+
display: flex;
|
|
39
|
+
align-items: center;
|
|
40
|
+
flex-wrap: wrap;
|
|
41
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Copyright 2026 The Lynx Authors. All rights reserved.
|
|
2
|
+
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
+
// LICENSE file in the root directory of this source tree.
|
|
4
|
+
|
|
5
|
+
import {} from '@lynx-js/react'
|
|
6
|
+
import './styles.css'
|
|
7
|
+
|
|
8
|
+
export function Card({
|
|
9
|
+
index,
|
|
10
|
+
}: {
|
|
11
|
+
index: number
|
|
12
|
+
}) {
|
|
13
|
+
return (
|
|
14
|
+
<view className='card'>
|
|
15
|
+
<text className='card-text'>{index}</text>
|
|
16
|
+
<text className='title'>
|
|
17
|
+
Swiper
|
|
18
|
+
</text>
|
|
19
|
+
<text className='subtitle'>
|
|
20
|
+
@lynx-js/lynx-ui
|
|
21
|
+
</text>
|
|
22
|
+
</view>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// Copyright 2026 The Lynx Authors. All rights reserved.
|
|
2
|
+
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
+
// LICENSE file in the root directory of this source tree.
|
|
4
|
+
|
|
5
|
+
import { root } from '@lynx-js/react'
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
Swiper,
|
|
9
|
+
SwiperItem,
|
|
10
|
+
interpolate,
|
|
11
|
+
interpolateJS,
|
|
12
|
+
} from '@lynx-js/lynx-ui'
|
|
13
|
+
|
|
14
|
+
import { Card } from './Card'
|
|
15
|
+
|
|
16
|
+
import './styles.css'
|
|
17
|
+
|
|
18
|
+
const itemArr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
|
19
|
+
const ITEM_WIDTH = 220
|
|
20
|
+
const ITEM_HEIGHT = 330
|
|
21
|
+
|
|
22
|
+
const customAnimation = (value: number) => {
|
|
23
|
+
'main thread'
|
|
24
|
+
const translateX = interpolate(value, [-1, 0], [-ITEM_WIDTH, 0], 'clamp')
|
|
25
|
+
const translateY = interpolate(value, [0, 1], [0, -18], 'extend')
|
|
26
|
+
const rotate = interpolate(value, [-1, 0], [-15, 0], 'clamp')
|
|
27
|
+
const scale = interpolate(value, [0, 1], [1, 0.95], 'extend')
|
|
28
|
+
const opacity = interpolate(value, [-1, -0.8, 0, 1], [0, 0.9, 1, 1], 'clamp')
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
transform:
|
|
32
|
+
`translate(${translateX}px, ${translateY}px) rotateZ(${rotate}deg) scale(${scale})`,
|
|
33
|
+
opacity: opacity,
|
|
34
|
+
'transform-origin': 'center',
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const customAnimationFirstScreen = (value: number, _index: number) => {
|
|
39
|
+
const translateX = interpolateJS(value, [-1, 0], [-ITEM_WIDTH, 0], 'clamp')
|
|
40
|
+
const translateY = interpolateJS(value, [0, 1], [0, -18], 'extend')
|
|
41
|
+
const rotate = interpolateJS(value, [-1, 0], [-15, 0], 'clamp')
|
|
42
|
+
const zIndex = interpolateJS(
|
|
43
|
+
value,
|
|
44
|
+
itemArr.map((_, index) => index),
|
|
45
|
+
itemArr.map((_, index) => (itemArr.length - index) * 10),
|
|
46
|
+
'extend',
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
const scale = interpolateJS(
|
|
50
|
+
value,
|
|
51
|
+
[0, 1, 0],
|
|
52
|
+
[1, 0.95, 1],
|
|
53
|
+
'extend',
|
|
54
|
+
)
|
|
55
|
+
const opacity = interpolateJS(
|
|
56
|
+
value,
|
|
57
|
+
[-1, -0.8, 0, 1],
|
|
58
|
+
[0, 0.9, 1, 1],
|
|
59
|
+
'clamp',
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
transform:
|
|
64
|
+
`translate(${translateX}px, ${translateY}px) rotateZ(${rotate}deg) scale(${scale})`,
|
|
65
|
+
opacity: opacity,
|
|
66
|
+
'transform-origin': 'center',
|
|
67
|
+
zIndex: zIndex,
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function SwiperEntry() {
|
|
72
|
+
return (
|
|
73
|
+
<view className='demo-container lunaris-dark'>
|
|
74
|
+
<Swiper
|
|
75
|
+
data={itemArr}
|
|
76
|
+
itemWidth={ITEM_WIDTH}
|
|
77
|
+
itemHeight={ITEM_HEIGHT}
|
|
78
|
+
containerWidth={ITEM_WIDTH}
|
|
79
|
+
duration={500}
|
|
80
|
+
initialIndex={0}
|
|
81
|
+
mode='custom'
|
|
82
|
+
main-thread:customAnimation={customAnimation}
|
|
83
|
+
customAnimationFirstScreen={customAnimationFirstScreen}
|
|
84
|
+
style={{
|
|
85
|
+
overflow: 'visible',
|
|
86
|
+
}}
|
|
87
|
+
>
|
|
88
|
+
{({ index, realIndex }) => (
|
|
89
|
+
<SwiperItem index={index} key={realIndex} realIndex={realIndex}>
|
|
90
|
+
<view
|
|
91
|
+
class='block-view'
|
|
92
|
+
style={{
|
|
93
|
+
width: '100%',
|
|
94
|
+
height: '100%',
|
|
95
|
+
display: 'flex',
|
|
96
|
+
justifyContent: 'center',
|
|
97
|
+
alignItems: 'center',
|
|
98
|
+
}}
|
|
99
|
+
>
|
|
100
|
+
<Card index={index} />
|
|
101
|
+
</view>
|
|
102
|
+
</SwiperItem>
|
|
103
|
+
)}
|
|
104
|
+
</Swiper>
|
|
105
|
+
</view>
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
root.render(<SwiperEntry />)
|
|
110
|
+
|
|
111
|
+
export default SwiperEntry
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
@import "@lynx-js/luna-styles/index.css";
|
|
2
|
+
|
|
3
|
+
.demo-container {
|
|
4
|
+
display: flex;
|
|
5
|
+
width: 100%;
|
|
6
|
+
height: 100%;
|
|
7
|
+
flex-direction: column;
|
|
8
|
+
justify-content: center;
|
|
9
|
+
padding-top: 48px;
|
|
10
|
+
padding-bottom: 24px;
|
|
11
|
+
background: linear-gradient(
|
|
12
|
+
0deg,
|
|
13
|
+
var(--gradient-a),
|
|
14
|
+
var(--gradient-b),
|
|
15
|
+
);
|
|
16
|
+
align-items: center;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.image {
|
|
20
|
+
width: 100%;
|
|
21
|
+
height: 100%;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.image-text {
|
|
25
|
+
position: absolute;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.card {
|
|
29
|
+
width: 100%;
|
|
30
|
+
height: 100%;
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
align-items: center;
|
|
34
|
+
justify-content: center;
|
|
35
|
+
background-color: var(--canvas);
|
|
36
|
+
border-radius: 8px;
|
|
37
|
+
box-shadow:
|
|
38
|
+
0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
|
39
|
+
0 4px 6px -4px rgba(0, 0, 0, 0.1);
|
|
40
|
+
border-color: var(--line);
|
|
41
|
+
border-width: 1px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.card-text {
|
|
45
|
+
color: var(--primary);
|
|
46
|
+
font-size: 128px;
|
|
47
|
+
font-weight: 600;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.title {
|
|
51
|
+
font-size: 16px;
|
|
52
|
+
font-weight: 600;
|
|
53
|
+
color: var(--content);
|
|
54
|
+
margin-top: 4px;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.subtitle {
|
|
58
|
+
font-size: 10px;
|
|
59
|
+
color: var(--content-subtle);
|
|
60
|
+
margin-top: 1px;
|
|
61
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Copyright 2026 The Lynx Authors. All rights reserved.
|
|
2
|
+
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
+
// LICENSE file in the root directory of this source tree.
|
|
4
|
+
|
|
5
|
+
import './styles.css'
|
|
6
|
+
import { Button as ButtonInner } from '@lynx-js/lynx-ui'
|
|
7
|
+
|
|
8
|
+
const ButtonStyle = {
|
|
9
|
+
border: '1px solid',
|
|
10
|
+
'border-radius': '4px',
|
|
11
|
+
width: '150px',
|
|
12
|
+
'background-color': 'red',
|
|
13
|
+
margin: '4px 8px',
|
|
14
|
+
padding: '4px 8px',
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const ButtonTextStyle = {
|
|
18
|
+
color: 'white',
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function Button(props: {
|
|
22
|
+
onClick: () => void
|
|
23
|
+
text: string
|
|
24
|
+
}) {
|
|
25
|
+
return (
|
|
26
|
+
<ButtonInner
|
|
27
|
+
style={ButtonStyle}
|
|
28
|
+
onClick={props.onClick}
|
|
29
|
+
>
|
|
30
|
+
<text style={ButtonTextStyle}>{props.text}</text>
|
|
31
|
+
</ButtonInner>
|
|
32
|
+
)
|
|
33
|
+
}
|