Three.js--》实现3d汽车模型展览搭建

news2024/11/19 5:53:58

目录

项目搭建

初始化three.js基础代码

添加汽车模型展示

动态修改汽车模型


今天简单实现一个three.js的小Demo,加强自己对three知识的掌握与学习,只有在项目中才能灵活将所学知识运用起来,话不多说直接开始。

项目搭建

本案例还是借助框架书写three项目,借用vite构建工具搭建vue项目,vite这个构建工具如果有不了解的朋友,可以参考我之前对其讲解的文章:vite脚手架的搭建与使用 。搭建完成之后,用编辑器打开该项目,在终端执行 npm i 安装一下依赖,安装完成之后终端在安装 npm i three 即可。

因为我搭建的是vue3项目,为了便于代码的可读性,所以我将three.js代码单独抽离放在一个组件当中,在App根组件中进入引入该组件。具体如下:

<template>
  <!-- 汽车展览 -->
  <autoShow></autoShow>
</template>

<script setup>
import autoShow from './components/autoShow.vue';
</script>

<style lang="less">
  *{
    margin: 0;
    padding: 0;
  }
</style>

初始化three.js基础代码

three.js开启必须用到的基础代码如下:

导入three库

import * as THREE from 'three'

初始化场景

const scene = new THREE.Scene()

初始化相机

const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000)
camera.position.set(0,2,6)

初始化渲染器

const renderer = new THREE.WebGLRenderer({
  antialias: true // 设置抗锯齿
})
renderer.setSize(window.innerWidth,window.innerHeight)

监听屏幕大小的改变,修改渲染器的宽高和相机的比例

window.addEventListener("resize",()=>{ 
  renderer.setSize(window.innerWidth,window.innerHeight)
  camera.aspect = window.innerWidth/window.innerHeight
  camera.updateProjectionMatrix()
})

导入控制器

import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"
// 实例化控制器
const controls = new OrbitControls(camera,renderer.domElement)

设置渲染函数

const render = () =>{ 
  renderer.render(scene,camera) // 渲染场景
  requestAnimationFrame(render) // 循环渲染
}

进行挂载

在html代码处创建一个div,然后通过ref获取其dom元素,在页面刚挂载的时候将渲染器插入到dom当中去,如下:

onMounted(()=>{
  // 添加控制器
  const controls = new OrbitControls(camera,canvas.value)
  controls.enableDamping = true 
  canvas.value.appendChild(renderer.domElement) // 将渲染器插入到dom中
  // 初始化渲染器,渲染背景
  scene.background = new THREE.Color("#ccc")
  scene.environment = new THREE.Color("#ccc")
  render()
})

添加汽车模型展示

在添加汽车模型之前,我们可以先创建一个网格地面,然后让汽车模型更具有立体效果:

// 添加网格地面
const gridHelper = new THREE.GridHelper(10,10)
gridHelper.material.opacity = 0.2
gridHelper.material.transparent = true
scene.add(gridHelper)

接下来就可以添加汽车模型,让汽车模型在网格地面上展示,如下:

// 先导入加载gltf模型和压缩模型的库
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";

// 添加gltf汽车模型
const loader = new GLTFLoader()
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath("/draco/")
loader.setDRACOLoader(dracoLoader)
loader.load("src/assets/model/bmw01.glb",(gltf)=>{
  scene.add(gltf.scene)
})

因为汽车展览的话,推荐平行光更具有立体效果,不建议直接使用环境光:

// 添加灯光
const light1 = new THREE.DirectionalLight(0xffffff, 0.7);
light1.position.set(0, 0, 10);
scene.add(light1);
const light2 = new THREE.DirectionalLight(0xffffff, 0.7);
light2.position.set(0, 0, -10);
scene.add(light2);
const light3 = new THREE.DirectionalLight(0xffffff, 0.7);
light3.position.set(10, 0, 0);
scene.add(light3);
const light4 = new THREE.DirectionalLight(0xffffff, 0.7);
light4.position.set(-10, 0, 0);
scene.add(light4);
const light5 = new THREE.DirectionalLight(0xffffff, 0.7);
light5.position.set(0, 10, 0);
scene.add(light5);
const light6 = new THREE.DirectionalLight(0xffffff, 0.3);
light6.position.set(5, 10, 0);
scene.add(light6);
const light7 = new THREE.DirectionalLight(0xffffff, 0.3);
light7.position.set(0, 10, 5);
scene.add(light7);
const light8 = new THREE.DirectionalLight(0xffffff, 0.3);
light8.position.set(0, 10, -5);
scene.add(light8);
const light9 = new THREE.DirectionalLight(0xffffff, 0.3);
light9.position.set(-5, 10, 0);
scene.add(light9);

