Skip to content

Commit

Permalink
feat(core): 完善屏幕大小自动适配
Browse files Browse the repository at this point in the history
  • Loading branch information
roymondchen committed Aug 1, 2024
1 parent 9f80881 commit 59f0527
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 25 deletions.
27 changes: 9 additions & 18 deletions packages/core/src/App.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@ import { DATA_SOURCE_FIELDS_CHANGE_EVENT_PREFIX } from '@tmagic/utils';

import Env from './Env';
import { bindCommonEventListener, isCommonMethod, triggerCommonMethod } from './events';
import Flexible from './Flexible';
import Node from './Node';
import Page from './Page';
import { calcFontsize, transformStyle as defaultTransformStyle } from './utils';
import { transformStyle as defaultTransformStyle } from './utils';

interface AppOptionsConfig {
ua?: string;
Expand Down Expand Up @@ -73,14 +74,15 @@ class App extends EventEmitter implements AppCore {
public useMock = false;
public platform = 'mobile';
public jsEngine: JsEngine = 'browser';
public designWidth = 375;
public request?: RequestFunction;

public components = new Map();

public eventQueueMap: Record<string, EventCache[]> = {};
public transformStyle: (style: Record<string, any>) => Record<string, any>;

public flexible?: Flexible;

private eventList = new Map<(fromCpt: Node, ...args: any[]) => void, string>();
private dataSourceEventList = new Map<string, Map<string, (...args: any[]) => void>>();

Expand All @@ -97,8 +99,8 @@ class App extends EventEmitter implements AppCore {
this.useMock = options.useMock;
}

if (typeof options.designWidth !== 'undefined') {
this.setDesignWidth(options.designWidth);
if (this.jsEngine === 'browser') {
this.flexible = new Flexible({ designWidth: options.designWidth });
}

this.transformStyle =
Expand All @@ -120,13 +122,7 @@ class App extends EventEmitter implements AppCore {
}

public setDesignWidth(width: number) {
this.designWidth = width;
// 根据屏幕大小计算出跟节点的font-size,用于rem样式的适配
if (this.jsEngine === 'browser') {
this.calcFontsize();
globalThis.removeEventListener('resize', this.calcFontsize);
globalThis.addEventListener('resize', this.calcFontsize);
}
this.flexible?.setDesignWidth(width);
}

/**
Expand Down Expand Up @@ -331,9 +327,8 @@ class App extends EventEmitter implements AppCore {
this.removeAllListeners();
this.page = undefined;

if (this.jsEngine === 'browser') {
globalThis.removeEventListener('resize', this.calcFontsize);
}
this.flexible?.destroy();
this.flexible = undefined;
}

private bindDataSourceEvents() {
Expand Down Expand Up @@ -418,10 +413,6 @@ class App extends EventEmitter implements AppCore {
this.eventQueueMap[event.eventConfig.to] = [event];
}
}

private calcFontsize() {
calcFontsize(this.designWidth);
}
}

export default App;
5 changes: 4 additions & 1 deletion packages/core/src/Env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class Env {
isMqq = false;
isWechat = false;
isWeb = false;
isOpenHarmony = false;

constructor(ua = globalThis.navigator.userAgent, options: Record<string, boolean | string> = {}) {
this.isIphone = ua.indexOf('iPhone') >= 0;
Expand All @@ -47,7 +48,9 @@ class Env {

this.isWechat = ua.indexOf('MicroMessenger') >= 0 && ua.indexOf('wxwork') < 0;

this.isWeb = !this.isIos && !this.isAndroid && !/(WebOS|BlackBerry)/.test(ua);
this.isOpenHarmony = ua.includes('OpenHarmony');

this.isWeb = !this.isIos && !this.isAndroid && !this.isOpenHarmony && !/(WebOS|BlackBerry)/.test(ua);

Object.entries(options).forEach(([key, value]) => {
(this as any)[key] = value;
Expand Down
72 changes: 72 additions & 0 deletions packages/core/src/Flexible.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
export default class Flexible {
public designWidth = 375;
private tid: NodeJS.Timeout | undefined;

constructor(options?: { designWidth?: number }) {
if (globalThis.document.readyState === 'complete') {
this.setBodyFontSize();
} else {
globalThis.document.addEventListener('DOMContentLoaded', this.setBodyFontSize, false);
}

globalThis.addEventListener('resize', this.resizeHandler, false);
globalThis.addEventListener('pageshow', this.pageshowHandler, false);

if (typeof options?.designWidth !== 'undefined') {
this.setDesignWidth(options.designWidth);
}
}

public destroy() {
globalThis.document.removeEventListener('DOMContentLoaded', this.setBodyFontSize, false);
globalThis.removeEventListener('resize', this.resizeHandler, false);
globalThis.removeEventListener('pageshow', this.pageshowHandler, false);
}

public setDesignWidth(width: number) {
this.designWidth = width;
this.refreshRem();
}

public setBodyFontSize() {
globalThis.document.body.style.fontSize = '.12rem';
}

public refreshRem() {
const { width } = document.documentElement.getBoundingClientRect();
const fontSize = width / (this.designWidth / 100);
globalThis.document.documentElement.style.fontSize = `${fontSize}px`;
globalThis.document.documentElement.style.fontSize = `${this.correctRem(fontSize)}px`;
}

/**
* 纠正由于文字缩放导致的字体大小计算不正确问题
* @param {number} fontSize
* @returns {number}
*/
public correctRem(fontSize: number) {
const { document } = globalThis;
const d = document.createElement('div');
d.style.cssText = 'width:1rem;height:0;overflow:hidden;position:absolute;z-index:-1;visibility:hidden;';
document.documentElement.appendChild(d);
const dw = d.offsetWidth;
document.documentElement.removeChild(d);
if (Math.abs(dw - fontSize) > 1) {
return fontSize ** 2 / dw;
}
return fontSize;
}

private resizeHandler = () => {
clearTimeout(this.tid);
this.tid = setTimeout(() => {
this.refreshRem();
}, 300);
};

private pageshowHandler = (e: PageTransitionEvent) => {
if (e.persisted) {
this.resizeHandler();
}
};
}
6 changes: 0 additions & 6 deletions packages/core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,3 @@ export const transformStyle = (style: Record<string, any> | string, jsEngine: Js

return results;
};

export const calcFontsize = (designWidth: number) => {
const { width } = document.documentElement.getBoundingClientRect();
const fontSize = width / (designWidth / 100);
document.documentElement.style.fontSize = `${fontSize}px`;
};

0 comments on commit 59f0527

Please sign in to comment.