全屏组件 FullScreenContainer
目录构造
index.vue
<template>
<div id="sp-full-screen-container" :ref="ref">
<div id="sp-full-screen-container-content">
<template v-if="ready">
<slot></slot>
</template>
</div>
</div>
</template>
<script>
import autoResize from "./mixin/autoResize.js";
export default {
name: "FullScreenContainer",
mixins: [autoResize],
props: {
// 设计稿画布大小(单位:px)canvasWidth: {
type: Number,
default: 0,
},
canvasHeight: {
type: Number,
default: 0,
},
},
data() {
return {
ref: "sp-full-screen-container",
ready: false,
scale: 1.0,
};
},
methods: {afterAutoResizeMixinInit() {const { initConfig, setContainerScale} = this;
initConfig();
setContainerScale();
this.ready = true;
},
initConfig() {const { dom, canvasWidth, canvasHeight} = this;
// debugger;
if (canvasWidth > 0 && canvasHeight > 0) {dom.style.cssText = `width: ${canvasWidth}px; height: ${canvasHeight}px;`;
}
},
setContainerScale() {const { width, height, dom} = this;
const {innerWidth, innerHeight} = window;
let top = 0;
let left = 0;
let scale = 0;
// 设置缩放率并居中
if (innerWidth / innerHeight > width / height) {
// 高低居中
scale = innerHeight / height;
left = (innerWidth - scale * 1920) / 2;
} else {
// 左右居中
scale = innerWidth / width;
// top = 0;
}
// 防止死循环
if (this.scale == scale) {dom.style.left = `${left}px`;
dom.style.top = `${top}px`;
dom.style.transform = `scale(${scale})`;
return;
}
this.scale = scale;
if (width == 0 || height == 0) {dom.style.left = `${left}px`;
dom.style.top = `${top}px`;
dom.style.transform = `scale(${scale})`;
} else {
// 升高 DOM 操作次数
dom.style.cssText = `width: ${width}px; height: ${height}px; left: ${left}px; top: ${top}px; transform: scale(${scale});`;
}
},
onResize() {const { setContainerScale} = this;
setContainerScale();},
},
};
</script>
<style lang="less">
#sp-full-screen-container {
position: fixed;
top: 0px;
left: 0px;
overflow: visible;
-webkit-transform-origin: left top;
transform-origin: left top;
z-index: 999;
display: flex;
justify-content: center;
align-items: center;
}
</style>
autoResize.js
import {debounce, observerDomResize} from "../util/index";
export default {data() {
return {
dom: "",
width: 0,
height: 0,
debounceInitWHFun: "",
domObserver: "",
};
},
methods: {async autoResizeMixinInit() {
const {
initWH,
getDebounceInitWHFun,
bindDomResizeCallback,
afterAutoResizeMixinInit,
} = this;
await initWH(false);
getDebounceInitWHFun();
bindDomResizeCallback();
if (typeof afterAutoResizeMixinInit === "function")
afterAutoResizeMixinInit();},
initWH(resize = true) {const { $nextTick, $refs, ref, onResize} = this;
return new Promise((resolve) => {$nextTick(() => {const dom = (this.dom = $refs[ref]);
this.width = dom.clientWidth;
this.height = dom.clientHeight;
if (typeof onResize === "function" && resize) onResize();
resolve();});
});
},
getDebounceInitWHFun() {const { initWH} = this;
this.debounceInitWHFun = debounce(100, initWH);
},
bindDomResizeCallback() {const { dom, debounceInitWHFun} = this;
this.domObserver = observerDomResize(dom, debounceInitWHFun);
window.addEventListener("resize", debounceInitWHFun);
},
unbindDomResizeCallback() {let { domObserver, debounceInitWHFun} = this;
domObserver.disconnect();
domObserver.takeRecords();
domObserver = null; // NOSONAR
window.removeEventListener("resize", debounceInitWHFun);
},
},
mounted() {const { autoResizeMixinInit} = this;
autoResizeMixinInit();},
onBeforeUnMount() {const { unbindDomResizeCallback} = this;
unbindDomResizeCallback();},
};
util/index.js
export function randomExtend(minNum, maxNum) {if (arguments.length === 1) {return parseInt(Math.random() * minNum + 1, 10);
} else {return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
}
}
export function debounce(delay, callback) {
let lastTime;
return function () {clearTimeout(lastTime);
const [that, args] = [this, arguments];
lastTime = setTimeout(() => {callback.apply(that, args);
}, delay);
};
}
export function observerDomResize(dom, callback) {
const MutationObserver =
window.MutationObserver ||
window.WebKitMutationObserver ||
window.MozMutationObserver;
const observer = new MutationObserver(callback);
observer.observe(dom, {
attributes: true,
attributeFilter: ["style"],
attributeOldValue: true,
});
return observer;
}
export function getPointDistance(pointOne, pointTwo) {const minusX = Math.abs(pointOne[0] - pointTwo[0]);
const minusY = Math.abs(pointOne[1] - pointTwo[1]);
return Math.sqrt(minusX * minusX + minusY * minusY);
}