1
0

Adaptive.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. <template>
  2. <div id="adaptive-container" :ref="refName">
  3. <template v-if="ready">
  4. <slot></slot>
  5. </template>
  6. </div>
  7. </template>
  8. <script>
  9. import { ref, onMounted, onUnmounted, nextTick, defineComponent } from 'vue';
  10. import { debounce, setRem } from '/@/utils/index';
  11. import { useAppStore } from '/@/store/modules/app';
  12. import { getActions } from '/@/qiankun/state';
  13. export default defineComponent({
  14. name: 'AdaptiveContainer',
  15. props: {
  16. options: Object,
  17. },
  18. setup(ctx) {
  19. const appStore = useAppStore();
  20. const refName = 'AdaptiveContainer'; //AdaptiveContainer
  21. // 屏幕宽度
  22. const width = ref(0);
  23. // 屏幕高度
  24. const height = ref(0);
  25. // 原始屏幕宽度
  26. const originalWidth = ref(0);
  27. // 原始屏幕高度
  28. const originalHeight = ref(0);
  29. // 控制显示
  30. const ready = ref(false);
  31. /*
  32. * dom:well-container的dom
  33. * observer: window.MutationObserver(Bom实例)监听dom改变
  34. */
  35. let dom, observer;
  36. const actions = getActions();
  37. //设置初始值
  38. const initSize = () => {
  39. return new Promise((resolve) => {
  40. nextTick(() => {
  41. dom = document.getElementById('adaptive-container');
  42. // 获取大屏的传入尺寸
  43. if (ctx.options && ctx.options.width && ctx.options.height) {
  44. //传入宽高
  45. width.value = ctx.options.width;
  46. height.value = ctx.options.height;
  47. } else {
  48. //可见宽高
  49. width.value = dom.clientWidth;
  50. height.value = dom.clientHeight;
  51. }
  52. // 获取画布尺寸
  53. if (!originalWidth.value || !originalHeight.value) {
  54. //屏幕分辨率宽高
  55. originalWidth.value = window.screen.width;
  56. originalHeight.value = window.screen.height;
  57. }
  58. resolve();
  59. });
  60. });
  61. };
  62. const updateSize = () => {
  63. if (width.value && height.value) {
  64. dom.style.width = `${width.value}px`;
  65. dom.style.height = `${height.value}px`;
  66. } else {
  67. dom.style.width = `${originalWidth.value}px`;
  68. dom.style.height = `${originalHeight.value}px`;
  69. }
  70. };
  71. const updateScale = () => {
  72. // debugger
  73. // 获取真实的视口尺寸
  74. const currentWidth = document.body.clientWidth;
  75. const currentHeight = document.body.clientHeight;
  76. // 获取大屏最终的宽高
  77. const realWidth = width.value || originalWidth.value;
  78. const realHeight = height.value || originalHeight.value;
  79. // console.log(currentWidth, currentHeight)
  80. // 缩放比例 = 分辨率宽高 / 传入宽高(可视宽高)
  81. const widthScale = currentWidth / realWidth;
  82. const heightScale = currentHeight / realHeight;
  83. appStore.setWidthScale(widthScale);
  84. appStore.setHeightScale(heightScale);
  85. actions.setGlobalState({ widthScale, heightScale });
  86. //如果dom存在,就按照比例缩放
  87. dom && (dom.style.transform = `scale(${widthScale}, ${heightScale})`);
  88. };
  89. const cssSize = () => {
  90. const currentWidth = document.body.clientWidth;
  91. const realWidth = width.value || originalWidth.value;
  92. const whdef = 100 / 1920; // 表示1920的设计图,使用100PX的默认值
  93. const wW = currentWidth / realWidth; // 当前窗口的宽度
  94. const rem = wW * whdef; // 以默认比例值乘以当前窗口宽度,得到该宽度下的相应FONT-SIZE值
  95. document.documentElement.style.fontSize = rem + 'px';
  96. window.addEventListener('resize', function () {
  97. const whdef = 100 / 1920; // 表示1920的设计图,使用100PX的默认值
  98. const wW = window.innerWidth; // 当前窗口的宽度
  99. const rem = wW * whdef; // 以默认比例值乘以当前窗口宽度,得到该宽度下的相应FONT-SIZE值
  100. document.documentElement.style.fontSize = rem + 'px';
  101. });
  102. };
  103. //重置缩放比例
  104. const onResize = async () => {
  105. // debugger;
  106. await initSize();
  107. updateScale();
  108. setRem();
  109. cssSize();
  110. };
  111. const initMutationObserver = () => {
  112. //监听元素属性变化
  113. const MutationObserver = window.MutationObserver;
  114. //如果变化,就用onResize重置屏幕所缩放比例
  115. observer = new MutationObserver(onResize);
  116. observer.observe(dom, {
  117. attributes: true,
  118. attributeFilter: ['style'],
  119. attributeOldValue: true,
  120. });
  121. };
  122. //移除监听属性
  123. const removeMutationObserver = () => {
  124. if (observer) {
  125. observer.disconnect();
  126. observer.takeRecords();
  127. observer = null;
  128. }
  129. };
  130. //
  131. onMounted(async () => {
  132. ready.value = false;
  133. await initSize();
  134. updateSize();
  135. updateScale();
  136. setRem();
  137. cssSize();
  138. window.addEventListener('resize', debounce(100, onResize));
  139. initMutationObserver();
  140. ready.value = true;
  141. });
  142. onUnmounted(() => {
  143. window.removeEventListener('resize', onResize);
  144. removeMutationObserver();
  145. });
  146. return {
  147. refName,
  148. ready,
  149. };
  150. },
  151. });
  152. </script>
  153. <style lang="less" scoped>
  154. #adaptive-container {
  155. position: relative;
  156. top: 0;
  157. left: 0;
  158. overflow: hidden;
  159. transform-origin: left top;
  160. z-index: 0;
  161. }
  162. </style>