mesh网格数据解析及cesium绘制格网三角网可视化实现

news2024/12/28 6:51:58

代码实现运行效果

技术术语

Mesh通常指网络拓扑中的网状结构。在计算机网络中,Mesh是指每个节点都与其他节点相连,形成一个无中心的网状结构。Mesh网络常见于分布式计算、传感器网络、互联网等场景中。另外,在3D计算机图形学中,Mesh是一个表示3D模型的网络,由许多小而简单的三角形构成;

Mesh(格网)是一种排列成规则网格状的结构,其中的每个单元格都是相同大小和形状的。在计算机图形学、数值分析、计算机辅助设计(CAD)和计算机辅助制造(CAM)等领域,Mesh广泛应用于以下应用场景:

  1. 三维建模:Mesh被用于创建三维模型,能够提供网格、曲面及多边形建模技术。

  2. 游戏开发:游戏开发者使用Mesh来构建游戏角色、场景和特效。

  3. 计算机辅助设计:在CAD中,Mesh用于建立几何模型,它提供了许多建模工具和技术,以便于设计师可以使用Mesh模型来创建复杂的几何形状。

  4. 数值分析:在数学、工程和物理等领域中,Mesh被用于数值分析、有限元模拟和计算流体动力学等计算应用程序中。

  5. 医学领域:在医学图像处理中,Mesh被用于生成三维重建的解剖结构。

  6. 建筑设计:在建筑设计中,Mesh被用于建立建筑外观、结构和平面图。

  7. 制造业:在制造业中,Mesh可以用于模拟非线性、动态和多物理场景下的部件行为,以提高制造效率和减少成本。

  8. 流体力学:Mesh格网可以用于流体力学领域中的数值模拟和计算流体力学等。

  9. 结构力学:Mesh格网可以用于结构力学中的有限元分析和结构优化等。

  10. 计算机动画:Mesh格网可以用于计算机动画中的人物建模、环境建模和特效制作等。

  11. 环境工程:水污染扩散模拟,水质模拟预测。

解析接口关键代码编写

//http://localhost:8085/ReadMesh/getMeshDataFiltered?FileName=A.mesh
   @RequestMapping(value = "/getMeshDataFiltered",method = RequestMethod.GET)
public @ResponseBody Map getMeshDataFiltered(String FileName) {

       //! 获取传入的参数,存在传入的文件名,则替换默认的文件名
   String defaultfilename = "A.mesh";
       String filename = FileName;
   if (!filename.isEmpty()){
      defaultfilename = filename;
   }
   String Meshpath = defaultfilename;
   String fileTyle = Meshpath.substring(Meshpath.lastIndexOf("."),Meshpath.length());

   Map map = new HashMap();
   if (fileTyle.equals(".mesh")){
      map = GenDataFromMesh(Meshpath);
   }

   if (fileTyle.equals(".msh")){
      map = GenDataFromMsh(Meshpath);
   }

   return  map;
}

前端可视化关键代码编写

primitiveTriangle:{
  isRLayerPanel: true,
  primitives:[],
  url: '/static/data/trangles.json',
  dataPath: '',
  dataIdField: 'code',
  options:{
    id:'primitiveTriangle',
    name:'三角格网',
    type:'triangles',
    isShow: false
  },
  location: {
    "destination":{"x":-2194142.1719457568,"y":4477352.104342483,"z":3981503.0453665117},
    "orientation":{"heading":6.283185231778362,"pitch":-0.6090220537393618,"roll":7.622047348831984e-8},
    duration: 2
  },
  entityType:'primitive'
}
<template>
  <div class="container">
    <div id="cesiumContainer1" style="height: 85%">
      <div id="tooltippop" class="ol-popup-tip" style="display:none; z-index:120; height:30px;">
        <div id="tooltip-title"></div>
        <div id="tooltip-content"></div>
      </div>
      <div id="gisToolPopoup">
        <GisTool :zjnCesium="zjnCesium" @setLayerVisible="setLayerVisible"  @zoomToC="zoomToC"></GisTool>
      </div>
      <div id="layersPanel">
        <layerPanel :layersInfo="layersInfo" @setLayerVisible="setLayerVisible"  @zoomToC="zoomToC"></layerPanel>
      </div>
    </div>
    <popHover :popHoverInfo="popHoverInfo" :popHoverScreenPoint="popHoverScreenPoint" :popHoverVisible="popHoverVisible"></popHover>
    <popClick :popAspect="popAspect" :popClickScreenPoint="popClickScreenPoint" :popClickVisible="popClickVisible" :popClickTitleInfo="popClickTitleInfo" :popClickContentInfo="popClickContentInfo"></popClick>
    <div class="CoordinateLabel">
      <p><label id="lon"></label></p>
      <p><label id="lat"></label></p>
      <p><label id="cdem"></label></p>
      <p><label id="cvInfo"></label></p>
    </div>
    <div>
      <input value="获取当前视图" type="button" style="height: 50px;width:100px" @click="getCv()">
    </div>
  </div>