动态修改汽车模型

因为3d建模生成的gltf模型会给我们标记好名字,所以我们只需要找到并拿来使用即可,如下:

如果想动态修改数据的话,可以借助一个gui库,关于gui库的讲解可以参看我之前讲解的文章:Gui.js库的使用讲解 ,在这里就不再赘述,这里我们为每一个汽车模型部位都创建一个物理材质然后进行动态的修改:

将动态修改材质的数据添加到汽车模型材质上去,这里我用switch动态的去判断各种情况,如下:

大体的思路就是上面了,ok可以简单看一下最后呈现的效果是啥,如下:

demo做完,给出本案例的完整代码:(获取素材也可以私信博主)

<template>
  <div class="home">
    <div class="canvas-container" ref="canvas"></div>
  </div>
</template>

<script setup>
import * as THREE from "three"
import { onMounted,ref } from "vue";
// 添加轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
// 引入gui.js库
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js'
// 实例化一个gui对象
const gui = new GUI()

let canvas = ref(null)

// 创建场景
const scene = new THREE.Scene()
// 创建相机
const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000)
camera.position.set(0,2,6)
// 创建渲染器
const renderer = new THREE.WebGLRenderer({
  antialias: true // 设置抗锯齿
})
renderer.setSize(window.innerWidth,window.innerHeight)

// 设置渲染函数
const render = () =>{ 
  renderer.render(scene,camera)
  requestAnimationFrame(render)
}

// 监听页面变化
window.addEventListener("resize",()=>{ 
  renderer.setSize(window.innerWidth,window.innerHeight)
  camera.aspect = window.innerWidth/window.innerHeight
  camera.updateProjectionMatrix()
})

onMounted(()=>{
  // 添加控制器
  const controls = new OrbitControls(camera,canvas.value)
  controls.enableDamping = true 
  canvas.value.appendChild(renderer.domElement) // 将渲染器插入到dom中
  // 初始化渲染器,渲染背景
  scene.background = new THREE.Color("#ccc")
  scene.environment = new THREE.Color("#ccc")
  render()
})

// 添加网格地面
const gridHelper = new THREE.GridHelper(10,10)
gridHelper.material.opacity = 0.2
gridHelper.material.transparent = true
scene.add(gridHelper)

// 设置汽车模型部件的名称
let wheels = [] // 汽车轮毂
let carBody,frontCar,hoodCar,glassCar // 汽车车身、汽车前列、汽车引擎、汽车挡风玻璃

