【win7Window】高仿Windows7系统窗体

news2024/10/5 18:26:07

特性:

  1. 任意拖拽到边界可以最大化、半屏放大
  2. 双击边界可以水平、纵向最大化
  3. 可以拖拽四边、四个顶点调整窗体尺寸
  4. 可以最大化、还原、最小化、关闭
  5. 支持双击标题栏最大化、还原
  6. 支持双击左上角图标关闭窗体

win7Window源码

<template>
    <div :class="$options.name" :style="style" :size="size">
        <div class="titlebar" ref="titlebar" @dblclick.stop.prevent="dblclickHeader">
            <div class="title">
                <img :src="title.iconURL" @mousedown.stop @dblclick.stop.prevent="dblclickTitleIcon">
                <label>{{ title.label }}</label>
            </div>
            <div class="buttons" @mousedown.stop @dblclick.stop>
                <div class="minimize" @click.stop="minimize" title="最小化">
                    <img src="static/img/desktop/icon/minimize.png">
                </div>
                <div class="maximize" v-if="size !== 'lg'" @click.stop="maximize" title="全屏">
                    <img src="static/img/desktop/icon/maximize.png">
                </div>
                <div class="maximize" v-if="size !== 'md'" @click.stop="restore_maximize" title="还原">
                    <img src="static/img/desktop/icon/restore-maximize.png">
                </div>
                <div class="close" @click.stop="close">
                    <img src="static/img/desktop/icon/close.png">
                </div>
            </div>
        </div>
        <div class="content">
            <div class="path-bar">
                <span class="back disabled"></span>
                <div class="path">{{ path }}</div>
                <input class="search" placeholder="输入关键词" v-model="searchValue" @keyup.enter="search">
            </div>
            <div class="files-container">

            </div>
        </DIV>

        <!-- 拖拽到屏幕边界的透明层 -->
        <div class="win7Window-opacity-bg" :style="win7WindowBgStyle" v-if="win7WindowBgStyle"></div>

        <!-- 拖拽移动窗体 -->
        <sgDragMove ref="sgDragMove" :data="dragMoveDoms" :grab="'default'" :grabbing="'move'" @dragStart="dragMoveStart"
            @dragging="draggingMove" @dragEnd="dragMoveEnd" />

        <!-- 拖拽改变窗体尺寸 -->
        <sgDragSize :disabled="size === 'lg'" @dragging="d => style = d" :minWidth="400" :minHeight="200" />

    </div>
</template>
    
