@ray-js/lamp-bead-strip 1.0.1-beta-1

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/README.md ADDED
@@ -0,0 +1,131 @@
1
+ English | [简体中文](./README-zh_CN.md)
2
+
3
+ # @ray-js/lamp-bead-strip
4
+
5
+ [![latest](https://img.shields.io/npm/v/@ray-js/lamp-bead-strip/latest.svg)](https://www.npmjs.com/package/@ray-js/lamp-bead-strip) [![download](https://img.shields.io/npm/dt/@ray-js/lamp-bead-strip.svg)](https://www.npmjs.com/package/@ray-js/lamp-bead-strip)
6
+
7
+ > Animated LED strip
8
+
9
+ Directly using `canvas` to draw animation effects, and internally preventing duplicate rendering, achieving simultaneous rendering of multiple animations on low-end machine pages without stuttering.
10
+
11
+ ## Installation
12
+
13
+ ```sh
14
+ $ npm install @ray-js/lamp-bead-strip
15
+ # or
16
+ $ yarn add @ray-js/lamp-bead-strip
17
+ ```
18
+
19
+ ## Develop
20
+
21
+ ```sh
22
+ # watch compile component code
23
+ yarn watch
24
+ # watch compile demo
25
+ yarn start:tuya
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ ### Basic usage
31
+
32
+ `colors`and `canvasId`are mandatory, otherwise the animation cannot run`canvasId`must ensure page uniqueness. When we input different animation modes`mode`, the component will automatically play the animation.
33
+
34
+ ```tsx
35
+ import LampBeadStrip from '@ray-js/lamp-bead-strip';
36
+ export default () => (
37
+ <LampBeadStrip
38
+ canvasId="diy-scene"
39
+ speed={80}
40
+ mode={10}
41
+ colors={['rgb(255,0,0)', 'rgb(0,255,0)', 'rgb(0,0,255)']}
42
+ contentValue={{ segmented: 1 }}
43
+ />
44
+ );
45
+ ```
46
+
47
+ ### Pauses
48
+
49
+ `ready`allows you to set whether the animation of the component plays or pauses.
50
+
51
+ ```tsx
52
+ import LampBeadStrip from '@ray-js/lamp-bead-strip';
53
+ export default () => (
54
+ <LampBeadStrip
55
+ canvasId="diy-scene1"
56
+ mode={2}
57
+ ready={false}
58
+ colors={['rgb(255,0,0)', 'rgb(0,255,0)', 'rgb(0,0,255)']}
59
+ contentValue={{ segmented: 1, direction: 1 }}
60
+ />
61
+ );
62
+ ```
63
+
64
+ ### Customize Scaling Size
65
+
66
+ Since the components are drawn through canvas, the internal dimensions are fixed. The component internally handles screen scaling logic, which is controlled through the`scale`property. If you want to modify the size of a component, you can customize the`scale`property to achieve your goal. The following use case expects the component size to be`1.1`times larger than before.
67
+
68
+ > It should be noted that the component only sets the scale once during initialization, so if the scale property is changed or set after initialization, it will be invalid
69
+
70
+ ```tsx
71
+ import LampBeadStrip from '@ray-js/lamp-bead-strip';
72
+ import { getSystemInfoSync } from '@ray-js/ray';
73
+
74
+ const { windowWidth = 375 } = getSystemInfoSync();
75
+ export default () => {
76
+ const scale = (windowWidth / 375) * 1.1;
77
+ return (
78
+ <LampBeadStrip
79
+ containerStyle={`height: ${48 * 1.1}rpx;width:${570 * 1.1}rpx;`}
80
+ mode={16}
81
+ canvasId="template2"
82
+ scale={scale}
83
+ colors={['rgb(255,0,0)', 'rgb(0,255,0)', 'rgb(0,0,255)']}
84
+ contentValue={{ expand: 1 }}
85
+ />
86
+ );
87
+ };
88
+ ```
89
+
90
+ ### Set the light off color
91
+
92
+ `closeColor` can set the color of lights that do not have color in the animation, that is, the color of the light beads that turn off the lights in the device. This way, the light strip component can adapt to multiple background colors, preventing the node color that turns off the lights from being the same as the background color.
93
+
94
+ ```tsx
95
+ import LampBeadStrip from '@ray-js/lamp-bead-strip';
96
+
97
+ export default () => {
98
+ return (
99
+ <LampBeadStrip
100
+ mode={16}
101
+ canvasId="template3"
102
+ closeColor="rgba(255,255,255,.6)"
103
+ colors={['rgb(255,0,0)', 'rgb(0,255,0)', 'rgb(0,0,255)']}
104
+ />
105
+ );
106
+ };
107
+ ```
108
+
109
+ ### Animation Mode
110
+
111
+ > Phase 1: 6, 1. Gradient, 2. Jump, 3. Breath, 4. Blink, 10. Flowing Water, 11. Rainbow
112
+ > Phase 2 10, 5 shooting stars, 6 accumulation, 7 falling, 8 chasing light, 9 drifting, 12 flashing, 13 rebounding, 14 shuttling, 15 chaotic flashing, 16 opening and closing
113
+
114
+ | Animation mode value | description | Contains control types contentValue |
115
+ | -------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------ |
116
+ | 1 | (Phase 1)Gradient | segmented(intact 0/subsection 1) |
117
+ | 2 | (Phase 1)Jump | segmented(intact 0/subsection 1) |
118
+ | 3 | (Phase 1)Breath | segmented(intact 0/subsection 1) |
119
+ | 4 | (Phase 1)Blink | segmented(intact 0/subsection 1) |
120
+ | 10 | (Phase 1)Flowing Water | direction(Clockwise 0/anti-clockwise 1) |
121
+ | 11 | (Phase 1)Rainbow | direction(Clockwise 0/anti-clockwise 1) |
122
+ | 5 | (Phase 2)shooting stars | direction(Clockwise 0/anti-clockwise 1) expand(shooting-stars 0/meteor-shower 1/Colorful-meteor 2) |
123
+ | 6 | (Phase 2)accumulation | direction(Clockwise 0/anti-clockwise 1) segmented(intact 0/subsection 1) |
124
+ | 7 | (Phase 2)falling | direction(Clockwise 0/anti-clockwise 1) segmented(intact 0/subsection 1) |
125
+ | 8 | (Phase 2)chasing light | direction(Clockwise 0/anti-clockwise 1) |
126
+ | 9 | (Phase 2)drifting | direction(Clockwise 0/anti-clockwise 1) |
127
+ | 12 | (Phase 2)flashing | segmented(intact 0/subsection 1) |
128
+ | 13 | (Phase 2)rebounding | expand(rebound 0/Colorful rebound 1) |
129
+ | 14 | (Phase 2)shuttling | - |
130
+ | 15 | (Phase 2)chaotic flashing | - |
131
+ | 16 | (Phase 2)opening and closing | expand(Same Time 0/staggered 1) |
@@ -0,0 +1,58 @@
1
+ /*
2
+ * @Author: mjh
3
+ * @Date: 2024-09-02 11:42:04
4
+ * @LastEditors: mjh
5
+ * @LastEditTime: 2024-10-16 17:37:37
6
+ * @Description:
7
+ */
8
+ import Render from './index.rjs';
9
+ // eslint-disable-next-line no-undef
10
+ Component({
11
+ properties: {
12
+ /** {
13
+ scale: Number,
14
+ mode: String,
15
+ ready: Boolean,
16
+ colors: Array,
17
+ canvasId: String,
18
+ contentValue: Object,
19
+ containerStyle: String,
20
+ canvasStyle: String,
21
+ closeColor: String
22
+ } */
23
+ prop: Object
24
+ },
25
+ data() {
26
+ return {
27
+ pre: {},
28
+ isReady: false
29
+ };
30
+ },
31
+ lifetimes: {
32
+ attached() {
33
+ this.render = new Render(this);
34
+ },
35
+ ready() {
36
+ if (!this.render) {
37
+ this.render = new Render(this);
38
+ }
39
+ this.pre = this.data.prop;
40
+ this.render.renderLight(this.data.prop);
41
+ this.isReady = true;
42
+ },
43
+ detached() {
44
+ this.render.stopLight();
45
+ }
46
+ },
47
+ observers: {
48
+ prop(res) {
49
+ // canvas元素加载完成后再渲染
50
+ if (!this.isReady || JSON.stringify(res) === JSON.stringify(this.pre || {})) {
51
+ return;
52
+ }
53
+ this.render.renderLight(res);
54
+ this.pre = res;
55
+ }
56
+ },
57
+ methods: {}
58
+ });
@@ -0,0 +1,4 @@
1
+ {
2
+ "component": true,
3
+ "usingComponents": {}
4
+ }
@@ -0,0 +1,151 @@
1
+ /*
2
+ * @Author: mjh
3
+ * @Date: 2024-09-02 11:42:04
4
+ * @LastEditors: mjh
5
+ * @LastEditTime: 2024-10-21 14:31:04
6
+ * @Description:
7
+ */
8
+
9
+ import { topList } from './utils'
10
+ import modeOption from './mode/index'
11
+ export default Render({
12
+ ctx: null,
13
+ offset: 0,
14
+ scale: 1,
15
+ timer: null,
16
+ colors: [],
17
+ contentValue: {},
18
+ speed: 50,
19
+ ready: true,
20
+ mode: null,
21
+ animationStore: null,
22
+ closeRgb: null,
23
+ /**
24
+ * @name: 渲染灯带动画
25
+ * @desc:
26
+ * @param {*} props
27
+ * @return {*}
28
+ */
29
+ async renderLight(props) {
30
+ this.scale = props.scale || 1;
31
+ if (!props.canvasId) {
32
+ console.log('canvasId 是必传项!');
33
+ return
34
+ }
35
+ // 初始化记录和缩放 canvas
36
+ if(!this.ctx) {
37
+ const canvas5 = await getCanvasById('ray-lamp-bead-strip-canvasId-' + props.canvasId);
38
+ this.ctx = canvas5.getContext('2d');
39
+ this.ctx.scale(this.scale, this.scale);
40
+ }
41
+ this.ready = props.ready ?? true
42
+ // 只有关键属性变化才重置动画
43
+ const isSameContent = `${props.closeColor}${props.mode}${props.colors.length}${props.contentValue.expand}${props.contentValue.segmented}` === `${this.closeRgb}${this.mode}${this.colors.length}${this.contentValue.expand}${this.contentValue.segmented}`
44
+ this.closeRgb = props.closeColor;
45
+ this.mode = props.mode;
46
+ this.colors = props.colors;
47
+ this.contentValue = props.contentValue || {};
48
+ this.speed = props.speed || 50;
49
+ // 获取对应模式的动画方法
50
+ const currFun = modeOption[this.mode];
51
+ const isSafe = this.errorCheck(currFun, props)
52
+ if(!isSafe) return
53
+ this.animationStore = modeOption[this.mode](props.colors, props.contentValue, this.closeRgb)
54
+ this.startLight(!isSameContent)
55
+ },
56
+ /**
57
+ * @name: 开始动画
58
+ * @desc:
59
+ * @param {*} init 是否重置动画
60
+ * @return {*}
61
+ */
62
+ startLight(init) {
63
+ // 重置动画
64
+ if (init) {
65
+ this.offset = 0
66
+ }
67
+ this.stopLight();
68
+ this.draw();
69
+ // 动画更新时间
70
+ const speed = this.speed < 30 ? 200 + (30 - this.speed) * 5 : 6000 / this.speed;
71
+ if(!this.ready) return
72
+ this.timer = setInterval(() => {
73
+ this.draw();
74
+ },speed);
75
+ },
76
+ /**
77
+ * @name: 暂停动画
78
+ * @desc:
79
+ * @return {*}
80
+ */
81
+ async stopLight() {
82
+ if (!this.timer) return;
83
+ clearInterval(this.timer);
84
+ this.timer = null;
85
+ },
86
+ /**
87
+ * @name: 绘制动画
88
+ * @desc:
89
+ * @return {*}
90
+ */
91
+ draw() {
92
+ const { colorList, length } = this.animationStore
93
+ this.drawPoint(colorList[this.offset]);
94
+ this.offset += 1;
95
+ if(this.offset === length) this.offset = 0
96
+ },
97
+ /**
98
+ * @name: 绘制点
99
+ * @desc:
100
+ * @param {*} colorList 颜色列表
101
+ * @return {*}
102
+ */
103
+ drawPoint(colorList) {
104
+ if(!colorList) return;
105
+ this.ctx.globalCompositeOperation = 'destination-over';
106
+ // clear canvas
107
+ this.ctx.clearRect(0, 0, this.ctx.canvas.clientWidth, this.ctx.canvas.clientHeight);
108
+ let startTop = (8.75 + 4.5)
109
+ colorList.forEach((_, index) => {
110
+ const color = colorList[index]
111
+ const topMid = topList[index]
112
+ startTop -= topMid
113
+ //开始绘制
114
+ this.ctx.beginPath();
115
+ this.ctx.arc(
116
+ (4.5 + 14.45 * index),
117
+ startTop,
118
+ 4.5,
119
+ 0,
120
+ 2*Math.PI);
121
+ this.ctx.fillStyle = color;
122
+ this.ctx.fill();
123
+ })
124
+ },
125
+ /**
126
+ * @name: 异常错误检测
127
+ * @desc:
128
+ * @param {*} currFun 动画方法
129
+ * @param {*} props 入参
130
+ * @return {*}
131
+ */
132
+ errorCheck(currFun, props) {
133
+ if (!currFun) {
134
+ console.error('错误的动画mode类型!');
135
+ return false
136
+ }
137
+ if (!props.colors?.length) {
138
+ console.error('未传入颜色列表!');
139
+ return false
140
+ }
141
+ if (props.colors.some(item => typeof item === 'string' ? !item.startsWith('rgb(') : true)) {
142
+ console.error('颜色必须是rgb!');
143
+ return false
144
+ }
145
+ if (props.speed > 100 || props.speed < 1) {
146
+ console.error('错误的speed值,其范围为1~100!');
147
+ return false
148
+ }
149
+ return true
150
+ }
151
+ });
@@ -0,0 +1,11 @@
1
+ <view
2
+ class="ray-lamp-bead-strip {{prop.className}}"
3
+ style="{{prop.containerStyle}}"
4
+ >
5
+ <canvas
6
+ type="2d"
7
+ class="ray-lamp-bead-strip-canvas"
8
+ canvas-id="ray-lamp-bead-strip-canvasId-{{prop.canvasId}}"
9
+ style="{{prop.canvasStyle}}"
10
+ ></canvas>
11
+ </view>
@@ -0,0 +1,9 @@
1
+ .ray-lamp-bead-strip {
2
+ height: 48rpx;
3
+ width:570rpx;
4
+ }
5
+
6
+ .ray-lamp-bead-strip-canvas {
7
+ width: 100%;
8
+ height: 100%;
9
+ }
@@ -0,0 +1,52 @@
1
+ /** 一期 */
2
+ import mode1 from './mode1';
3
+ import mode2 from './mode2';
4
+ import mode3 from './mode3';
5
+ import mode4 from './mode4';
6
+ import mode10 from './mode10';
7
+ import mode11 from './mode11';
8
+ /** 二期 */
9
+ import mode5 from './mode5';
10
+ import mode6 from './mode6';
11
+ import mode7 from './mode7';
12
+ import mode8 from './mode8';
13
+ import mode9 from './mode9';
14
+ import mode12 from './mode12';
15
+ import mode13 from './mode13';
16
+ import mode14 from './mode14';
17
+ import mode15 from './mode15';
18
+ import mode16 from './mode16';
19
+ export default {
20
+ /** 渐变 */
21
+ 1: mode1,
22
+ /** 跳变 */
23
+ 2: mode2,
24
+ /** 呼吸 */
25
+ 3: mode3,
26
+ /** 闪烁 */
27
+ 4: mode4,
28
+ /** 流水 */
29
+ 10: mode10,
30
+ /** 彩虹 */
31
+ 11: mode11,
32
+ /** 流星 */
33
+ 5: mode5,
34
+ /** 堆积 */
35
+ 6: mode6,
36
+ /** 飘落 */
37
+ 7: mode7,
38
+ /** 追光 */
39
+ 8: mode8,
40
+ /** 飘动 */
41
+ 9: mode9,
42
+ /** 闪现 */
43
+ 12: mode12,
44
+ /** 反弹 */
45
+ 13: mode13,
46
+ /** 穿梭 */
47
+ 14: mode14,
48
+ /** 乱闪 */
49
+ 15: mode15,
50
+ /** 开合 */
51
+ 16: mode16
52
+ };
@@ -0,0 +1,29 @@
1
+ import { generateGradientColors, getListByIndex, arrayFill } from '../utils';
2
+
3
+ /** 渐变 */
4
+ const mode = (colors, option) => {
5
+ const {
6
+ segmented
7
+ } = option || {};
8
+ let allColor = [];
9
+ colors.forEach((element, index) => {
10
+ const afterColor = colors[index + 1] || colors[0];
11
+ const colorList = generateGradientColors([element, afterColor], 10);
12
+ allColor = [...allColor, ...colorList];
13
+ });
14
+ if (!segmented) {
15
+ const colorList = allColor.map(item => arrayFill(20, item));
16
+ return {
17
+ colorList,
18
+ length: colorList.length
19
+ };
20
+ }
21
+ const colorList = allColor.map((_, index) => {
22
+ return [...arrayFill(4, allColor[index]), ...arrayFill(4, getListByIndex(allColor, index + 10)), ...arrayFill(4, getListByIndex(allColor, index + 20)), ...arrayFill(4, getListByIndex(allColor, index + 30)), ...arrayFill(4, getListByIndex(allColor, index + 40))];
23
+ });
24
+ return {
25
+ colorList,
26
+ length: colorList.length
27
+ };
28
+ };
29
+ export default mode;
@@ -0,0 +1,45 @@
1
+ /*
2
+ * @Author: mjh
3
+ * @Date: 2024-10-21 14:23:12
4
+ * @LastEditors: mjh
5
+ * @LastEditTime: 2024-10-21 14:24:06
6
+ * @Description:
7
+ */
8
+ import { arrayFill } from '../utils';
9
+
10
+ /** 流水 */
11
+ const mode = (colors, option) => {
12
+ const {
13
+ direction
14
+ } = option || {};
15
+ let numList = [];
16
+ switch (colors.length) {
17
+ case 2:
18
+ numList = arrayFill(colors.length, 15);
19
+ break;
20
+ case 3:
21
+ numList = arrayFill(colors.length, 10);
22
+ break;
23
+ case 4:
24
+ case 5:
25
+ numList = arrayFill(colors.length, 6);
26
+ break;
27
+ case 6:
28
+ case 7:
29
+ case 8:
30
+ numList = arrayFill(colors.length, 5);
31
+ break;
32
+ default:
33
+ break;
34
+ }
35
+ const allColor = numList.map((item, index) => arrayFill(item, colors[index])).flat(1);
36
+ const colorList = allColor.map((_, index) => {
37
+ const list = [...allColor.slice(index), ...allColor.slice(0, index)];
38
+ return direction ? list : list.reverse();
39
+ });
40
+ return {
41
+ colorList,
42
+ length: colorList.length
43
+ };
44
+ };
45
+ export default mode;
@@ -0,0 +1,45 @@
1
+ /*
2
+ * @Author: mjh
3
+ * @Date: 2024-10-21 14:23:12
4
+ * @LastEditors: mjh
5
+ * @LastEditTime: 2024-10-21 14:24:33
6
+ * @Description:
7
+ */
8
+ import { arrayFill } from '../utils';
9
+
10
+ /** 彩虹 */
11
+ const mode = (colors, option) => {
12
+ const {
13
+ direction
14
+ } = option || {};
15
+ let colorList = colors;
16
+ switch (colors.length) {
17
+ case 2:
18
+ case 4:
19
+ case 6:
20
+ case 8:
21
+ colorList = arrayFill(5, colors).flat(1);
22
+ break;
23
+ case 3:
24
+ case 7:
25
+ colorList = arrayFill(10, colors).flat(1);
26
+ break;
27
+ case 5:
28
+ colorList = arrayFill(2, colors).flat(1);
29
+ break;
30
+ default:
31
+ break;
32
+ }
33
+ const allColor = colorList.map(item => arrayFill(4, item)).flat(1);
34
+ const colorAnimation = allColor.map((_, index) => {
35
+ const endIndex = index + 20;
36
+ const endColor = endIndex > allColor.length - 1 ? allColor.slice(0, endIndex - allColor.length + 1) : [];
37
+ const list = [...allColor.slice(index, index + 20), ...endColor];
38
+ return direction ? list : list.reverse();
39
+ });
40
+ return {
41
+ colorList: colorAnimation,
42
+ length: colorAnimation.length
43
+ };
44
+ };
45
+ export default mode;
@@ -0,0 +1,80 @@
1
+ /*
2
+ * @Author: mjh
3
+ * @Date: 2024-10-21 14:23:12
4
+ * @LastEditors: mjh
5
+ * @LastEditTime: 2024-10-21 14:27:13
6
+ * @Description:
7
+ */
8
+ import { arrayFill, splitArray } from '../utils';
9
+
10
+ /** 闪现 */
11
+ const mode = (colors, option, closeRgb) => {
12
+ const {
13
+ segmented
14
+ } = option || {};
15
+ const closeColors = arrayFill(4, closeRgb);
16
+ // 全段
17
+ if (!segmented) {
18
+ const colorAnimation = colors.map(item => {
19
+ let partCheckList = arrayFill(5, false);
20
+ const partColors = arrayFill(4, item);
21
+ const fillColors = arrayFill(6, '').map((_, index) => {
22
+ if (index) {
23
+ const currIndexList = [];
24
+ partCheckList.forEach((check, ind) => {
25
+ !check && currIndexList.push(ind);
26
+ });
27
+ const checkIndex = Math.ceil(Math.random() * (currIndexList.length - 1));
28
+ partCheckList[currIndexList[checkIndex]] = true;
29
+ }
30
+ const list = partCheckList.map(part => part ? partColors : closeColors).flat(1);
31
+ return arrayFill(2, list);
32
+ }).flat(1);
33
+ fillColors.push(...arrayFill(3, arrayFill(20, item)));
34
+ return fillColors;
35
+ }).flat(1);
36
+ return {
37
+ colorList: colorAnimation,
38
+ length: colorAnimation.length
39
+ };
40
+ }
41
+ // 分段
42
+ let colorList = colors;
43
+ switch (colors.length) {
44
+ case 2:
45
+ case 3:
46
+ case 4:
47
+ case 6:
48
+ case 7:
49
+ case 8:
50
+ colorList = arrayFill(5, colors).flat(1);
51
+ break;
52
+ case 5:
53
+ break;
54
+ default:
55
+ break;
56
+ }
57
+ const splitColorList = splitArray(colorList, 5);
58
+ const colorAnimation = splitColorList.map(colorItemList => {
59
+ let partCheckList = arrayFill(5, false);
60
+ const fillColors = arrayFill(6, '').map((_, index) => {
61
+ if (index) {
62
+ const currIndexList = [];
63
+ partCheckList.forEach((item, ind) => {
64
+ !item && currIndexList.push(ind);
65
+ });
66
+ const checkIndex = Math.ceil(Math.random() * (currIndexList.length - 1));
67
+ partCheckList[currIndexList[checkIndex]] = true;
68
+ }
69
+ const list = partCheckList.map((item, indexs) => item ? arrayFill(4, colorItemList[indexs]) : closeColors).flat(1);
70
+ return arrayFill(3, list);
71
+ }).flat(1);
72
+ fillColors.push(...arrayFill(4, fillColors[fillColors.length - 1]));
73
+ return fillColors;
74
+ }).flat(1);
75
+ return {
76
+ colorList: colorAnimation,
77
+ length: colorAnimation.length
78
+ };
79
+ };
80
+ export default mode;
@@ -0,0 +1,35 @@
1
+ /*
2
+ * @Author: mjh
3
+ * @Date: 2024-10-21 14:23:12
4
+ * @LastEditors: mjh
5
+ * @LastEditTime: 2024-10-21 14:27:45
6
+ * @Description:
7
+ */
8
+ import { arrayFill, generateGradientColors } from '../utils';
9
+
10
+ /** 反弹 */
11
+ const mode = (colors, option, closeRgb) => {
12
+ const {
13
+ expand
14
+ } = option || {};
15
+ const closeColors = arrayFill(20, closeRgb);
16
+ const colorList = colors % 2 === 0 ? colors : arrayFill(2, colors).flat(1);
17
+ let direction = 'right';
18
+ let isFirst = true;
19
+ const colorAnimation = colorList.map((item, index) => {
20
+ const currColors = !expand ? arrayFill(5, item) : generateGradientColors([item, colorList[index + 1] || colorList[0]], 5);
21
+ const colorRoadList = arrayFill(isFirst ? 16 : 15, '').map((_, ind) => {
22
+ const currList = [...closeColors];
23
+ currList.splice(isFirst ? ind : ind + 1, 5, ...currColors);
24
+ return direction === 'right' ? currList : currList.reverse();
25
+ });
26
+ isFirst = false;
27
+ direction = direction === 'right' ? 'left' : 'right';
28
+ return colorRoadList;
29
+ }).flat(1);
30
+ return {
31
+ colorList: colorAnimation,
32
+ length: colorAnimation.length
33
+ };
34
+ };
35
+ export default mode;