// 创建轮毂材质
const wheelsMaterial = new THREE.MeshPhysicalMaterial({
  color: 0xff0000,
  metalness: 1,
  roughness: 0.1,
});
const wheelsChange = gui.addFolder("轮毂设置")
wheelsChange.close() // 默认关闭状态
wheelsChange.addColor(wheelsMaterial,'color').name('前轮毂颜色').onChange(value=>{
  wheelsMaterial.color.set(value)
})
wheelsChange.add(wheelsMaterial,'metalness',0,1).name('金属度').onChange(value=>{
  wheelsMaterial.metalness = value
})
wheelsChange.add(wheelsMaterial,'roughness',0,1).name('粗糙度').onChange(value=>{
  wheelsMaterial.roughness = value
})
// 创建右后轮毂材质
const wheelsRightMaterial = new THREE.MeshPhysicalMaterial({
  color: 0xff0000,
  metalness: 1,
  roughness: 0.1,
});
const wheelsRightChange = wheelsChange.addFolder("右后轮毂设置")
wheelsRightChange.close() // 默认关闭状态
wheelsRightChange.addColor(wheelsRightMaterial,'color').name('右后轮毂颜色').onChange(value=>{
  wheelsRightMaterial.color.set(value)
})
wheelsRightChange.add(wheelsRightMaterial,'metalness',0,1).name('金属度').onChange(value=>{
  wheelsRightMaterial.metalness = value
})
wheelsRightChange.add(wheelsRightMaterial,'roughness',0,1).name('粗糙度').onChange(value=>{
  wheelsRightMaterial.roughness = value
})
// 创建轮毂材质
const wheelsLeftMaterial = new THREE.MeshPhysicalMaterial({
  color: 0xff0000,
  metalness: 1,
  roughness: 0.1,
});
const wheelsLeftChange = wheelsChange.addFolder("左后轮毂设置")
wheelsLeftChange.close() // 默认关闭状态
wheelsLeftChange.addColor(wheelsLeftMaterial,'color').name('左后轮毂颜色').onChange(value=>{
  wheelsLeftMaterial.color.set(value)
})
wheelsLeftChange.add(wheelsLeftMaterial,'metalness',0,1).name('金属度').onChange(value=>{
  wheelsLeftMaterial.metalness = value
})
wheelsLeftChange.add(wheelsLeftMaterial,'roughness',0,1).name('粗糙度').onChange(value=>{
  wheelsLeftMaterial.roughness = value
})

// 创建车身材质
const bodyMaterial = new THREE.MeshPhysicalMaterial({
  color: 0xff0000,
  metalness: 1,
  roughness: 0.5,
  clearcoat: 1,
  clearcoatRoughness: 0,
})
const carBodyChange = gui.addFolder("车身设置")
carBodyChange.close() // 默认关闭状态
carBodyChange.addColor(bodyMaterial,'color').name('车身颜色').onChange(value=>{
  bodyMaterial.color.set(value)
})
carBodyChange.add(bodyMaterial,'metalness',0,1).name('金属度').onChange(value=>{
  bodyMaterial.metalness = value
})
carBodyChange.add(bodyMaterial,'roughness',0,1).name('粗糙度').onChange(value=>{
  bodyMaterial.roughness = value
})
carBodyChange.add(bodyMaterial,'clearcoat',0,1).name('清漆').onChange(value=>{
  bodyMaterial.clearcoat = value
})
carBodyChange.add(bodyMaterial,'clearcoatRoughness',0,1).name('清漆粗糙度').onChange(value=>{
  bodyMaterial.clearcoatRoughness = value
})

// 创建车前列材质
const frontMaterial = new THREE.MeshPhysicalMaterial({
  color: 0xff0000,
  metalness: 1,
  roughness: 0.5,
  clearcoat: 1,
  clearcoatRoughness: 0,
})
const frontCarChange = gui.addFolder("车前身设置")
frontCarChange.close() // 默认关闭状态
frontCarChange.addColor(frontMaterial,'color').name('车前身颜色').onChange(value=>{
  frontMaterial.color.set(value)
})
frontCarChange.add(frontMaterial,'metalness',0,1).name('金属度').onChange(value=>{
  frontMaterial.metalness = value
})
frontCarChange.add(frontMaterial,'roughness',0,1).name('粗糙度').onChange(value=>{
  frontMaterial.roughness = value
})
frontCarChange.add(frontMaterial,'clearcoat',0,1).name('清漆').onChange(value=>{
  frontMaterial.clearcoat = value
})
frontCarChange.add(frontMaterial,'clearcoatRoughness',0,1).name('清漆粗糙度').onChange(value=>{
  frontMaterial.clearcoatRoughness = value
})