<script>
import sgDragMove from "@/vue/components/admin/sgDragMove";
import sgDragSize from "@/vue/components/admin/sgDragSize";
export default {
    name: 'win7Window',
    components: {
        sgDragMove,
        sgDragSize,

    },
    data() {
        return {
            searchValue: '',
            dragSizeDom: null,
            dragMoveDoms: [
                /* {
                    canDragDom: elementDOM,//可以拖拽的位置元素
                    moveDom: elementDOM,//拖拽同步移动的元素
                } */
            ],//可以拖拽移动的物体
            style_bk: null,
            style: {
                zIndex: 1,
                height: '500px',
                width: '800px',
                left: '0',
                top: '0',
            },
            dragStartPoint: null,
            win7WindowBgStyle: {},
            size: 'md',//lg全屏、md普通、mn最小
        }

    },
    props: [
        "initStyle",
        "title",
        "path",
    ],
    watch: {
        initStyle: {
            handler(d) {
                if (d && Object.keys(d).length) {
                    this.style = d;
                } else {
                    this.style.left = `${(innerWidth - parseFloat(this.style.width)) / 2}px`;
                    this.style.top = `${(innerHeight - parseFloat(this.style.height)) / 2}px`;
                }

            }, deep: true, immediate: true,
        },
        size: {
            handler(d) {
                if (d === 'md') {
                    this.$nextTick(() => {
                        let rect = this.$el.getBoundingClientRect();
                        if (this.style
                            && this.style_bk
                            && (rect.x < 0 || rect.y < 0)
                        ) {
                            this.style = null;
                            this.$nextTick(() => {
                                this.style = JSON.parse(JSON.stringify(this.style_bk));
                            });
                        }
                    });

                }
            }, deep: true, immediate: true,
        },
    },
    created() {

    },
    mounted() {
        this.dragSizeDom = this.$el;//拖拽设置大小的元素
        this.dragMoveDoms = [
            {
                canDragDom: this.$refs.titlebar,//窗体标题栏可以拖拽
                moveDom: this.$el,//拖拽的时候,整个窗体一起跟随移动
            }
        ];
    },
    computed: {
    },
    methods: {
        search(d) {
            this.$emit(`search`, this.searchValue);
        },
        dblclickHeader(d) {
            switch (this.size) {
                case 'lg':
                    this.restore_maximize();
                    break;
                case 'md':
                    this.maximize();
                    break;
            }
        },
        changeSize(d) {
            this.size = d
            switch (this.size) {
                case 'lg':
                    this.maximize();
                    break;
                case 'md':
                    this.restore_maximize();
                    break;
            }

        },
        dblclickTitleIcon(d) {
            this.close(d);
        },
        close(d) {
            this.$emit(`close`, d);
        },
        minimize(d) {
            this.size = 'mn';
        },
        maximize(d) {
            this.size = 'lg';
            this.style = null;
            this.storeOriginStyle();
            this.$nextTick(() => {
                this.style = {
                    left: `0px`,
                    top: `0px`,
                    width: `${innerWidth}px`,
                    height: `${innerHeight}px`,
                    transition: '.1s',
                };
            });
        },
        restore_maximize(d) {
            this.size = 'md';
            this.style = null;
            this.$nextTick(() => {
                this.style = JSON.parse(JSON.stringify(this.style_bk))
            });
        },
        storeOriginStyle() {
            let rect = this.$el.getBoundingClientRect();
            if (rect.y > 0 && rect.width < innerWidth && rect.height < innerHeight) {
                this.style_bk = {
                    left: `${rect.x}px`,
                    top: `${rect.y}px`,
                    width: `${rect.width}px`,
                    height: `${rect.height}px`,
                }
            }
        },
        storeDragStartPoint({ x, y }) {
            let rect = this.$el.getBoundingClientRect();
            if (rect.width >= innerWidth || rect.height >= innerHeight) {
                this.dragStartPoint = { x };
            }
        },
        dragMoveStart({ $event: { x, y } }) {
            this.storeOriginStyle();
            this.storeDragStartPoint({ x, y });
        },
        draggingMove({ $event: { x, y } }) {
            let dis = 20;
            let rect = this.$el.getBoundingClientRect();
            if (y <= (dis / 2)) {
                // 拖拽到浏览器顶部
                this.win7WindowBgStyle = {
                    left: `${-rect.x + (dis / 2)}px`,
                    top: `${-rect.y + (dis / 2)}px`,
                    width: `${innerWidth - dis}px`,
                    height: `${innerHeight - dis}px`,
                    opacity: .5,
                    transition: '.1s',
                };
            }
            else if (x <= 0) {
                // 拖拽到浏览器左侧
                this.win7WindowBgStyle = {
                    left: `${-rect.x + (dis / 2)}px`,
                    top: `${-rect.y + (dis / 2)}px`,
                    width: `${innerWidth / 2 - dis}px`,
                    height: `${innerHeight - dis}px`,
                    opacity: .5,
                    transition: '.1s',
                };
            }
            else if (x >= innerWidth - (dis / 2)) {
                // 拖拽到浏览器右侧
                this.win7WindowBgStyle = {
                    left: `${-((innerWidth / 2) - (innerWidth - rect.x)) + (dis / 2)}px`,
                    top: `${-rect.y + (dis / 2)}px`,
                    width: `${innerWidth / 2 - dis}px`,
                    height: `${innerHeight - dis}px`,
                    opacity: .5,
                    transition: '.1s',
                };
            } else {
                // 拖拽回到浏览器中间
                this.size = 'md';
                this.style.width = this.style_bk.width;
                this.style.height = this.style_bk.height;
                if (this.dragStartPoint) {
                    let leftPointDis = (this.dragStartPoint.x / innerWidth) * parseFloat(this.style.width);//计算鼠标到左上角定点的距离
                    this.$refs.sgDragMove.setOffset({
                        x: leftPointDis
                    });
                    this.dragStartPoint = null;
                }
                this.win7WindowBgStyle && (this.win7WindowBgStyle = {
                    left: `0px`,
                    top: `0px`,
                    width: `${rect.width}px`,
                    height: `${rect.height}0px`,
                    opacity: 0,
                    transition: 'none',
                })
            }
        },
        dragMoveEnd({ $event: { x, y } }) {
            let dis = 20;
            if (y <= (dis / 2)) {
                // 拖拽到浏览器顶部
                this.maximize()
            }
            else if (x <= 0) {
                // 拖拽到浏览器左侧
                this.style = null;
                this.$nextTick(() => {
                    this.style = {
                        left: `0px`,
                        top: `0px`,
                        width: `${innerWidth / 2}px`,
                        height: `${innerHeight}px`,
                        transition: '.1s',
                    };
                });
            }
            else if (x >= innerWidth - (dis / 2)) {
                // 拖拽到浏览器右侧
                this.style = null;
                this.$nextTick(() => {
                    this.style = {
                        left: `${innerWidth / 2}px`,
                        top: `0px`,
                        width: `${innerWidth / 2}px`,
                        height: `${innerHeight}px`,
                        transition: '.1s',
                    };
                });
            } else {
                // 拖拽回到浏览器中间

            }
            // 防止窗口拖拽到最底部,标题栏不见了,没办法再把窗体拖回来
            this.$nextTick(() => {
                let rect = this.$el.getBoundingClientRect();
                let maxY = innerHeight - 32;
                if (rect.y > maxY) {
                    this.style.top = 'revet';
                    this.$nextTick(() => {
                        this.style.top = `${maxY}px`;
                    });
                }
            });
            this.win7WindowBgStyle = null;
        },
        emit(d) {
            this.$emit(`input`, d);
        },
    }
};
</script>
    