</template>

<script>
    // import { Viewer,createWorldTerrain,Cesium3DTileset,WebMapTileServiceImageryProvider,ImageryLayer,Cartesian3,HeadingPitchRange,Math} from 'cesium/Cesium'
    import  'cesium/Widgets/widgets.css'
    import './renderStyle/index.css'
    import GisTool from "./gisTool"
    import ZJNCesium from './ZJNCesium.js'
    import layerPanel from './widgets/layerPanel/index'
    import popHover from './widgets/popHover/index'
    import popClick from './widgets/popClick/index'
    import {layersInfo} from './store/LayersInfo'
    import {LayersRenderSet} from './renderSet/LayersRenderSet'
    import {LayersRenderLabelSet} from './renderSet/LayersRenderLabelSet'
    import {layerMsgClick} from "./layerMsg/LayerMsgClick";
    import {
      CommonDrawEntities,
      CommonDrawEntitiesByLayerID,
      CommonDrawWallEntities,
      CommonDrawPolylineEntities,
      setLayerVisible,
      CommonDrawPolygonEntities,
      CommonDrawPointEntitiesByUrl,
      CommonDrawWallEntitiesByUrl,
      CommonDrawPolylineEntitiesByUrl,
      CommonDrawPolygonEntitiesByUrl,
      CommonDrawCorridorEntitiesByUrl,
      CommonDrawByGeojson,
      CommonDrawPolylineVolumeEntitiesByUrl,
      CommonDrawWindyEntitiesByUrl,
      CommonDrawHeatmapByUrl,
      CommonDrawPrimitiveEntitiesByUrl,
      CommonCreateMeshGrid,CommonCreateMeshTriangle
    } from './MapCommon'
    import {carDatas} from "../../common/api/carRoad"
    import {linedata,polygondata} from "./data/pointlinepolygon"
    import {TransferSimUtil} from "./utils/TransferSimUtil"

    var zjnCesium;
    export default {
        name: "earth",
        components: {
          layerPanel,
          GisTool,
          popHover,
          popClick
        },
        data() {
            return {
              zjnCesium: null,
              popHoverScreenPoint: {x: null, y: null},
              popHoverInfo: '',
              popHoverVisible: false,
              popClickScreenPoint: {x: null, y: null},
              popAspect:{cWidth: 600, cHeight: 400},
              popClickPoint: null,
              popClickTitleInfo: '',
              popClickContentInfo: '',
              popClickVisible: false,
              transferSimUtil: null,
              buttondaohe:"道合",
              layersInfo:layersInfo,
              modelList:{
                daohe:{x: -2412207.790025016,y: 4418038.146476992,z: 3904021.2752170297},
                daoheOrientation:{
                  heading : 0,
                  pitch : -0.3,
                  roll : 0
                },
                caike:{x: -2399848.645912107,y: 4425276.703809752,z: 3903524.9361700616},
                caikeOrientation:{
                  heading : 0,
                  pitch : -0.3,
                  roll : 0
                },
                dairuike:{x: -2398945.254669891,y: 4426231.6794353435,z: 3903000.9872286734},
                dairuikeOrientation:{
                  heading : 0,
                  pitch : -0.3,
                  roll : 0
                },
                guangyue:{x: -2410663.34105633, y: 4417042.059943647, z: 3905962.3976926757},
                guangyueOrientation:{heading: 3.282430123199906,pitch: -0.20432213919653686,roll: 7.223571873993251e-7}
              },
            };
        },
        methods:{
          setPosition:function (key){
            zjnCesium.viewer.camera.flyTo({
              destination : this.modelList[key],
              orientation : this.modelList[key+'Orientation'],
              duration: 2
            });
          },
          getCv:function (){
            let cp=zjnCesium.getCurrentViewPosition();
            document.getElementById('cvInfo').innerText=JSON.stringify(cp);
            // this.transferSimUtil.RemoveTrack()
            // this.setViewType(1)
          },
          MousemoveCallback(data,layerId,c){
            // debugger
            if (layersInfo[layerId] && layersInfo[layerId].floatLabelInfo) {
              this.popHoverScreenPoint.x = c.x + layersInfo[layerId].floatLabelInfo.offsetX
              this.popHoverScreenPoint.y = c.y + layersInfo[layerId].floatLabelInfo.offsetY
              this.popHoverInfo = data[layersInfo[layerId].floatLabelInfo.floatLabelField]
              this.popHoverVisible = true
            } else {
              this.popHoverVisible = false
            }
          },
          MouseclickCallback(data,layerId){
            if (layersInfo[layerId].CustomPopupTemplate) {
              this.popClickTitleInfo = data[layersInfo[layerId].CustomPopupTemplate.titleField]
              this.popClickContentInfo = layersInfo[layerId].CustomPopupTemplate.content
              let attrs = Object.keys(data)
              for (let i = 0; i < attrs.length; i++) {
                this.popClickContentInfo = this.popClickContentInfo.replaceAll('{' + attrs[i] + '}', data[attrs[i]])
              }
              this.popAspect.cWidth = layersInfo[layerId].CustomPopupTemplate.width
              this.popAspect.cHeight = layersInfo[layerId].CustomPopupTemplate.height
              this.popClickVisible = true
            }
            if(layerMsgClick[layerId] !== undefined){
              for(var i = 0; i < layerMsgClick[layerId].length; i++){
                var mcmd = layerMsgClick[layerId][i].method+'(';
                for(var j = 0; j < layerMsgClick[layerId][i].params.length; j++){
                  mcmd += layerMsgClick[layerId][i].params[j];
                  if(j < layerMsgClick[layerId][i].params.length - 1){
                    mcmd += ',';
                  }
                }
                mcmd += ')';
                eval(mcmd);
              }
            }
          },
          setLayerVisible(layerId, visible){
            setLayerVisible(layersInfo,layerId,visible)
            var testdata = [
              [115.66560745239256,
                34.41760191899927],
              [115.67530632019043,
                34.41795594404557],
              [115.685133934021,
                34.4180621512672],
              [115.69406032562254,
                34.4180621512672],
              [115.69509029388428,
                34.41700007298082],
              [115.69547653198244,
                34.416079594221465],
              [115.69607734680174,
                34.414769664672725],
              [115.69620609283447,
                34.41186650444182],
              [115.69624900817871,
                34.41048569775086],
              [115.69612026214601,
                34.40917568058836],
              [115.69067001342772,
                34.409211086727375],
              [115.69071292877196,
                34.402412833257614]
            ]
            // this.transferSimUtil.SimulateTansfer(testdata)
          },
          zoomToC(location){
            zjnCesium.viewer.camera.flyTo(location);
          },
          testClick(re,layerId){
            debugger
          },
          setViewType(viewType){
            //0二维,1三维
            zjnCesium.setViewType(viewType)
          },
          // setLayerOpacity (layerId, opacity) {
          //   // getLayerByCode(this.smap, layerId).setOpacity(opacity)
          // }
        },
        mounted() {
          zjnCesium = new ZJNCesium("cesiumContainer1");
          this.zjnCesium = zjnCesium
          zjnCesium.initMap()
          for (let key in layersInfo){
            if(layersInfo[key].entityType == 'rectangle'){
              CommonDrawEntitiesByLayerID(zjnCesium,layersInfo,key)
            }else if((layersInfo[key].entityType == 'point' || layersInfo[key].entityType == 'billboard' || layersInfo[key].entityType == 'ellipse' || layersInfo[key].entityType == 'cylinder' || layersInfo[key].entityType == 'box' || layersInfo[key].entityType == 'ellipsoid') && layersInfo[key].url != undefined && layersInfo[key].url != ""){
              CommonDrawPointEntitiesByUrl(zjnCesium,layersInfo,LayersRenderSet,LayersRenderLabelSet,key)
            }
            else if(layersInfo[key].entityType == 'heatmap'){
              CommonDrawHeatmapByUrl(zjnCesium,layersInfo,key)
            }
            else if((layersInfo[key].entityType == 'wall') && layersInfo[key].url != undefined && layersInfo[key].url != ""){
              CommonDrawWallEntitiesByUrl(zjnCesium,layersInfo,LayersRenderSet,LayersRenderLabelSet,key)
            }
            else if((layersInfo[key].entityType == 'line') && layersInfo[key].url != undefined && layersInfo[key].url != ""){
              CommonDrawPolylineEntitiesByUrl(zjnCesium,layersInfo,LayersRenderSet,LayersRenderLabelSet,key)
            }
            else if((layersInfo[key].entityType == 'corridor') && layersInfo[key].url != undefined && layersInfo[key].url != ""){
              CommonDrawCorridorEntitiesByUrl(zjnCesium,layersInfo,LayersRenderSet,LayersRenderLabelSet,key)
            }
            else if((layersInfo[key].entityType == 'polylineVolume') && layersInfo[key].url != undefined && layersInfo[key].url != ""){
              CommonDrawPolylineVolumeEntitiesByUrl(zjnCesium,layersInfo,LayersRenderSet,LayersRenderLabelSet,key)
            }
            else if((layersInfo[key].entityType == 'polygon') && layersInfo[key].url != undefined && layersInfo[key].url != ""){
              CommonDrawPolygonEntitiesByUrl(zjnCesium,layersInfo,LayersRenderSet,LayersRenderLabelSet,key)
            }
            else if((layersInfo[key].entityType == 'primitive') && layersInfo[key].url != undefined && layersInfo[key].url != ""){
              CommonDrawPrimitiveEntitiesByUrl(zjnCesium,layersInfo,LayersRenderSet,LayersRenderLabelSet,key)
            }
            else if((layersInfo[key].entityType == 'windy') && layersInfo[key].url != undefined && layersInfo[key].url != ""){
              CommonDrawWindyEntitiesByUrl(zjnCesium,layersInfo,key)
            }
            else if(layersInfo[key].entityType == 'glb'){
              zjnCesium.CommonCreateGlbEntityModel(layersInfo[key])
            }
            else if(layersInfo[key].entityType == 'geojson'){
              CommonDrawByGeojson(zjnCesium,layersInfo,LayersRenderSet,LayersRenderLabelSet,key)
            }
            else{
              zjnCesium.commonAddProviderLayer(layersInfo,key)
            }

          }
          // CommonCreateMeshTriangle(undefined,zjnCesium,layersInfo,'')
          // CommonCreateMeshGrid(zjnCesium,layersInfo,'')
          // CommonCreateMesh(undefined,zjnCesium,layersInfo,'')
          // CommonDrawEntities(outputData,zjnCesium,layersInfo,LayersRenderSet,LayersRenderLabelSet,'outPutPoint','lng','lat','outPutId')
          // // setLayerVisible(layersInfo,'outPutPoint',false)
          // CommonDrawWallEntities(roadData,zjnCesium,layersInfo,LayersRenderSet,LayersRenderLabelSet,'roadWall','positions','minimumHeights','code')

          // CommonDrawPolylineEntities(linedata,zjnCesium,layersInfo,LayersRenderSet,LayersRenderLabelSet,'rline','positions','code')

          // CommonDrawPolygonEntities(polygondata,zjnCesium,layersInfo,LayersRenderSet,LayersRenderLabelSet,'rpolygon','positions','code')

          // carDatas().then((res)=>{
          //   // CommonDrawWallEntities(res.data,zjnCesium,layersInfo,LayersRenderSet,LayersRenderLabelSet,'roadWall','positions','minimumHeights','code')
          // })
          // setLayerVisible(layersInfo,'roadwall',false)
          // zjnCesium.createGltfEntityModel('/static/model/bingdundun.glb','gltf','xmf',115.650964712670241,34.44454369992611,{heading: 90, pitch: 0, roll: 0})
          //绑定鼠标移动,点击等事件
          zjnCesium.bindMousemoveDefault(this.MousemoveCallback);
          zjnCesium.bindLonLatOnMouseMove("lon", "lat", "cdem");
          //地图点击
          zjnCesium.bindClickDefault(this.MouseclickCallback);
          //设置初始视野
          zjnCesium.Home();
          this.transferSimUtil = new TransferSimUtil(zjnCesium)
        }
    };
