如何在React-Native应用中实现类似糖果传奇的关卡升级地图UI
嘿,刚好之前帮朋友做过类似的糖果传奇风格关卡地图,给你梳理一下实现思路和核心代码,应该能帮你快速上手!
实现思路与核心步骤
这类关卡地图的核心是线性排列的关卡节点+节点间的状态连线,再配合滚动、交互逻辑就能还原效果。下面一步步拆解:
1. 拆分核心组件
把复杂的UI拆成独立可复用的小组件,维护起来更方便:
- LevelNode(关卡节点):负责单个关卡的显示(关卡号、状态样式)和点击交互
- LevelConnector(关卡连线):负责连接相邻关卡,根据关卡状态显示不同样式(实线/虚线)
- LevelMap(地图容器):整合上面两个组件,处理整体布局、滚动和状态管理
关卡节点组件示例
import React from 'react'; import { TouchableOpacity, Text, StyleSheet } from 'react-native'; const LevelNode = ({ level, isCompleted, isCurrent, onPress }) => { // 根据状态设置背景色 let backgroundColor; if (isCurrent) { backgroundColor = '#FDD835'; // 当前关卡用高亮黄色 } else if (isCompleted) { backgroundColor = '#4CAF50'; // 已通关用绿色 } else { backgroundColor = '#9E9E9E'; // 未解锁用灰色 } return ( <TouchableOpacity style={[styles.node, { backgroundColor }]} onPress={onPress} disabled={!isCompleted && !isCurrent} // 未解锁关卡禁止点击 > <Text style={styles.levelText}>{level}</Text> </TouchableOpacity> ); }; const styles = StyleSheet.create({ node: { width: 60, height: 60, borderRadius: 30, justifyContent: 'center', alignItems: 'center', marginVertical: 10, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.2, elevation: 3, // 安卓阴影 }, levelText: { fontSize: 20, fontWeight: 'bold', color: 'white', }, }); export default LevelNode;
关卡连线组件示例
import React from 'react'; import { View, StyleSheet } from 'react-native'; const LevelConnector = ({ isCompleted }) => { return ( <View style={[ styles.connector, isCompleted ? styles.completedConnector : styles.lockedConnector, ]} /> ); }; const styles = StyleSheet.create({ connector: { width: 2, height: 40, alignSelf: 'center', }, completedConnector: { backgroundColor: '#4CAF50', // 已通关用实线绿色 }, lockedConnector: { borderStyle: 'dashed', borderWidth: 2, borderColor: '#9E9E9E', // 未解锁用灰色虚线 backgroundColor: 'transparent', }, }); export default LevelConnector;
2. 地图容器与布局逻辑
用FlatList来实现滚动布局(性能比ScrollView好,适合大量关卡),纵向/横向排列都可以调整:
import React, { useState } from 'react'; import { View, FlatList, StyleSheet, Alert } from 'react-native'; import LevelNode from './LevelNode'; import LevelConnector from './LevelConnector'; const LevelMap = () => { // 模拟状态:已通关关卡、当前关卡 const [completedLevels, setCompletedLevels] = useState([1, 2, 3]); const [currentLevel, setCurrentLevel] = useState(4); // 生成20个关卡示例 const levels = Array.from({ length: 20 }, (_, i) => i + 1); // 关卡点击逻辑 const handleLevelPress = (level) => { if (level === currentLevel || completedLevels.includes(level)) { console.log(`跳转至关卡 ${level}`); // 这里替换成你的关卡跳转逻辑 } else { Alert.alert('提示', '请先完成前面的关卡!'); } }; // 渲染每个关卡项(节点+连线) const renderItem = ({ item, index }) => { const isCompleted = completedLevels.includes(item); const isCurrent = item === currentLevel; const isLastItem = index === levels.length - 1; return ( <View style={styles.itemContainer}> <LevelNode level={item} isCompleted={isCompleted} isCurrent={isCurrent} onPress={() => handleLevelPress(item)} /> {/* 最后一个关卡不显示连线 */} {!isLastItem && ( <LevelConnector isCompleted={completedLevels.includes(item) && item + 1 <= currentLevel} /> )} </View> ); }; return ( <View style={styles.container}> <FlatList data={levels} renderItem={renderItem} keyExtractor={(item) => item.toString()} vertical // 改成horizontal={true}就是横向布局 contentContainerStyle={styles.listContent} showsVerticalScrollIndicator={false} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, paddingVertical: 20, backgroundColor: '#f5f5f5', }, listContent: { alignItems: 'center', }, itemContainer: { alignItems: 'center', }, }); export default LevelMap;
3. 交互状态管理
上面的示例用了本地状态模拟,实际项目中你可以:
- 把关卡状态存在
AsyncStorage或后端接口,确保重启APP后数据不丢失 - 通关后更新
completedLevels和currentLevel状态,自动刷新UI
4. 进阶优化建议
如果要做更接近糖果传奇的复杂效果,可以试试这些技巧:
- 自定义弯曲路径:如果关卡不是直线排列,用
react-native-svg绘制贝塞尔曲线连接节点,实现弯曲的路径效果 - 动画增强:用
AnimatedAPI给关卡点击、通关连线添加动画(比如节点缩放、连线渐显) - 特殊关卡标记:给BOSS关卡添加特殊图标(比如皇冠),在LevelNode组件里根据关卡类型渲染不同内容
- 屏幕适配:用
Dimensions动态调整节点大小和间距,确保在不同设备上显示比例一致
这些代码可以作为基础框架,你可以根据需求调整样式和细节,比如加入关卡星级、解锁动画之类的~
内容的提问来源于stack exchange,提问作者siddhardha
相关产品推荐
相关产品推荐