// 创建汽车引擎材质
const hoodMaterial = new THREE.MeshPhysicalMaterial({
  color: 0xff0000,
  metalness: 1,
  roughness: 0.5,
  clearcoat: 1,
  clearcoatRoughness: 0,
});
const hoodCarChange = gui.addFolder("汽车引擎设置")
hoodCarChange.close() // 默认关闭状态
hoodCarChange.addColor(hoodMaterial,'color').name('汽车引擎颜色').onChange(value=>{
  hoodMaterial.color.set(value)
})
hoodCarChange.add(hoodMaterial,'metalness',0,1).name('金属度').onChange(value=>{
  hoodMaterial.metalness = value
})
hoodCarChange.add(hoodMaterial,'roughness',0,1).name('粗糙度').onChange(value=>{
  hoodMaterial.roughness = value
})
hoodCarChange.add(hoodMaterial,'clearcoat',0,1).name('清漆').onChange(value=>{
  hoodMaterial.clearcoat = value
})
hoodCarChange.add(hoodMaterial,'clearcoatRoughness',0,1).name('清漆粗糙度').onChange(value=>{
  hoodMaterial.clearcoatRoughness = value
})

// 创建汽车挡风玻璃材质
const glassMaterial = new THREE.MeshPhysicalMaterial({
  color: 0xffffff,
  metalness: 0,
  roughness: 0,
  transmission: 1,
  transparent: true,
});
const glassCarChange = gui.addFolder("汽车挡风玻璃设置")
glassCarChange.close() // 默认关闭状态
glassCarChange.addColor(glassMaterial,'color').name('汽车挡风玻璃颜色').onChange(value=>{
  glassMaterial.color.set(value)
})
glassCarChange.add(glassMaterial,'metalness',0,1).name('金属度').onChange(value=>{
  glassMaterial.metalness = value
})
glassCarChange.add(glassMaterial,'roughness',0,1).name('粗糙度').onChange(value=>{
  glassMaterial.roughness = value
})
glassCarChange.add(glassMaterial,'transmission',0,1).name('透射值').onChange(value=>{
  glassMaterial.transmission = value
})
glassCarChange.add(glassMaterial,'transparent',0,1).name('是否透明').onChange(value=>{
  glassMaterial.transparent = value
})

// 添加gltf汽车模型
const loader = new GLTFLoader()
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath("/draco/")
loader.setDRACOLoader(dracoLoader)
loader.load("src/assets/model/bmw01.glb",(gltf)=>{
  // traverse函数是一种用于遍历Object3D及其子对象的函数,可以访问场景中所有的Object3D类型对象(包括Mesh、Group、Object等)
  gltf.scene.traverse((child)=>{
    switch(child.isMesh){
      // 判断是否为轮毂
      case child.name.includes("轮毂"):
        wheels.push(child)
        wheels[0].material = wheelsMaterial
        if(wheels.length === 3){
          wheels[1].material = wheelsRightMaterial
          wheels[2].material = wheelsLeftMaterial
        }
        break
      // 判断是否为车身
      case child.name.includes("Mesh002"):
        carBody = child
        carBody.material = bodyMaterial
        break
      // 判断是否是车前列
      case child.name.includes("前脸"):
        frontCar = child
        frontCar.material = frontMaterial
        break
      // 判断是否为引擎盖
      case child.name.includes("引擎盖_1"):
        hoodCar = child
        hoodCar.material = hoodMaterial
        break
      // 判断是否为挡风玻璃
      case child.name.includes("挡风玻璃"):
        glassCar = child
        glassCar.material = glassMaterial
        break
      default:
        return 
    }
  })
  scene.add(gltf.scene)
})

// 添加灯光
const light1 = new THREE.DirectionalLight(0xffffff, 0.7);
light1.position.set(0, 0, 10);
scene.add(light1);
const light2 = new THREE.DirectionalLight(0xffffff, 0.7);
light2.position.set(0, 0, -10);
scene.add(light2);
const light3 = new THREE.DirectionalLight(0xffffff, 0.7);
light3.position.set(10, 0, 0);
scene.add(light3);
const light4 = new THREE.DirectionalLight(0xffffff, 0.7);
light4.position.set(-10, 0, 0);
scene.add(light4);
const light5 = new THREE.DirectionalLight(0xffffff, 0.7);
light5.position.set(0, 10, 0);
scene.add(light5);
const light6 = new THREE.DirectionalLight(0xffffff, 0.3);
light6.position.set(5, 10, 0);
scene.add(light6);
const light7 = new THREE.DirectionalLight(0xffffff, 0.3);
light7.position.set(0, 10, 5);
scene.add(light7);
const light8 = new THREE.DirectionalLight(0xffffff, 0.3);
light8.position.set(0, 10, -5);
scene.add(light8);
const light9 = new THREE.DirectionalLight(0xffffff, 0.3);
light9.position.set(-5, 10, 0);
scene.add(light9);
</script>

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

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