</script>
<style>
#layersPanel{
  position: absolute;
  top: 50px;
  right: 300px;
  z-index: 999;
}
#gisToolPopoup{
  position: absolute;
  top: 50px;
  left: 20px;
  z-index: 999;
}
</style>
可视化运行效果(水质污染扩散)

如果对恁有帮助,请点赞打赏支持,多谢!

技术合作交流qq:2401315930

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

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

相关文章

前端web入门-移动web-day08

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 平面转换 平面转换 transform 平面转换 – 平移 平移实现居中效果 平面转换 – 旋转 平面转换 – 改…

最新特斯拉电机控制器4D1实拍

特斯拉发布过自己的扁线电机&#xff0c;最近Ingineerix大神发布了特斯拉最新动力系统的拆机视频&#xff0c;本篇结合之前的Tesla Model 3 SIC 控制器&#xff08;控制器具体命名不清楚&#xff0c;以最熟悉的一款车型进行描述我们不妨称之为第二代&#xff0c;第一代为单管IG…

Web安全——JavaScript基础(加入案例)

JavaScript基础 一、概述二、嵌入方法1、内嵌式2、外链式3、行内式 三、语句四、注释五、变量六、JavaScript 保留关键字七、JavaScript 作用域1、JavaScript 局部变量2、JavaScript 全局变量 八、数据类型1、判断类型2、数字类型&#xff08;Number&#xff09;3、字符串型&am…