<style lang="scss" scoped>
$width: 600px;
$minWidth: 400px;
$minHeight: 200px;

//  ----------------------------------------
.win7Window-bg {
    user-select: none;
    position: absolute;
    background: linear-gradient(180deg, rgba(250, 250, 250, 0.1) 0%, rgba(255, 255, 255, 0.4) 30%, rgba(70, 70, 70, 0.2) 40%, rgba(170, 170, 170, 0.1) 100%);
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.8), 0 0 8px 3px rgba(10, 10, 10, 0.8);
    backdrop-filter: blur(7px) brightness(0.9);
    border-radius: 8px;
    display: flex;
    flex-direction: column;
    font-size: 15px;
    min-width: $minWidth;
    min-height: $minHeight;
    opacity: 0.9;
}

.win7Window {
    @extend .win7Window-bg;
    // resize: both;
    transition: none;

    &[focused] {
        opacity: 1;
    }


    .titlebar {
        height: 32px;
        display: flex;
        flex-direction: row;
        justify-content: space-between;
        align-items: center;
        padding: 0 10px;
        opacity: 1;

        .title {
            flex-grow: 1;

            img {
                width: 20px;
                height: 20px;
                margin-right: 5px;
                vertical-align: middle;
                cursor: default;
            }

            label {
                text-shadow: 0 0 5px rgba(255, 255, 255, 1), 0 0 5px rgba(255, 255, 255, 1), 0 0 5px rgba(255, 255, 255, 1), 0 0 5px rgba(255, 255, 255, 1);
                flex-grow: 1;
                height: 100%;
                line-height: 32px
            }
        }

        .buttons {
            flex-shrink: 0;
            display: flex;
            flex-direction: row;
            height: 19px;
            align-self: flex-start;
            box-shadow: 0 0 3px rgba(255, 255, 255, 0.4), 0 0 0 1px rgba(0, 0, 0, 0.5), inset 0 0 1px 2px rgba(255, 255, 255, 0.4);
            border-top: none;
            border-bottom-left-radius: 5px;
            border-bottom-right-radius: 5px;
            overflow: hidden;

            &>* {
                cursor: default;
                text-align: center;
                line-height: 19px;
                font-size: 12px;
                font-weight: bold;
                color: #fff;
                width: 28px;
                background: linear-gradient(180deg, rgba(200, 200, 200, 0.5) 0%, rgba(200, 200, 200, 0.5) 40%, rgba(110, 110, 110, 0.4) 60%, rgba(150, 150, 150, 0.4) 90%, rgba(180, 180, 180, 0.4) 100%);
                backdrop-filter: grayscale(1);
                transition: .1s;

                img {
                    filter: drop-shadow(0 0 2px rgba(0, 0, 0, 1));
                }

                &:hover {

                    filter: brightness(1.3);

                }

                &:active {
                    filter: brightness(0.9);
                }
            }

            .minimize {
                border-right: solid 1px rgba(0, 0, 0, 0.4);


                img {
                    height: 13px;
                    margin-top: 2px;
                }
            }

            .maximize {
                border-right: solid 1px rgba(0, 0, 0, 0.4);

                img {
                    height: 11px;
                    margin-top: 3px;
                }
            }

            .close {
                background: linear-gradient(180deg, rgba(255, 107, 63, 0.8) 0%, rgba(212, 116, 91, 0.7) 40%, rgba(192, 55, 44, 0.9) 55%, rgba(204, 33, 33, 0.7) 80%, rgba(255, 125, 125, 0.9) 100%);
                width: 46px;


                img {
                    height: 13px;
                    margin-top: 2px;
                }
            }
        }
    }

    .content {
        flex-grow: 1;
        border: solid 1px rgba(10, 10, 10, 0.5);
        overflow: hidden;
        margin: 0 5px 5px 5px;
        max-width: calc(100% - 10px);
        border: 0;
        display: flex;
        flex-direction: column;


        .path-bar {

            display: flex;
            flex-direction: row;
            align-items: center;
            flex-wrap: nowrap;
            margin-bottom: 6px;

            .back {
                background-image: url('/static/img/desktop/icon/back.png');
                width: 32px;
                height: 32px;
                background-repeat: no-repeat;
                background-position: center;
                background-size: contain;
                margin-right: 5px;
                transition: .1s;

                .disabled {
                    filter: grayscale(1);
                }

                &:hover {
                    filter: brightness(1.2);
                }

                &::active {
                    filter: brightness(0.8);
                }

            }

            .path {
                flex-grow: 1;
                color: rgba(0, 0, 0, 1);
                margin-right: 5px;

                height: 24px;
                line-height: 24px;
                padding: 0 5px;
                font-size: 15px;
                border: solid 1px rgba(0, 0, 0, 0.5);
                background: rgba(255, 255, 255, 1);
                border-radius: 2px;
            }

            .search {

                height: 24px;
                line-height: 24px;
                padding: 0 5px;
                font-size: 15px;
                border: solid 1px rgba(0, 0, 0, 0.5);
                background: rgba(255, 255, 255, 1);
                border-radius: 2px;
            }

        }

        .files-container {
            position: relative;
            flex-grow: 1;
            display: flex;
            flex-direction: row;
            flex-wrap: wrap;
            align-items: flex-start;
            justify-content: flex-start;
            align-content: flex-start;
            width: 100%;
            height: 100%;
            overflow: auto;
            background: rgba(255, 255, 255, 1);
            flex-grow: 1;
            position: relative;
        }
    }


    .win7Window-opacity-bg {
        @extend .win7Window-bg;
        position: fixed;
        left: 0;
        top: 0;
        width: 0;
        height: 0;
        z-index: -1;
        opacity: 0;
        pointer-events: none;
        background: #ffffff33;
    }

    &[size="lg"] {}

    &[size="md"] {}

    &[size="mn"] {
        display: none;
    }

}
</style>

 应用

