react自动放缩组件
# react自动放缩组件
背景:公司有一个大屏展示的项目(1920*1080),该项目被多个产品以iframe的形式内嵌,有时候会出现布局混乱。 所以需要做一个外部的壳子,根据外部穿进来的宽度,等比放缩该大屏项目,所以做了该功能。
# 代码
{% raw %}
// index.tsx
import React, { useEffect } from 'react';
import './index.scss';
import { useImmer } from 'use-immer';
import { Props, ScaleBoxState } from './interface';
const ScaleBox = function (props: Props) {
const { width = 1920, height = 1080, children, monitorScaleChange, outsideWidth = 0, outsideHeight=0 } = props;
const [state, updateState] = useImmer<ScaleBoxState>({
scale: 1,
wrapWidth: null,
wrapHeight: null,
});
useEffect(() => {
init();
return () => {
window.onresize = null
}
}, []);
useEffect(() => {
setScale();
}, [window.innerWidth + window.innerHeight]);
const getScale = () => {
const currentWrapWidth = window.innerWidth - outsideWidth;
const currentWrapHeight = window.innerHeight - outsideHeight;
let ww = currentWrapWidth / width;
let wh = currentWrapHeight / height;
updateState((draft) => {
draft.wrapWidth = currentWrapWidth;
draft.wrapHeight = currentWrapHeight;
})
return Math.min(ww, wh);
}
const setScale = () => {
const scale = getScale();
monitorScaleChange(scale);
updateState((draft) => {
draft.scale = scale;
});
}
const debounce: Function = (fn: Function, delay: number = 500): Function => {
let timer: any
return function () {
let args = arguments;
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function () {
timer = null;
fn(args);
}, delay);
}
}
const init = () => {
if (state.wrapWidth === null && state.wrapHeight === null) {
window.onresize = debounce(setScale);
}
}
return (
<div className="scale-box-wrap">
<div className="scale-box" style={{width: `${width}px`, height: `${height}px`, transform: `scale(${state.scale}) translate(-50%, -50%)`}} >
{
children
}
</div>
</div>
);
};
export default ScaleBox;
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
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
{% endraw %}
// interface.ts
export interface Props {
width?: number;
height?: number;
wrapWidth?: number;
wrapHeight?: number;
children?: any;
monitorScaleChange?: Function;
outsideWidth?: number;
outsideHeight?: number;
}
export interface ScaleBoxState {
scale: number;
wrapWidth: number;
wrapHeight: number;
// tabDom: HTMLElement[];
// barWidth: number;
// barLeft: number;
// isClose: boolean;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// index.less
.scale-box-wrap {
background-color: #000000;
width: 100%;
height: 100%;
}
.scale-box {
display: flex;
flex-direction: column;
transform-origin: 0 0;
position: absolute;
left: 50%;
top: 50%;
transition: 0.3s;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
编辑 (opens new window)
上次更新: 2025/04/18, 01:42:12