满汉楼项目

满汉楼项目 1. 满汉楼介绍 满汉楼是一个综合餐饮管理系统&#xff0c;其主要分为&#xff1a; 人事登记&#xff1a;各部门人员信息登录管理&#xff1a;员工号、姓名、职位、密码菜谱价格&#xff1a;菜谱及价格报表统计&#xff1a;统计销售额成本及库房&#xff1a;名称注…

深度学习优化算法

梯度下降算法 随机梯度下降。随机梯度下降是指每次迭代在训练数据中随机抽取一个数据计算梯度来更新模型得参数。随机梯度下降容易受到噪声干扰,训练时间长,代价函数最终会围绕全局最小值或者局部极小值震荡。批量梯度下降。每次迭代时使用所有的训练数据来计算梯度更新模型的…

vue使用emit控制改变父组件的值,实现子组件的显示与隐藏

vue使用emit控制改变父组件的值&#xff0c;实现子组件的显示与隐藏 需求概述 父组件在提交表单后&#xff0c;弹框进行提示&#xff0c;子组件是一个弹框。 vue版本 v2.x 实现原理 在父组件内建立控制器isShowModal&#xff0c;使用v-if来控制子组件的显示与隐藏。在子组…

Node.js中的process.nextTick与浏览器环境中的nextTick有何不同?

