Newer
Older
safe_production_front / src / views / bigScreen / components / autoScalContainerBak.vue
dutingting on 27 Dec 4 KB gm部署版本
<template>
    <div class="auto-scal-container" ref="AutoScalContainerRef">
        <div ref="DomRef" class="auto-scal-container-inner">
            <slot></slot>
        </div>
    </div>
</template>

<script>
/**
 * 自动缩放容器
 * 使用transform进行缩放
 *  */
import {
    defineComponent,
    ref,
    getCurrentInstance,
    reactive,
    toRef,
    computed,
    onMounted,
    onActivated,
    watch,
    onBeforeUnmount,
} from 'vue';

export default defineComponent({
    props: {
        width: {
            type: Number,
            default: 1920,
        },
        height: {
            type: Number,
            default: 1080,
        },
        /** 内部容器的宽高比例 */
        ratio: {
            type: Number,
            default: 1920 / 1080,
        },
        /**
         * fit,原理同img的object-fit
         * contain : 被替换的内容将被缩放,以在填充元素的内容框时保持其宽高比。
         * cover : 被替换的内容在保持其宽高比的同时填充元素的整个内容框。如果对象的宽高比与内容框不相匹配,该对象将被剪裁以适应内容框。
         *  */
        fit: {
            type: String,
            default: 'contain',
        },
    },
    emits: ['onResizeScreen'],
    setup(props, { emit }) {
        const DomRef = ref(null); //组件实例
        const AutoScalContainerRef = ref(null); //组件实例
        const dataContainer = reactive({
            height: toRef(props, 'height'),
            width: toRef(props, 'width'),
            ratio: toRef(props, 'ratio'),
            fit: toRef(props, 'fit'),
        });
        /** 是否是文档上 */
        function isActive() {
            if (!DomRef.value) return false;
            return DomRef.value.getRootNode() === document;
        }
        /** 自动缩放 */
        function autoResizeScreen() {
            if (!AutoScalContainerRef.value) return;
            if (!DomRef.value) return;
            if (!isActive) return;
            let rect = AutoScalContainerRef.value.getBoundingClientRect();
            let clientWidth = rect.width;
            let clientHeight = rect.height;
            var width = dataContainer.width;
            var height = dataContainer.height;
            let left = 0;
            let top = 0;
            let scale = 0;
            /** 使用外部传入的比例或者传入的宽高计算比例 */
            let ratio = dataContainer.ratio || width / height;
            // 获取比例  可视化区域的宽高比与 屏幕的宽高比  来进行对应屏幕的缩放
            if (dataContainer.fit == 'contain') {
                if (clientWidth / clientHeight > ratio) {
                    scale = clientHeight / height;
                    top = 0;
                    left = (clientWidth - width * scale) / 2;
                } else {
                    scale = clientWidth / width;
                    left = 0;
                    top = (clientHeight - height * scale) / 2;
                }
            }
            if (dataContainer.fit == 'cover') {
                if (clientWidth / clientHeight > ratio) {
                    scale = clientWidth / width;
                } else {
                    scale = clientHeight / height;
                }
            }
            // 防止组件销毁后还执行设置状态s
            Object.assign(DomRef.value.style, {
                transform: `scale(${scale})`,
                left: `${left}px`,
                top: `${top}px`,
            });
            /** 向外部通知已经计算缩放 */
            emit('onResizeScreen');
        }
        /** 防抖 */
        let timer_1;
        function fnContainer() {
            clearTimeout(timer_1);
            // timer_1 = setTimeout(()=>{
            autoResizeScreen();
            // },16);
        }
        let timer = setInterval(() => {
            fnContainer();
        }, 300);
        onMounted(() => {
            autoResizeScreen();
        });
        window.addEventListener('resize', fnContainer);
        onBeforeUnmount(() => {
            window.removeEventListener('resize', fnContainer);
            window.clearInterval(timer);
        });
        return {
            dataContainer,
            DomRef,
            AutoScalContainerRef,
        };
    },
});
</script>

<style lang="scss" scoped>
.auto-scal-container {
    width: 100%;
    height: 100%;
    position: relative;
    overflow: auto;
    /** 隐藏滚动条 */
    -ms-overflow-style: none;
    scrollbar-width: none;
    &::-webkit-scrollbar {
        display: none;
    }
    > .auto-scal-container-inner {
        overflow: hidden;
        transform-origin: left top;
        z-index: 999;
        width: max-content;
        height: max-content;
        position: absolute;
        top: 0;
        left: 0;
    }
}
</style>