<template>
    <div :class="$options.name">
        <win7Window :initStyle="initStyle" :title="title" focused />
    </div>
</template>
    
<script>
import win7Window from "@/vue/components/admin/win7Window";
export default {
    name: 'demo',
    components: {
        win7Window
    },
    data() {
        return {
            title: {
                label: '窗体标题',
                iconURL: 'static/img/desktop/icon/computer.png',//窗体图标
            },
            // 窗体初始位置
            initStyle: {
                /*zIndex: 1,
                 height: '345px',
                width: '619px',
                left: '380px',
                top: '133px', */
            },
        }

    },
    props: ["data", "value"],
    watch: {
        value: {
            handler(d) {

            }, deep: true, immediate: true,
        },
    },
    created() {

    },
    mounted() {

    },
    computed: {

    },
    methods: {
        emit(d) {
            this.$emit(`input`, d);
        },
    }
};
</script>
    
<style lang="scss" scoped>
.demo {
    position: absolute;
    left: 0;
    top: 0;

    width: 100%;
    height: 100%;
    /*背景图片*/
    background: transparent url("/static/img/desktop/bg1.jpg") no-repeat center / cover;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/894092.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JS的解析与Js2Py使用

JS的解析与Js2Py使用 JS的解析事件监听器搜索关键字请求关联JS文件 Js2PyJs2Py的简单使用安装Js2Py执行JavaScript代码调用JavaScript函数 Js2Py的应用示例创建JavaScript文件使用JavaScript JS的解析 在一个网站中&#xff0c;登录密码通常是会进行加密操作的&#xff0c;那么…

LeetCode--HOT100题(34)

目录 题目描述&#xff1a;94. 二叉树的中序遍历&#xff08;简单&#xff09;题目接口解题思路1代码解题思路2代码 PS: 题目描述&#xff1a;94. 二叉树的中序遍历&#xff08;简单&#xff09; 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 LeetCode做…

el-table根据容器大小自适应滚动条-修改滚动条样式

需求&#xff1a;父容器里有多个容器为上下级&#xff0c;之后浏览器在缩放的时候&#xff0c;上面容器高度改变了&#xff0c;所以el-table被挤压&#xff0c;如果el-table设置的是固定的高度&#xff0c;那么挤压后内容超出父容器&#xff0c;本文章就是解决这个问题 不自适…

拒绝无效内卷!新同事靠着这套大屏模板效率翻倍,搭上升职快车!

竞争是职场永恒的话题&#xff0c;太多人为了升职加薪卷生卷死&#xff0c;就拿我自己身边来说&#xff0c;这段时间我所在的小组有一个升职机会&#xff0c;好多老员工为了这个机会争得头破血流&#xff0c;一个在公司待了10年的老员工&#xff0c;直接天天加班到12点&#xf…

蓝牙耳机的发展

目录 1.蓝牙耳机的概念 2.蓝牙耳机的发展过程 3.蓝牙耳机的便利性 4.蓝牙耳机未来的发展趋势 1.蓝牙耳机的概念 蓝牙耳机是一种使用蓝牙无线技术连接到音频源设备&#xff08;如智能手机、平板电脑、电脑等&#xff09;的耳机。它们通过无线蓝牙信号接收音频数据&#xff0c…

MybatisPlus的使用

一. 关于注解的使用&#xff0c;官方地址&#xff1a; 注解 | MyBatis-PlusMyBatis-Plus 官方文档https://baomidou.com/pages/223848/#tablename 1.关于TableName的使用 假设我们不加TableName("tbl_employee")的话&#xff0c;那么数据库中的表名和类名相同的话&…

Qt下拉菜单

1&#xff0c;QComboBox 2&#xff0c;setMenu()---设置下拉菜单 AI对话未来丨智能写作对话: setMenu()是QWidget类的一个成员函数&#xff0c;在Qt中用于将一个菜单作为一个控件的下拉菜单设置。具体来说&#xff0c;它会把相应的菜单对象与该控件关联&#xff0c;并在控件上…

Mysql8.0为什么取消了缓存查询的功能

首先我们介绍一下MySQL的缓存机制 【MySQL缓存机制】简单的说就是缓存sql文本及查询结果&#xff0c;如果运行完全相同的SQL&#xff0c;服务器直接从缓存中取到结果&#xff0c;而不需要再去解析和执行SQL。 但如果表中任何数据或是结构发生改变&#xff0c;包括INSERT、UPD…

问道管理:放量打拐什么意思?常见的放量打拐三种形态?

成交量一直是股票交易中比较重要的目标&#xff0c;那么&#xff0c;放量打拐是什么意思&#xff1f;常见的放量打拐三种形状是什么&#xff1f;下面问道管理为我们预备了相关内容&#xff0c;以供参阅。 放量打拐什么意思&#xff1f; 放量是指股票成交量与前几个交易日比较显…

隐私文件夹怎么加密?隐私文件夹加密方法

在个人电脑中&#xff0c;我们经常会将一些个人隐私存放在电脑文件夹中&#xff0c;这些文件夹都需要加密保护。那么&#xff0c;隐私文件夹该怎么加密呢&#xff1f;下面我们就来了解一下吧。 超级秘密文件夹 隐私数据存放在文件夹中&#xff0c;最怕的就是被其他人发现。而如…

迅镭激光中标全球集装箱行业龙头中集集团10家子公司集采项目!

迅镭激光中标喜报频传!继连续中标工程机械、钢构、船舶、电力电气、新能源等多个行业龙头企业后&#xff0c;近日再次中标全球集装箱行业龙头中集集团(CIMC)&#xff0c;这与迅镭激光坚持高端、注重技术引领、十五年的技术沉淀和口碑积累密不可分。 日前&#xff0c;中集集团20…

如何使用ChatGPT创作一个小说式的虚构的世界

世界构建也许是小说写作中最重要的一环&#xff0c;但也可能非常耗时。让ChatGPT加快这一过程吧。 写小说最棒的一点就是有机会从零开始创造一个新世界。你可以创造超凡脱俗的景观&#xff0c;赋予人物魔法。神话故事可以存在于你小说中的现实世界&#xff0c;而传统可以帮助你…

gazebo仿真ros2两轮差速小车没有控制的情况下缓慢移动后退

最近在做一款2轮差速的机器人小车&#xff0c;在做gazebo仿真的时候&#xff0c;发现小车一直在缓慢的后退&#xff0c;一边后退一边缓慢拐弯。 环境&#xff1a;ros2 foxy gazebo-11 小车xacro模型代码 <?xml version"1.0"?> <robot name"jtb…

华为OD机试 - 查找接口成功率最优时间段 - 回溯(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#…

【图书推荐 | 测试】—《测试设计思想》

前言 随着科技的不断发展&#xff0c;互联网的不断进步&#xff0c;日益出现了一种趋势&#xff1a;测试设计将成为一种跨领域的综合性工作&#xff0c;测试者将成为一种跨领域的通用型人才。由此清华大学出版社推出了一本名为《测试设计思想》的书籍&#xff0c;由知名专家周…

分析Flink,源和算子并行度不一致时,运行一段时间后,看似不再继续消费的问题,提供解决思路。

文章目录 背景分析 问题来了比较一开始的情况解决方式 背景 之前有分析过一次类似问题&#xff0c;最终结论是在keyby之后&#xff0c;其中有一个key数量特别庞大&#xff0c;导致对应的subtask压力过大&#xff0c;进而使得整个job不再继续运作。在这个问题解决之后&#xff…

数据分析15——office中的Excel基础技术汇总

0、前言&#xff1a; 这部分总结就是总结每个基础技术的定义&#xff0c;在了解基础技术名称和定义后&#xff0c;方便对相关技术进行检索学习。笔记不会详细到所有操作都说明&#xff0c;但会把基础操作的名称及作用说明&#xff0c;可自行检索。本文对于大部分读者有以下作用…

火山引擎DataLeap:助力PICO落地数据流程规范,提升开发效率

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 作为目前中国市场领跑的头部XR品牌之一&#xff0c;字节跳动旗下的PICO已经拥有了超百万客户。 过去一年&#xff0c;PICO在XR场景中不断建设和发力&#xff0c;为运…

更好的 3D 网格,从重建到生成式 AI

推荐&#xff1a;使用 NSDT场景编辑器 助你快速搭建可二次编辑的3D应用场景 这些生成的 3D 模型通常提取为标准三角形网格。网格表示提供了许多好处&#xff0c;包括支持现有软件包、高级硬件加速和支持物理仿真。但是&#xff0c;并非所有网格都是平等的&#xff0c;这些优势只…