相关文章

makefile make 的隐式规则

文章目录 前言一、什么是隐式规则?二、典型隐式规则情况三、查看隐式规则四、隐式规则的禁用五、隐式规则的副作用总结 前言 一、什么是隐式规则? make 提供了一些常用的&#xff0c;例行的规则实现。 当相应的规则未提供时 &#xff0c; make 尝试使用隐式规则。 make 提供…

KDZK-F水轮发电机转子测试仪

一、产品概述 KDZK-F水轮发电机转子测试仪是判断发电机转子绕组有无匝间短路的专用仪器&#xff0c;可以自动、手动&#xff08;单向或双向&#xff09;测量转子绕组的电压、电流、阻抗、功率、相位角等参数。 二、功能与特点 旋转鼠标&#xff0c;操作更方便。 可选择快速的…

手写操作系统必掌握基础:函数调用约定

哈喽&#xff0c;我是子牙&#xff0c;一个很卷的硬核男人。深入研究Windows内核、Linux内核、Hotspot源码…聚焦做那些大家想学没地方学的课程&#xff1a;手写操作系统、手写虚拟机、手写模拟器、手写编程语言… 目前我已经做了两个成熟的课程&#xff1a;手写JVM、手写OS&a…

RTX4060 系 2399 元起,NVIDIA 又赢麻了

就在上周&#xff0c;NVIDIA 正式官宣了 RTX40 系显卡家族中更加主流的三款新品。 分别是 RTX 4060、RTX 4060 Ti 8G 以及 RTX 4060 Ti 16G。 其中 RTX 4060 Ti 8G 解禁时间为本月 23 日晚&#xff0c;24 日上架开售。 而 RTX 4060、RTX 4060 Ti 16G 要等到七月份。 价格部分…

2023年湖北建筑架子工报名流程?报名需要什么资料?考试一次过?

2023年湖北建筑架子工报名流程&#xff1f;报名需要什么资料&#xff1f;考试一次过&#xff1f; 建筑架子工证是建筑行业必备的证书之一&#xff0c;它是证明持有人可以在建筑工地上从事搭建脚手架、模板等施工工作的重要证明。启程别告诉你架子工的报名流程和资料。 百度搜一…

测试提效1-电商一键创单的实现

因电商项目不同场景下单特别多&#xff0c;而走前端流程特别慢。所以在某些测试场景需要特定配送方式 和 特定配送状态数据&#xff0c;本次实现快速创建。 1、前端页面 前端页面采用vue &#xff0c;页面需要的属性或字段&#xff0c;打算包括 环境env、店铺(准备了3种不同模…

一种新的爬虫网络解锁器

事出原由 遇到一个需要采集境外电商的需求&#xff0c;相比国内各种层出不穷的反爬手段&#xff0c;境外产品更注重于用户行为和指纹上。 所以笔者在想是否有类似于指纹浏览器的环境可以提供给爬虫采集器使用。 经过检索&#xff0c;找到了一种名为爬虫网络解锁器的新兴产品…

SAP: 建立HTTPS 连接时,报错 ICM_HTTP_SSL_PEER_CERT_UNTRUSTED

报错1&#xff1a; SSL handshake with tpm-uat.jlbry.cn:443 failed: SSSLERR_PEER_CERT_UNTRUSTED (-102)#The peers X.509 Certificate (chain) is untrusted##SapSSLSessionStartNB()SSSLERR_PEER_CERT_UNTRUSTED# SSL:SSL_read() failed (536872221/0x2000051d)# >…

【正点原子STM32连载】第十四章 蜂鸣器实验 摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第十四…

【无标题】ELISA-3(加装跟踪装置)—让群体协作更智能!

群体智能是近年来发展迅速的一个人工智能学科领域&#xff0c;通过对蚂蚁、蜜蜂等为代表的社会性昆虫群体行为的研究&#xff0c;实现分布式等智能行为。作为新一代人工智能的重要方向&#xff0c;群体智能通常用于无人机、机器人集群的协同作业。目前&#xff0c;群体智能在基…

