-
Notifications
You must be signed in to change notification settings - Fork 0
/
Markup.ts
133 lines (97 loc) · 4.02 KB
/
Markup.ts
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import { WindowSize, IMarkup, MarkupConfig } from '../types/markup';
import { throttle } from '../utils/throttle';
const DEFAULT_HTML_FONT_SIZE = 10;
const MIN_HTML_FONT_SIZE = 5;
const DEFAULT_MOBILE_SIZE: WindowSize = {
width: 375,
height: 812,
};
const DEFAULT_DESKTOP_SIZE: WindowSize = {
width: 1280,
height: 820,
};
export default class Markup implements IMarkup {
/** Пересчитывать ли размер шрифта при ресайзе экрана или перевороте экрана моб. устройства */
private readonly _isFitOnResize: boolean;
/** Является ли девайс мобильным устройством */
private readonly _isMobile: boolean;
/** Размеры мобильного девайса, под который ориентированы макеты */
private readonly _mobileWindowSize: WindowSize;
/** Размеры десктопного девайса, под который ориентированы макеты */
private readonly _desktopWindowSize: WindowSize;
/** Размер шрифта html по умолчанию, то есть значение 1rem */
private readonly _htmlFontSize: number;
/** Минимальный размер шрифта html, чтобы содержимое страницы не было слишком мелким */
private readonly _minFontSize: number;
/** Максимальный размер шрифта html */
private readonly _maxFontSize: number | null;
/* Текущий размер шрифта тега html */
// @ts-ignore
private _currentHtmlFontSize: number;
constructor(config?: MarkupConfig) {
this._isFitOnResize = config?.isFitOnResize ?? false;
this._isMobile = config?.isMobile ?? true;
this._mobileWindowSize = config?.mobileWindowSize ?? DEFAULT_MOBILE_SIZE;
this._desktopWindowSize = config?.desktopWindowSize ?? DEFAULT_DESKTOP_SIZE;
this._htmlFontSize = config?.htmlFontSize ?? DEFAULT_HTML_FONT_SIZE;
this._minFontSize = config?.minFontSize ?? MIN_HTML_FONT_SIZE;
this._maxFontSize = config?.maxFontSize ?? null;
this.fit();
if (this._isFitOnResize) {
window.addEventListener('resize', this.throttledFit);
}
}
get throttledFit(): VoidFunction {
return throttle(this.fit.bind(this));
}
get currentHtmlFontSize(): number {
return this._currentHtmlFontSize;
}
set currentHtmlFontSize(value: number) {
if (this._maxFontSize !== null && value > this._maxFontSize) {
this._currentHtmlFontSize = this._maxFontSize;
return;
}
if (value < this._minFontSize) {
this._currentHtmlFontSize = this._minFontSize;
return;
}
this._currentHtmlFontSize = value;
}
fit(): void {
const currentWindowWidth = window.innerWidth;
const currentWindowHeight = window.innerHeight;
const { width: windowWidth, height: windowHeight } = this._isMobile
? this._mobileWindowSize
: this._desktopWindowSize;
let scaleX = currentWindowWidth / windowWidth;
let scaleY = currentWindowHeight / windowHeight;
if (scaleX * windowHeight > currentWindowHeight) {
scaleX = currentWindowHeight / windowHeight;
}
if (scaleY * windowWidth > currentWindowWidth) {
scaleY = currentWindowWidth / windowWidth;
}
let currentScale = Math.min(scaleX, scaleY);
if (currentWindowHeight > currentWindowWidth * 2) {
currentScale +=
0.1 *
(currentWindowHeight / (currentWindowWidth * 2 + currentWindowHeight));
}
const result = currentScale * this._htmlFontSize;
this.currentHtmlFontSize = this.round(result);
document.documentElement.style.fontSize = `${this._currentHtmlFontSize}px`;
}
round(value: number): number {
return Math.round(value * 2) / 2;
}
remToPx(rem: number): number {
return this.round(rem * this._currentHtmlFontSize);
}
pxToRem(px: number): number {
return px / this._currentHtmlFontSize;
}
destroy(): void {
window.removeEventListener('resize', this.throttledFit);
}
}