alchaincyf--huashu-design
176 行
4.4 KiB
React
176 行
4.4 KiB
React
/**
|
|
* AndroidFrame — Android设备边框(参考Pixel 8系列)
|
|
*
|
|
* 含:punch-hole相机 + 状态栏 + 导航栏 + 圆角
|
|
*
|
|
* 用法:
|
|
* <AndroidFrame time="9:41" battery={85}>
|
|
* <YourAppContent />
|
|
* </AndroidFrame>
|
|
*/
|
|
|
|
const androidFrameStyles = {
|
|
wrapper: {
|
|
display: 'inline-block',
|
|
padding: 10,
|
|
background: '#1a1a1a',
|
|
borderRadius: 44,
|
|
boxShadow: '0 0 0 2px #2a2a2a, 0 20px 60px rgba(0,0,0,0.3)',
|
|
position: 'relative',
|
|
},
|
|
screen: {
|
|
position: 'relative',
|
|
borderRadius: 36,
|
|
overflow: 'hidden',
|
|
background: '#fff',
|
|
},
|
|
statusBar: {
|
|
position: 'absolute',
|
|
top: 0,
|
|
left: 0,
|
|
right: 0,
|
|
height: 32,
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'space-between',
|
|
padding: '0 24px',
|
|
fontSize: 14,
|
|
fontWeight: 500,
|
|
fontFamily: 'Roboto, -apple-system, sans-serif',
|
|
zIndex: 20,
|
|
pointerEvents: 'none',
|
|
},
|
|
punchHole: {
|
|
position: 'absolute',
|
|
top: 10,
|
|
left: '50%',
|
|
transform: 'translateX(-50%)',
|
|
width: 14,
|
|
height: 14,
|
|
background: '#000',
|
|
borderRadius: '50%',
|
|
zIndex: 30,
|
|
},
|
|
statusIcons: {
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: 6,
|
|
},
|
|
batteryText: {
|
|
fontSize: 11,
|
|
fontWeight: 600,
|
|
marginLeft: 2,
|
|
},
|
|
content: {
|
|
position: 'absolute',
|
|
top: 32,
|
|
left: 0,
|
|
right: 0,
|
|
bottom: 24,
|
|
overflow: 'auto',
|
|
},
|
|
navBar: {
|
|
position: 'absolute',
|
|
bottom: 0,
|
|
left: 0,
|
|
right: 0,
|
|
height: 24,
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
gap: 60,
|
|
zIndex: 10,
|
|
},
|
|
navButton: {
|
|
width: 36,
|
|
height: 4,
|
|
background: 'rgba(0,0,0,0.3)',
|
|
borderRadius: 999,
|
|
},
|
|
};
|
|
|
|
function AndroidFrame({
|
|
children,
|
|
width = 412,
|
|
height = 892,
|
|
time = '9:41',
|
|
battery = 100,
|
|
darkMode = false,
|
|
navStyle = 'gesture',
|
|
}) {
|
|
const textColor = darkMode ? '#fff' : '#1a1a1a';
|
|
|
|
return (
|
|
<div style={androidFrameStyles.wrapper}>
|
|
<div style={{
|
|
...androidFrameStyles.screen,
|
|
width,
|
|
height,
|
|
background: darkMode ? '#000' : '#fff',
|
|
}}>
|
|
<div style={{ ...androidFrameStyles.statusBar, color: textColor }}>
|
|
<span>{time}</span>
|
|
<div style={androidFrameStyles.statusIcons}>
|
|
<svg width="14" height="10" viewBox="0 0 14 10" fill="currentColor">
|
|
<rect x="0" y="6" width="2" height="4" rx="0.5" />
|
|
<rect x="4" y="4" width="2" height="6" rx="0.5" />
|
|
<rect x="8" y="2" width="2" height="8" rx="0.5" />
|
|
<rect x="12" y="0" width="2" height="10" rx="0.5" />
|
|
</svg>
|
|
<svg width="14" height="10" viewBox="0 0 14 10" fill="none">
|
|
<path d="M7 9a1 1 0 100-2 1 1 0 000 2z" fill="currentColor" />
|
|
<path d="M3 6a5 5 0 018 0" stroke="currentColor" strokeWidth="1.2" />
|
|
<path d="M0.5 3.5a11 11 0 0113 0" stroke="currentColor" strokeWidth="1.2" opacity="0.6" />
|
|
</svg>
|
|
<div style={{
|
|
width: 22,
|
|
height: 10,
|
|
border: '1.5px solid currentColor',
|
|
borderRadius: 2,
|
|
padding: 1,
|
|
position: 'relative',
|
|
}}>
|
|
<div style={{
|
|
width: `${battery}%`,
|
|
height: '100%',
|
|
background: 'currentColor',
|
|
borderRadius: 1,
|
|
}} />
|
|
</div>
|
|
<span style={androidFrameStyles.batteryText}>{battery}%</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div style={androidFrameStyles.punchHole} />
|
|
|
|
<div style={androidFrameStyles.content}>
|
|
{children}
|
|
</div>
|
|
|
|
{navStyle === 'gesture' && (
|
|
<div style={androidFrameStyles.navBar}>
|
|
<div style={{
|
|
...androidFrameStyles.navButton,
|
|
width: 100,
|
|
height: 4,
|
|
background: darkMode ? 'rgba(255,255,255,0.5)' : 'rgba(0,0,0,0.4)',
|
|
}} />
|
|
</div>
|
|
)}
|
|
|
|
{navStyle === 'buttons' && (
|
|
<div style={androidFrameStyles.navBar}>
|
|
<span style={{ color: textColor, fontSize: 20 }}>◁</span>
|
|
<span style={{ color: textColor, fontSize: 16 }}>○</span>
|
|
<span style={{ color: textColor, fontSize: 16 }}>□</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (typeof window !== 'undefined') {
|
|
window.AndroidFrame = AndroidFrame;
|
|
}
|