零操作难度,轻松进行应用测试,App专项测试之Monkey测试完全指南!

目录 前言&#xff1a; 一、 Monkey测试的基础参数 1.1 事件类型参数&#xff1a; 1.2 覆盖包 1.3 事件数量 二、 Monkey测试的高级参数 2.1 稳定性级别 2.2 策略参数 2.3 包含选项参数 三、 附加代码 四、 总结 前言&#xff1a; 在移动应用的开发过程中&#xff0…

数据结构(C语言):有序顺序表的设计及相关操作函数

一、题目 有序顺序表的设计 实验要求&#xff1a; 有序顺序表的操作&#xff0c;包括初始化&#xff0c;求数据元素个数&#xff0c;插入&#xff0c;删除和取数据元素。放在头文件中&#xff08;建议尝试用动态数组实现有序顺序表&#xff09;&#xff1b;注意有序顺序表的…

【正点原子STM32连载】 第十七章 串口通信实验摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第十七…

2023年25个Java8面试问题和答案

Java是一种非常流行的编程语言&#xff0c;从Android应用程序到物联网&#xff08;IoT&#xff09;无处不在。事实上&#xff0c;根据Codeplatoon的数据&#xff0c;Java在1年的招聘信息中排名#2022。考虑到它的普遍存在&#xff0c;对精通Java的专业人员的需求仍然很高也就不足…

【vlan高级特性——super vlan概述】

今天给大家分享Windows常用cmd网络命令&#xff0c;希望对大家能有所帮助&#xff01; 1、arp [option] [address] 显示/修改ARP缓存 执行命令&#xff1a;arp -a 参数说明&#xff1a; 显示和修改地址解析协议(ARP)使用的“IP 到物理”地址转换表。 ARP -s inet_addr eth…

那些30多岁的测试工程师都是怎么走过来的?

最近工作真的不好找了&#xff0c;感觉身边的朋友明显变得焦虑了&#xff0c;一个个都在抱怨生活的迷茫和疑惑。 30岁测试员该何去何从&#xff1f; 如今我们往往能够看到网上的各种新闻&#xff0c;什么“30岁是程序员的一道坎“ “非诚勿扰:32岁 程序员登台&#xff0c;遭美…

【Java-Crawler】爬取动态页面(WebMagic、Selenium、ChromeDriver)

WebMagicSeleniumChromeDriverMaven 爬取动态页面 一、需要下载的资源和引入的依赖资源依赖 二、实战代码测试效果 在上一篇说WebMagic框架的时候&#xff08; 一文学会WebMagic爬虫框架&#xff09;&#xff0c;提到了WebMagic仅能解析静态页面&#xff0c;满足不了小编的爬虫…

chatgpt赋能Python-python_numpy转置

Python中的Numpy转置&#xff1a;使用transpose()函数 在Python中&#xff0c;Numpy是非常常用的一个科学计算库&#xff0c;它提供了大量的数学函数、矩阵计算等功能。其中&#xff0c;矩阵的转置是一个非常基本的运算&#xff0c;在Numpy中&#xff0c;我们可以使用transpos…

SSRS rdlc报表 六 报表分组和总计

报表分组和总计在报表中是一个很常用的功能&#xff0c;比如我们需要按部门进行分组&#xff0c;统计每个部门的费用支出&#xff0c;或者在进一步分组&#xff0c;每个部门每个月的费用支出&#xff0c;通过rdlc报表&#xff0c;很容易实现这个需求。 我们下面要讲解的案例&a…

Thinkphp漏洞详解合集

文章目录 Thinkphp6.0.12LTS反序列化漏洞环境漏洞分析 thinkphp lang命令执行环境影响版本漏洞分析漏洞复现 CNVD-2018-24942(t5RCE)环境影响版本漏洞分析漏洞复现 Thinkphp3.2.x命令执行环境漏洞分析漏洞复现 thinkphp-2x-rce漏洞环境影响版本漏洞分析 Thinkphp5.0.23变量覆盖…