-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathindex.tsx
109 lines (101 loc) · 3.45 KB
/
index.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import { Global, Interpolation, Theme } from '@emotion/react';
import React, { useCallback, useEffect, useState } from 'react';
import { ContextValue, getContextValue } from '../context';
import { useWindowResize } from '../Effect/useWindowResize';
import round from 'lodash/round';
import { useViewport } from '../Effect/useViewport';
export interface ContainerProps {
// 用户自定义的全局样式
globalStyle?: Interpolation<Theme>;
// 容器包裹的子元素
children?: React.ReactNode;
// 设计尺寸
designWidth?: number;
}
/**
* 自适应容器
* @param props
*/
export function Container(props: ContainerProps) {
// 来自全局的环境变量
const { minDocWidth, maxDocWidth } = getContextValue() as ContextValue;
// 获取环境变量
const { designWidth = 750, globalStyle, children } = props;
// 获取期待的根字体尺寸,采用rem布局
const expectFontSize = useCallback(() => {
const winWidth = window.innerWidth;
let expectFontSize: number;
if (winWidth >= maxDocWidth) {
expectFontSize = (maxDocWidth * 100) / designWidth;
} else if (winWidth <= minDocWidth) {
expectFontSize = (minDocWidth * 100) / designWidth;
} else {
expectFontSize = (winWidth * 100) / designWidth;
}
return expectFontSize;
}, [designWidth, minDocWidth, maxDocWidth]);
// 基准字体尺寸
const [baseFontSize, setBaseFontSize] = useState<number>(expectFontSize());
// 页面大小变化时,基准字体同步变化
useWindowResize(() => setBaseFontSize(() => expectFontSize()));
// 字体缩放逻辑
const scaleFont = useCallback<() => void>(() => {
let computeSize = parseFloat(
window.getComputedStyle(document.documentElement).fontSize
);
if (typeof computeSize === 'number' && computeSize !== baseFontSize) {
setBaseFontSize(round(baseFontSize ** 2 / computeSize, 1));
}
}, [baseFontSize]);
// 字体更新时,同步更新缩放逻辑
useEffect(scaleFont, [scaleFont]);
// 设置meta, 确保viewport的合法逻辑
useViewport();
// 一些页面的初始化逻辑
useEffect(() => {
// 激活iOS上的:active
const activable = () => {};
document.body.addEventListener('touchstart', activable);
return () => {
document.body.removeEventListener('touchstart', activable);
};
}, []);
return (
<React.Fragment>
<Global
styles={[
{
'*': {
boxSizing: 'border-box',
},
html: {
WebkitTapHighlightColor: 'transparent',
WebkitOverflowScrolling: 'touch',
WebkitTextSizeAdjust: '100%',
fontSize: `${baseFontSize}px`,
touchAction: 'manipulation',
},
body: {
fontSize: '16px',
margin: '0 auto',
maxWidth: `${maxDocWidth}px`,
minWidth: `${minDocWidth}px`,
},
[`@media (min-width: ${maxDocWidth}px)`]: {
html: {
fontSize: `${(100 * maxDocWidth) / designWidth}px`,
},
},
[`@media (max-width: ${minDocWidth}px)`]: {
html: {
fontSize: `${(100 * minDocWidth) / designWidth}px`,
},
},
},
globalStyle,
]}
/>
{children}
</React.Fragment>
);
}