Adapter.ts 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. import { _decorator, Component, UITransform, size, Size, screen, view, v4 } from 'cc';
  2. import { EDITOR, JSB } from 'cc/env';
  3. const { ccclass, property } = _decorator;
  4. /**
  5. * @description 该适配方案参考 https://forum.cocos.org/t/cocos-creator/74001
  6. */
  7. /**
  8. * 屏幕分辨率下 的像素值
  9. */
  10. interface SafeArea {
  11. /**
  12. * 屏幕分辨率下:画布(屏幕)宽度
  13. */
  14. width: number;
  15. /**
  16. * 屏幕分辨率下:画布(屏幕)高度
  17. */
  18. height: number;
  19. /**@description 屏幕分辨率下:安全区域大小(像素) */
  20. safe: Size;
  21. /**@description 「设计分辨率」 非安全区域的大小(像素)即刘海单边的大小 */
  22. outside: Size;
  23. /**
  24. * 「设计分辨率」像素值转换到 「屏幕分辨率」 下的像素比
  25. *
  26. * e.g.
  27. *
  28. * * screenPx = designPx * pixelRatio
  29. * * designPx = screenPx / pixelRatio
  30. */
  31. designPxToScreenPxRatio: number;
  32. }
  33. /**@description 设备方向 */
  34. enum DeviceDirection {
  35. /**@description 未知*/
  36. Unknown,
  37. /**@description 横屏(即摄像头向左) */
  38. LandscapeLeft,
  39. /**@description 横屏(即摄像头向右) */
  40. LandscapeRight,
  41. /**@description 竖屏(即摄像头向上) */
  42. Portrait,
  43. /**@description 竖屏(即摄像头向下) */
  44. UpsideDown,
  45. }
  46. let SAFE_SIZE = size(0, 0);
  47. let OUTSIDE_SIZE = size(0, 0);
  48. export class Adapter extends Component {
  49. static direction = DeviceDirection;
  50. protected set width(value: number) {
  51. let trans = this.getComponent(UITransform);
  52. if (!trans) {
  53. return;
  54. }
  55. trans.width = value;
  56. }
  57. protected get width() {
  58. let trans = this.getComponent(UITransform);
  59. if (!trans) {
  60. return 0;
  61. }
  62. return trans.width;
  63. }
  64. protected set height(value: number) {
  65. let trans = this.getComponent(UITransform);
  66. if (!trans) {
  67. return;
  68. }
  69. trans.height = value;
  70. }
  71. protected get height() {
  72. let trans = this.getComponent(UITransform);
  73. if (!trans) {
  74. return 0;
  75. }
  76. return trans.height;
  77. }
  78. protected static get windowSize() {
  79. if (EDITOR) {
  80. return view.getDesignResolutionSize();
  81. }
  82. return screen.windowSize;
  83. }
  84. protected static get visibleSize() {
  85. return view.getVisibleSize();
  86. }
  87. protected _func: any = null;
  88. /**@description 适配完成回调 */
  89. onAdapterComplete: () => void = null!;
  90. protected doOnAdapterComplete() {
  91. if (this.onAdapterComplete) {
  92. this.onAdapterComplete();
  93. }
  94. }
  95. onLoad() {
  96. super.onLoad && super.onLoad();
  97. this.onChangeSize();
  98. }
  99. onEnable() {
  100. super.onEnable && super.onEnable();
  101. this.addEvents();
  102. }
  103. onDisable() {
  104. this.removeEvents();
  105. super.onDisable && super.onDisable();
  106. }
  107. onDestroy() {
  108. this.removeEvents();
  109. super.onDestroy && super.onDestroy();
  110. }
  111. protected addEvents() {
  112. if (this._func) {
  113. return;
  114. }
  115. this._func = this.onChangeSize.bind(this);
  116. window.addEventListener("resize", this._func);
  117. window.addEventListener("orientationchange", this._func);
  118. }
  119. protected removeEvents() {
  120. if (this._func) {
  121. window.removeEventListener("resize", this._func);
  122. window.removeEventListener("orientationchange", this._func);
  123. }
  124. this._func = null;
  125. }
  126. /**
  127. * @description 视图发生大小变化
  128. */
  129. protected onChangeSize() {
  130. this.doOnAdapterComplete();
  131. }
  132. /**@description 获取当前设备方向 */
  133. get direction() {
  134. let str = "未知"
  135. let result = DeviceDirection.Unknown;
  136. let orientation = window.orientation;
  137. if (JSB) {
  138. orientation = jsb.device.getDeviceOrientation();
  139. }
  140. if (orientation != undefined || orientation != null) {
  141. if (orientation == 90) {
  142. str = `横屏向左`
  143. result = DeviceDirection.LandscapeLeft;
  144. } else if (orientation == -90) {
  145. str = `横屏向右`
  146. result = DeviceDirection.LandscapeRight;
  147. } else if (orientation == 0) {
  148. str = "竖屏向上"
  149. result = DeviceDirection.Portrait;
  150. } else if (orientation == 180) {
  151. str = "竖屏向下"
  152. result = DeviceDirection.UpsideDown;
  153. }
  154. }
  155. // console.log(`当前设备方向:${str}`)
  156. return result;
  157. }
  158. static get safeAreaEdge() {
  159. if (JSB) {
  160. return jsb.device.getSafeAreaEdge();
  161. } else {
  162. return v4(0, 0, 0, 0);
  163. }
  164. }
  165. private static _safeArea: SafeArea = null!;
  166. static set safeArea(value: SafeArea) {
  167. this._safeArea = value as any;
  168. }
  169. static screenPxToDesignPx(screenPx: number) {
  170. return screenPx / this.safeArea.designPxToScreenPxRatio;
  171. }
  172. static designPxToScreenPx(designPx: number) {
  173. return designPx * this.safeArea.designPxToScreenPxRatio;
  174. }
  175. /**
  176. * 基于屏幕尺寸的安全区域
  177. *
  178. * 可以通过 screenPxToDesignPx 转换为基于设计画布尺寸的像素大小
  179. */
  180. static get safeArea() {
  181. if (this._safeArea == null || this._safeArea == undefined) {
  182. // 初始屏幕宽高像素
  183. let screenWidth = Adapter.windowSize.width;
  184. let screenHeight = Adapter.windowSize.height;
  185. // 「设计分辨率」像素值转换到 「屏幕分辨率」 下的像素比
  186. let designWidth = Adapter.visibleSize.width;
  187. let designHeight = Adapter.visibleSize.height;
  188. let designPxToScreenPxRatio = Math.min(screenWidth / designWidth, screenHeight / designHeight);
  189. OUTSIDE_SIZE.width = 0
  190. OUTSIDE_SIZE.height = 0
  191. SAFE_SIZE.width = screenWidth - OUTSIDE_SIZE.width;
  192. SAFE_SIZE.height = screenHeight - OUTSIDE_SIZE.height
  193. if (JSB) {
  194. OUTSIDE_SIZE.width = (this.safeAreaEdge.y + this.safeAreaEdge.w)
  195. OUTSIDE_SIZE.height = (this.safeAreaEdge.x + this.safeAreaEdge.z)
  196. SAFE_SIZE.width = screenWidth - OUTSIDE_SIZE.width;
  197. SAFE_SIZE.height = screenHeight - OUTSIDE_SIZE.height
  198. OUTSIDE_SIZE.width = OUTSIDE_SIZE.width / 2
  199. OUTSIDE_SIZE.height = OUTSIDE_SIZE.height / 2
  200. }
  201. this._safeArea = {
  202. width: screenWidth,
  203. height: screenHeight,
  204. outside: OUTSIDE_SIZE,
  205. safe: SAFE_SIZE,
  206. designPxToScreenPxRatio: designPxToScreenPxRatio,
  207. };
  208. }
  209. return this._safeArea;
  210. }
  211. private _isFullScreenAdaption = true;
  212. /** 是否全屏*/
  213. public get isFullScreenAdaption() {
  214. return this._isFullScreenAdaption;
  215. }
  216. public set isFullScreenAdaption(value) {
  217. this._isFullScreenAdaption = value;
  218. }
  219. /**
  220. * 获取是否为16:9的常规屏幕尺寸
  221. */
  222. static isNormalScreen(): boolean {
  223. return screen.windowSize.height /screen.windowSize.width < 1335 / 750;
  224. }
  225. }