如果有更好的書寫方式,歡迎提出
廢話不多說,直接上代碼!!
由于不同手機(jī)機(jī)型分辨率不同,先寫個(gè)適配比例不同機(jī)型的方法
import { Dimensions, Platform } from 'react-native';
const { height, width } = Dimensions.get('window');
const isWeb = Platform.OS === 'web';
const baseHeight = 667;
const baseWidth = 375;
const HRatio = width / baseWidth;
const VRatio = height / baseHeight;
// 根據(jù)手機(jī)屏幕的寬度進(jìn)行比例適配
export const convertX = (width: number) => (isWeb ? width : width * HRatio);
// 根據(jù)手機(jī)屏幕的高度進(jìn)行比例適配
export const convertY = (height: number) => (isWeb ? height : height * VRatio);
思路:
1、將8按下圖劃分

image.png
utils.js:
export const numPosition = (val, width, border) => {
const offset = border / 2;
const all = width + border * 2 * 2;
const obj = {
0: { top: offset, left: 0 },
1: { top: 0, left: offset },
2: { top: offset, left: 2 * offset + border * 2 + width },
3: { top: 2 * offset + border * 2 + width, left: offset },
4: { top: all + offset - border, left: 0 },
5: { top: (2 * offset + border * 2 + width) * 2, left: offset },
6: { top: all + offset - border, left: 2 * offset + border * 2 + width },
};
return obj[val];
};
export const numToIndex = val => {
const obj = {
0: [0, 1, 2, 4, 5, 6],
1: [2, 6],
2: [1, 2, 3, 4, 5],
3: [1, 2, 3, 5, 6],
4: [0, 2, 3, 6],
5: [0, 1, 3, 5, 6],
6: [0, 1, 3, 4, 5, 6],
7: [1, 2, 6],
8: [0, 1, 2, 3, 4, 5, 6],
9: [0, 1, 2, 3, 5, 6],
10: [3],
p: [0, 1, 2, 3, 4],
c: [0, 1, 4, 5],
l: [0, 4, 5],
f: [0, 1, 3, 4],
h: [0, 2, 3, 4, 6],
};
return obj[val];
};
export const isOdd = num => {
return num % 2 !== 0;
};
實(shí)現(xiàn)代碼:
import React, { useState } from 'react';
import { View, StyleSheet, StyleProp, ViewStyle } from 'react-native';
import { convertX, isOdd, numPosition, numToIndex } from '@utils';
interface NumProps {
num: number; // 顯示的文案
numWidth: number; // numWidth={cx(10)}
numBorder: number; // 數(shù)字一豎杠的邊框?qū)挾? style: StyleProp<ViewStyle>; // 最外層的樣式設(shè)置
color: string; // 數(shù)字顏色設(shè)置
}
const NumView = (props: NumProps) => {
const { num = 8, numWidth = convertX(20), numBorder = convertX(4), style} = props;
const [numTxt, setNumTxt] = useState(numToIndex(num));
return (
<View
style={[
styles.wrap,
{ width: numWidth + numBorder * 5, height: numWidth * 2 + numBorder * 8 },
style,
]}
>
{numTxt.map(item => (
<View
key={item}
style={[
styles.numAbs,
{
flexDirection: !isOdd(item) ? 'column' : 'row',
},
numPosition(item, numWidth, numBorder),
]}
>
<View
style={[
styles.commonAngle,
{ borderWidth: numBorder },
!isOdd(item) ? styles.bottomChoice : styles.leftChoice,
]}
/>
<View
style={
!isOdd(item)
? [styles.columnLine, { width: numBorder * 2, height: numWidth }]
: [styles.rowLine, { width: numWidth, height: numBorder * 2 }]
}
/>
<View
style={[
styles.commonAngle,
{ borderWidth: numBorder },
!isOdd(item) ? styles.topChoice : styles.rightChoice,
]}
/>
</View>
))}
</View>
);
};
const styles = StyleSheet.create({
wrap: {
position: 'relative',
backgroundColor: 'red'
},
numAbs: {
position: 'absolute',
},
rowLine: {
backgroundColor: '#fff',
},
columnLine: {
backgroundColor: '#fff',
},
commonAngle: {
width: 0,
height: 0,
borderStyle: 'solid',
},
leftChoice: {
borderTopColor: 'transparent',
borderLeftColor: 'transparent',
borderBottomColor: 'transparent',
borderRightColor: '#fff',
},
rightChoice: {
borderTopColor: 'transparent',
borderLeftColor: '#fff',
borderBottomColor: 'transparent',
borderRightColor: 'transparent',
},
topChoice: {
borderTopColor: '#fff',
borderLeftColor: 'transparent',
borderBottomColor: 'transparent',
borderRightColor: 'transparent',
},
bottomChoice: {
borderTopColor: 'transparent',
borderLeftColor: 'transparent',
borderBottomColor: '#fff',
borderRightColor: 'transparent',
},
});
export default NumView;