文章目录 nextTick 是一个用于异步操作的函数Node.js中的process.nextTick vs 浏览器环境中的nextTick1. 执行时机2. 微任务队列3. 堆栈溢出风险4. 兼容性 nextTick 是一个用于异步操作的函数 nextTick 是一个用于异步操作的函数&#xff0c;用来在当前执行栈执行完毕后&#…

第2章 k-近邻算法

文章目录 第2章 k-近邻算法2.1k-近邻算法概述2.1.1准备&#xff1a;使用Python导入数据2.1.2实施kNN分类算法 2.2示例&#xff1a;使用k近邻算法改进约会网站的2.2.2分析数据&#xff1a;使用Matplotlib创建散点图2.2.3准备数据&#xff1a;归一化数值2.2.4测试算法 第2章 k-近…

C++中的继承(超详细)

文章目录 &#x1f4cd;前言C中的继承1.继承的概念及定义1.1 继承的概念1.2 继承的定义1.2.1 定义格式1.2.2 继承关系和访问限定符1.2.3 继承基类成员访问方式的变化 2. 基类和派生类对象赋值转换3.继承中的作用域4.派生类的默认成员函数5.继承与友元6.继承与静态成员7.复杂的菱…

Anaconda详细安装及配置教程(Windows)

Anaconda详细安装及配置教程&#xff08;Windows&#xff09; 一、下载方式1、官网下载2、网盘下载 二、安装三、配置四、创建虚拟环境 一、下载方式 1、官网下载 点击下载 点击window下载即可。 2、网盘下载 点击下载 二、安装 双击运行 点next 点I agree next 如…

