一般大屏使用的伸缩布局React hooks版与vue3 hooks版

436 阅读1分钟

前言

通常设计稿页面要放到不同尺寸屏幕上展示,这时就需要屏幕自适应了

原理

使用css transform属性, transform: scale(${scaleX}, ${scaleY}) 页面根据屏幕尺寸进行一定比例的放大或者缩小。

React hooks版

useWindowScale文件

import { useEffect, useState } from 'react';

const useWindowScale = (
    designWidth: number = 1920, // 设计稿尺寸
    designHeight: number = 1080,
) => {
    const [scaleX, setScaleX] = useState(1);
    const [scaleY, setScaleY] = useState(1);
    const handleResize = () => {
        const _scaleX = window.innerWidth / designWidth;
        const _scaleY = window.innerHeight / designHeight;
        setScaleX(_scaleX);
        setScaleY(_scaleY);
    };
    useEffect((): (() => void) | void => {
        handleResize();
        window.addEventListener('resize', handleResize);
        return () => {
            window.removeEventListener('resize', handleResize);
        };
    }, []);
    return {
        scaleX,
        scaleY,
    };

};

export default useWindowScale;

引用useWindowScale hooks封装 ScaleLayout React组件

大屏页面只需引用ScaleLayout组件,用ScaleLayout组件包裹根组件就行

import React from 'react';
import useWindowScale from "@app/hooks/useWindowScale";
export interface ScaleLayoutProps {
    className?: any;
    style?: React.CSSProperties;
    children?: React.ReactNode;
}

const ScaleLayout = (props: ScaleLayoutProps) => {
    const { children } = props;
    const { scaleX, scaleY } = useWindowScale();
    return (
        <div
            style={{
                width: '1920px',
                height: '1080px',
                transformOrigin: 'left top',
                transform: `scale(${scaleX}, ${scaleY})`,
                transition: 'transform .3s ease-in-out',
            }}
        >
            {children}
        </div>
    );
};
export default ScaleLayout;

react举例使用

Snipaste_2022-10-28_09-23-47.png

vue3 hooks版

useWindowScale文件

import {  onMounted, onUnmounted, reactive, toRefs } from 'vue';
import { DESIGN_WIDTH, DESIGN_HEIGHT } from '@/utils/constant';

const useWindowScale = (
    designWidth: number = DESIGN_WIDTH, //设计稿尺寸
    designHeight: number = DESIGN_HEIGHT,
) => {
    const scale = reactive({
        scaleX: 1,
        scaleY: 1,
    });
    const handleResize = () => {
        scale.scaleX = window.innerWidth / designWidth;
        scale.scaleY = window.innerHeight / designHeight;
    }
    handleResize();
    onMounted(() => {
        window.addEventListener("resize", handleResize);
    });

    onUnmounted(() => {
        window.removeEventListener("resize", handleResize);
    });

    return toRefs(scale);
};

export default useWindowScale;

DESIGN_WIDTH设计稿宽度1920与DESIGN_HEIGHT设计稿高度1080是常量

引用useWindowScale hooks封装 ScaleLayout vue组件

大屏页面只需引用ScaleLayout组件,用ScaleLayout组件包裹根组件就行 ScaleLayout文件

<script setup lang="ts">
import { computed } from 'vue';
//弹性 伸缩布局
import useWindowScale from "@/hooks/useWindowScale";
import { DESIGN_WIDTH, DESIGN_HEIGHT } from '@/utils/constant';
const { scaleX, scaleY }  = useWindowScale();
const designWidth = computed(() => DESIGN_WIDTH + 'px');
const designHeight = computed(() => DESIGN_HEIGHT + 'px');
</script>
<template>
    <div class="scale-wrapper">
        <slot/>
    </div>
</template>
<style lang="less" scoped>
.scale-wrapper {
    width: v-bind(designWidth);
    height: v-bind(designHeight);
    transform-origin: left top;
    transform: scale(v-bind(scaleX), v-bind(scaleY));
    transition: transform .3s ease-in-out;
}
</style>

vue举例使用

Snipaste_2022-10-28_09-36-21.png

结语

写react多年,代码思想多少都是互通的,欢迎评论区交流