4.26 能量谱

上述函数使用时域计算就很复杂&#xff0c;但是使用帕斯瓦尔就比较简单

git 获取两个版本间的变更文件,生成增量包

可用于代码在无git环境情况下的做增量包 #下面命令可以获取两个版本直接的变更文件 git diff 开始版本号 截止版本号 --name-only 使用管道命令生成压缩包 git diff 开始版本号 截止版本号 --name-only | xargs zip update.zip 牛逼之处就是打出来的压缩包是带有目录层级关系的…

ubuntu20 准备阶段

1. 换源 换成中国的源&#xff0c;图中为腾讯源 2. 系统自带中文输入法 中文输入法 3. 终端Terminator的安装 终端Terminator的安装 4. 截图shtter shutter 5. ros安装 ros安装 6. gazebo11 安装ros自带版本11&#xff0c;可以使用

前端-css选择器

CSS选择器 水平居中 margin: 0 auto;div、p、h 需要设置元素的宽度&#xff0c;否则会自动撑满父元素 <divstyle"margin: 0 auto; width:200px; border: 1px solid #cccccc; text-align: center;" >Hello World! </div>复合选择器 后代选择器 父选择…

Go切片底层原理

slice在函数参数传递过程中是值传递还是引用类型传递&#xff1f; 严格来说&#xff0c;是值传递&#xff0c;但是又呈现出了引用传递的效果 上面图片显示出现了引用传递的现象 但是下面的图片又不符合引用传递的现象了 Slice基本原理 本质是一个结构体 上面的图片也解释了为…

如何使用Jenkins来定时执行JMeter脚本,并查看测试报告

【摘要】 Jenkins是一个开源的持续集成工具&#xff0c;可以帮助开发人员自动构建、测试和部署软件项目。JMeter是一个流行的性能测试工具&#xff0c;它可以模拟多种负载情况来测试应用程序的性能和稳定性。本文将介绍如何使用Jenkins来定时执行JMeter脚本&#xff0c;并查看测…

让集合数据操控指尖舞动:迭代器和生成器的精妙之处

文章目录 &#x1f499;迭代器&#xff08;Iterator&#xff09;迭代器的特点&#xff1a;迭代器的优点&#xff1a;代码案例&#xff1a; &#x1f49a;生成器&#xff08;Generator&#xff09;生成器的特点&#xff1a;生成器的优点&#xff1a;代码案例&#xff1a; &#…

Java面试Day12

1.意向锁是什么&#xff1f;有什么作用&#xff1f;它是表级锁还是行级锁&#xff1f; 意向锁是什么 在使用 InnoDB 引擎的表里时对某些记录加上「共享锁」之前&#xff0c;需要先在表级别加上一个「意向共享锁」 在使用 InnoDB 引擎的表里时对某些记录加上「独占锁」之前&…

RK3568 NPU YOLOV5S 目标检测DEMO

视频流解析 硬件环境 开发板&#xff1a;RK356X 系统&#xff1a;Debian11 获取源码 程序源码内置SDK目录 $ ls external/rknpu2/examples/rknn_yolov5_video_demo/build build-android_RK356X.sh build-android_RK3588.sh build-linux_RK356X.sh build-linux_RK3588…

《计算机系统与网络安全》第五章 消息认证与数字签名

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…