ThreeJS-3D教学二:基础形状展示

news2024/11/17 10:35:49

three中提供了22 个基础模型,此案例除了 EdgesGeometry、ExtrudeGeometry、TextGeometry、WireframeGeometry,涵盖 17 个形状。

 Fog  雾化设置,这是scene场景效果
 
 EdgesGeometry , WireframeGeometry 更多地可能作为辅助功能去查看几何体的边和线框
 
 ExtrudeGeometry 则是将一个二维图形沿 z 轴拉伸出一个三维图形
 
 TextGeometry 则需要从外部加载特定格式的字体文件(可在 typeface.js_three 网站上进行转换)进行渲染,其内部依然使用 ExtrudeGeometry 对字体进行拉伸,从而形成三维字体。另外,该类字体的本质是一系列类似SVG 的指令。所以,字体越简单(如直线越多),就越容易被正确渲染。

 planeGeometry  底层
  
 BoxGeometry(长方体)
 
 CircleGeometry(圆形)
 
 ConeGeometry(圆锥体)
 
 CylinderGeometry(圆柱体)
 
 DodecahedronGeometry(十二面体)
 
 IcosahedronGeometry(二十面体)

 LatheGeometry(让任意曲线绕 y 轴旋转生成一个形状,如花瓶)
 
 OctahedronGeometry(八面体)

 ParametricGeometry(根据参数生成形状)
 
 PolyhedronGeometry(多面体)

 RingGeometry(环形)
 
 ShapeGeometry(二维形状)

 SphereGeometry(球体)

 TetrahedronGeometry(四面体)
 
 TorusGeometry(圆环体)
 
 TorusKnotGeometry(换面纽结体)
 
 TubeGeometry(管道)

我们先看下效果图
在这里插入图片描述
看代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    body {
      width: 100%;
      height: 100%;
    }
    * {
      margin: 0;
      padding: 0;
    }
    .label {
      font-size: 20px;
      color: #000;
      font-weight: 700;
    }
  </style>
</head>
<body>
<div id="container"></div>
<script type="importmap">
  {
    "imports": {
      "three": "../three-155/build/three.module.js",
      "three/addons/": "../three-155/examples/jsm/"
    }
  }
</script>
<script type="module">
import * as THREE from 'three';
import Stats from 'three/addons/libs/stats.module.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GPUStatsPanel } from 'three/addons/utils/GPUStatsPanel.js';
import { CSS2DRenderer, CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
import { createMultiMaterialObject } from 'three/addons/utils/SceneUtils.js';
import { ParametricGeometry } from 'three/addons/geometries/ParametricGeometry.js';
import { ParametricGeometries } from 'three/addons/geometries/ParametricGeometries.js';
let stats, labelRenderer, gpuPanel;
let camera, scene, renderer, mesh, target, controls, meshs = [];
const group = new THREE.Group();
/**
 在 Three.js 中可以渲染着色器的材质有两种:RawShaderMaterial 和 ShaderMaterial,
 它们之间的区别是 ShaderMaterial 会自动将一些初始化着色器的参数添加到代码中(内置 attributes 和 uniforms),
 而 RawShaderMaterial 则什么都不会添加。
 */
init();
initHelp();
initLight();
axesHelperWord();
animate();

meshs = addGeometries();
addPlane();

function addPlane() {
  // 创建一个平面 PlaneGeometry(width, height, widthSegments, heightSegments)
  const planeGeometry = new THREE.PlaneGeometry(120, 140, 1, 1);
  // 创建 Lambert 材质:会对场景中的光源作出反应,但表现为暗淡,而不光亮。
  const planeMaterial = new THREE.MeshLambertMaterial({
    color: 0xffffff
  });
  const plane = new THREE.Mesh(planeGeometry, planeMaterial);
  // 以自身中心为旋转轴,绕 x 轴顺时针旋转 45 度
  plane.rotation.x = -0.5 * Math.PI;
  plane.position.set(0, -4, 0);
  scene.add(plane);
}

function addGeometries() {
  const geoms = [];
  const meshs = [];
  // 共 22 个形状,除了 EdgesGeometry、ExtrudeGeometry、TextGeometry、WireframeGeometry,下面涵盖 17 个(PlaneGeometry在上面)
  // Box 长方体
  geoms.push(new THREE.BoxGeometry(8, 8, 8));

  // Circle 圆形
  geoms.push(new THREE.CircleGeometry(8, 32));

  // Cone 圆锥体
  geoms.push(new THREE.ConeGeometry(8, 20, 32));

  // Cylinder 圆柱体
  geoms.push(new THREE.CylinderGeometry(5, 5, 20, 32));

  // Dodecahedron 十二面体
  geoms.push(new THREE.DodecahedronGeometry(8));

  // Icosahedron 二十面体
  geoms.push(new THREE.IcosahedronGeometry(8));

  // Lathe 让任意曲线绕 y 轴旋转生成一个形状,如花瓶
  const lathePoints = [];
  for (let i = 0; i < 10; i++) {
    lathePoints.push(new THREE.Vector2(Math.sin(i * 0.2) * 5 + 2.5, (i - 5) * 2));
  }
  geoms.push(new THREE.LatheGeometry(lathePoints));

  // Octahedron 八面体
  geoms.push(new THREE.OctahedronGeometry(8));

  // Parametric:根据参数生成形状,THREE.ParametricGeometries.klein 是 ParametricGeometries.js_three 库提供
  geoms.push(new ParametricGeometry(ParametricGeometries.klein, 10, 10));

  const verticesOfCube = [
    -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1,
    -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1,
  ];

  const indicesOfFaces = [
    2, 1, 0, 0, 3, 2,
    0, 4, 7, 7, 3, 0,
    0, 1, 5, 5, 4, 0,
    1, 2, 6, 6, 5, 1,
    2, 3, 7, 7, 6, 2,
    4, 5, 6, 6, 7, 4
  ];

  // Polyhedron 多面体
  geoms.push(new THREE.PolyhedronGeometry(verticesOfCube, indicesOfFaces, 8, 1));

  // Ring 环形
  geoms.push(new THREE.RingGeometry(3, 8, 16));

  // Shape 二维形状(心形)
  let x = 0, y = 0;
  let heartShape = new THREE.Shape();

  heartShape.moveTo(x + 5, y + 5);
  heartShape.bezierCurveTo(x + 5, y + 5, x + 4, y, x, y);
  heartShape.bezierCurveTo(x - 6, y, x - 6, y + 7, x - 6, y + 7);
  heartShape.bezierCurveTo(x - 6, y + 11, x - 3, y + 15.4, x + 5, y + 19);
  heartShape.bezierCurveTo(x + 12, y + 15.4, x + 16, y + 11, x + 16, y + 7);
  heartShape.bezierCurveTo(x + 16, y + 7, x + 16, y, x + 10, y);
  heartShape.bezierCurveTo(x + 7, y, x + 5, y + 5, x + 5, y + 5);

  geoms.push(new THREE.ShapeGeometry(heartShape));

  // Sphere 球体
  geoms.push(new THREE.SphereGeometry(8, 24, 24));

  // Tetrahedron 四面体
  geoms.push(new THREE.TetrahedronGeometry(8));

  // Torus 圆环体
  geoms.push(new THREE.TorusGeometry(6, 2, 16, 100));

  // TorusKnot 环面纽结体
  geoms.push(new THREE.TorusKnotGeometry(6, 2, 100, 16));

  // Tube 管道
  const points = [];
  for (let i = 0; i < 5; i++) {
    const randomX = -10 + Math.round(Math.random() * 20);
    const randomY = -7 + Math.round(Math.random() * 20);
    const randomZ = -10 + Math.round(Math.random() * 20);
    points.push(new THREE.Vector3(randomX, randomY, randomZ));
  }

  geoms.push(new THREE.TubeGeometry(new THREE.CatmullRomCurve3(points), 20, 2, 8, false));
  let j = 0;
  // 为几何体添加材质
  for (let i = 0; i < geoms.length; i++) {
    let materials = [
      // 内侧
      new THREE.MeshLambertMaterial({
        color: Math.random() * 0xffffff,
        flatShading: true, // 定义是否使用平面着色渲染材质
        side: THREE.DoubleSide,
        wireframe: true // 将几何体渲染为线框。默认值为false(即渲染为平面多边形)
      }),
      // 外侧
      new THREE.MeshBasicMaterial({
        color: Math.random() * 0xffffff,
        wireframe: false
      })
    ];

    let mesh = createMultiMaterialObject(geoms[i], materials);

    meshs.push(mesh);

    // 设置每个物体的位置
    mesh.position.x = -36 + ((i % 4) * 24);
    mesh.position.y = 4;
    mesh.position.z = -36 + (j * 24);

    if ((i + 1) % 4 == 0) {
      j++
    }
    scene.add(mesh)
  }
  return meshs
}

function init() {

  camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 10, 2000 );
  camera.position.set(0, 125, 125);
  camera.up.set(0, 1, 0);
  camera.lookAt(0, 0, 0);

  scene = new THREE.Scene();
  scene.background = new THREE.Color( '#ccc' );

  // Fog( hex, near, far ),线性雾化。
  // near 表示哪里开始应用雾化效果
  // far 表示雾化效果在哪里结束
  scene.fog = new THREE.Fog(0xffffff, 0.015, 100);
  // FogExp2( hex, density ),指数雾化
  // density 是雾化强度
  scene.fog = new THREE.FogExp2(0xffffff, 0.005); //0.01 雾化就很重了
  // 雾化效果默认是全局影响的,若某个材质不受雾化效果影响,则可为材质的 fog 属性设置为 false(默认值 true)
  // var material = new THREE.Material({
  //   fog: false
  // });

  renderer = new THREE.WebGLRenderer( { antialias: true } );
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize( window.innerWidth, window.innerHeight );
  document.body.appendChild( renderer.domElement );

  labelRenderer = new CSS2DRenderer();
  labelRenderer.setSize( window.innerWidth, window.innerHeight );
  labelRenderer.domElement.style.position = 'absolute';
  labelRenderer.domElement.style.top = '0px';
  labelRenderer.domElement.style.pointerEvents = 'none';
  document.getElementById( 'container' ).appendChild( labelRenderer.domElement );

  window.addEventListener( 'resize', onWindowResize );

  controls = new OrbitControls( camera, renderer.domElement );
  controls.minDistance = 10;
  controls.maxDistance = 1000;
  // 设置为true可启用阻尼(惯性),可用于为控件提供重量感。默认值为false。
  // 请注意,如果启用了此选项,则必须在动画循环中调用.update()。
  controls.enableDamping = false;
  controls.screenSpacePanning = false; // 定义平移时如何平移相机的位置 控制不上下移动

  stats = new Stats();
  stats.setMode(1); // 0: fps, 1: ms
  document.body.appendChild( stats.dom );

  gpuPanel = new GPUStatsPanel( renderer.getContext() );
  stats.addPanel( gpuPanel );
  stats.showPanel( 0 );

  scene.add( group );
}

function initLight() {
  const light = new THREE.DirectionalLight(new THREE.Color('rgb(253,253,253)'));
  light.position.set(100, 100, -10);
  light.intensity = 3; // 光线强度
  light.castShadow = true; // 是否有阴影
  light.shadow.mapSize.width = 2048; // 阴影像素
  light.shadow.mapSize.height = 2048;
  // 阴影范围
  const d = 80;
  light.shadow.camera.left = -d;
  light.shadow.camera.right = d;
  light.shadow.camera.top = d;
  light.shadow.camera.bottom = -d;
  light.shadow.bias = -0.0005; // 解决条纹阴影的出现
  // 最大可视距和最小可视距
  light.shadow.camera.near = 0.01;
  light.shadow.camera.far = 2000;
  const AmbientLight = new THREE.AmbientLight(new THREE.Color('rgb(255, 255, 255)'));
  scene.add( light );
  scene.add( AmbientLight );
}

function initHelp() {
  // const size = 100;
  // const divisions = 5;
  // const gridHelper = new THREE.GridHelper( size, divisions );
  // scene.add( gridHelper );

  // The X axis is red. The Y axis is green. The Z axis is blue.
  const axesHelper = new THREE.AxesHelper( 100 );
  scene.add( axesHelper );
}

function axesHelperWord() {
  let xP = addWord('X轴');
  let yP = addWord('Y轴');
  let zP = addWord('Z轴');
  xP.position.set(50, 0, 0);
  yP.position.set(0, 50, 0);
  zP.position.set(0, 0, 50);
}

function addWord(word) {
  let name = `<span>${word}</span>`;
  let moonDiv = document.createElement( 'div' );
  moonDiv.className = 'label';
  // moonDiv.textContent = 'Moon';
  // moonDiv.style.marginTop = '-1em';
  moonDiv.innerHTML = name;
  const label = new CSS2DObject( moonDiv );
  group.add( label );
  return label;
}

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize( window.innerWidth, window.innerHeight );
}

function animate() {
  requestAnimationFrame( animate );

  // 各个网格(mesh)绕自身中心的 y 轴自转
  if (meshs.length > 0) {
    for (let i = 0; i < meshs.length; i++) {
      meshs[i].rotation.y += 0.01;
    }
  }

  stats.update();
  controls.update();
  labelRenderer.render( scene, camera );
  renderer.render( scene, camera );
}
</script>
</body>
</html>

直接复制粘贴到html文件即可看到效果,当然前提是已经提前下载了three的代码库,然后在script type="importmap"标签中改下路径就可以了。
到这一步,我们开始往场景 scene 中添加模型,也就是mesh,案例中用到了 SceneUtils.js 中的createMultiMaterialObject 创建 mesh,这个在官网中用法是这样的:
在这里插入图片描述
我们发现按官网看调用应该是SceneUtils.createMultiMaterialObject,但是这样会报错,我们看three 155版本中发现源码为:
在这里插入图片描述
看来新的版本已经更简洁了直接使用createMultiMaterialObject即可
从这个解错的过程中,我们可以总结一些规律,当我们发现有时官网提供的方法也会报错,解错思路是什么呢?
1、百度查问题,事实我也是这么做的,但由于这是最新版本,查询的结果大家也是推荐的官网用法,一通折腾没结果,这也是使用最新版本可能出现的一些无法预知的问题
2、这时大家可以调转思路,为什么不看一眼源码,虽然大部分源码晦涩难懂,多层嵌套,比较难发现问题,本身我也不喜欢读源码,但结果是看完源码几秒钟这个问题就解决了,所以当我们遇到问题,第一步不一定要百度,看一眼源码也是很好的

因为要写案例,在这个过程中遇到了一些问题,我就把解决问题的思路写下来分享给大家,我想这远比教会大家怎么实现效果更有助于大家成长。

回到主题我们在讲createMultiMaterialObject做了什么时,先看下一般情况下mesh是怎么做的,在代码中有一个addPlane函数:

  // 创建一个平面  PlaneGeometry(width, height, widthSegments, heightSegments)
  const planeGeometry = new THREE.PlaneGeometry(120, 140, 1, 1);
  // 创建 Lambert 材质:会对场景中的光源作出反应,但表现为暗淡,而不光亮。
  const planeMaterial = new THREE.MeshLambertMaterial({
    color: 0xffffff
  });
  // 这里new THREE.Mesh 大部分情况我们都是这样做的
  const plane = new THREE.Mesh(planeGeometry, planeMaterial);
  // 以自身中心为旋转轴,绕 x 轴顺时针旋转 45 度
  plane.rotation.x = -0.5 * Math.PI;
  plane.position.set(0, -4, 0);
  scene.add(plane);

Mesh

表示基于三角形多边形网格的对象的类。还可以作为其他类(如SkinnedMesh)的基础。

很显然PlaneGeometry 和 MeshLambertMaterial大家可能是第一次见到

Geometry

对原生WebGL中的顶点位置position、顶点法向量normal、顶点颜色color、顶点纹理坐标uv、顶点索引index等顶点数据进行了封装
立方体BoxGeometry、圆柱体CylinderGeometry、球体SphereGeometry等Three.js几何体类都是基于基类BufferGeometry二次封装

Materials

材质就像对象的蒙皮。它定义了几何图形的外观。Three.js提供了许多工作材料。我们应该根据我们的需要选择材料的类型。

Three.js中最常用的材料:

1、MeshBasicMateria
Three.js中非常基本的材料

2、MeshDepthMaterial
它使用与摄影机的距离来确定如何以灰度为网格着色

3、MeshNormalMaterial
此材质使用面法线向量的x/y/z值的大小来计算和设置面上显示的颜色的红/绿/蓝值

4、MeshLambertMaterial
您可以使用此材质创建外观暗淡、无光泽的表面

5、MeshPhongMaterial
此材质类似于MeshLambertMaterial,但可以创建更有光泽的曲面

6、MeshStandardMaterial
它与MeshLambertMaterial或MeshPhongMaterial类似,但提供了更准确、更逼真的外观结果。它有两个特性:粗糙度和金属性,而不是光泽

7、MeshPhysicalMaterial
它与MeshStandardMaterial非常相似。可以控制材质的反射率

以上介绍了const plane = new THREE.Mesh(planeGeometry, planeMaterial);各个部分的大概定义,
所以可以看到一个立方体就是由geometry(什么形状)、materia(什么样子),代入到Mesh中实现。
后面对各个材质大部分都会用到,具体的后面再说,想了解更深入些,大家可以用这个例子根据官方文档依次使用下,想学会这点主观能动性还是要有的

createMultiMaterialObject再看这个就按理解了,官方定义是
为材质中定义的每个材质创建一个包含新网格的新组。请注意,这与为1个网格定义多个材质的材质数组不同。这对于同时需要材质和线框实现的对象非常有用。其实就是可以实现一个模型同时具有两种材质的效果。

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

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

相关文章

修炼k8s+flink+hdfs+dlink(一:安装flink)

一&#xff1a;standalone的ha环境部署。 创建目录&#xff0c;上传安装包。 mkdir /opt/app/flink 上传安装包到本目录。 tar -zxvf flink-1.13.6-bin-scala_2.12.tgz配置参数。 在flink-conf.yaml中添加zookeeper配置 jobmanager.rpc.address: node01 high-availability: …

论文浅尝 | INGRAM:通过关系图的归纳知识图谱嵌入

笔记整理&#xff1a;郭荣辉&#xff0c;天津大学硕士 链接&#xff1a;https://arxiv.org/abs/2305.19987 动机 归纳知识图谱补全是预测训练期间没有观察到的新实体之间缺失的三元组的任务。虽然大多数归纳知识图谱补全方法假定所有实体都是新的&#xff0c;但它们不允许在推理…

【c语言的malloc函数介绍】

malloc&#xff08;memory allocation的缩写&#xff09;是C语言中的一个函数&#xff0c;用于动态分配内存空间。这个函数允许你在程序运行时请求指定大小的内存块&#xff0c;以供后续使用。malloc函数属于标准库函数&#xff0c;需要包含头文件#include <stdlib.h> 才…

使用Vue、ElementUI实现登录注册,配置axios全局设置,解决CORS跨域问题

目录 引言 什么是ElementUI&#xff1f; 步骤1&#xff1a;创建Vue组件用于用户登录和注册 1. 基于SPA项目完成登录注册 在SPA项目中添加elementui依赖 在main.js中添加elementui模块 创建用户登录注册组件 配置路由 修改项目端口并启动项目 静态页面展示图 步骤2&#x…

搭建qml box2d开发环境

box2d是开源的优秀物理引擎 box2d官网 https://box2d.org/ qml box2d插件工程 https://gitee.com/gao_yao_yao/qml-box2d 1. qml box2d插件工程 下载&#xff0c;解压qml-box2d-master.zip&#xff0c;用qt打开box2d.pro&#xff0c;编译Debug|Release拷贝Box2D.dll|Box2Dd.…

LeetCode算法二叉树—226. 翻转二叉树

目录 226. 翻转二叉树 代码&#xff1a; 运行结果&#xff1a; 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&#xff1a; 输入…

easyrecovery好用吗 easyrecovery软件收费吗

EasyRecovery是一款专业的数据恢复软件&#xff0c;它功能强大且性价比高&#xff0c;能够精确找回需要的文件&#xff0c;方便又快捷。那么Easyrecovery好用吗&#xff0c;Easyrecovery软件收费吗。今天我为大家解答一下这两个问题。 一、Easyrecovery好用吗 EasyRcovery可用…

系统接口响应信息通用加密设计

设计目的 出于对一些敏感信息的安全性考虑&#xff0c;接口的响应信息需要进行加密&#xff0c;避免明文传输 使用场景 本系统前端响应信息加密 第三方系统响应信息加密 功能设计思路 配置模式加密 使用场景&#xff1a;本系统前端响应信息加密 在nacos中配置需要加密的…

用于生物分子修饰的Alkyne NHS ester,906564-59-8

产品简介&#xff1a;用于生物分子修饰的炔烃NHS酯。铜催化的化学反应中的炔基几乎从未在天然分子中遇到过。然而&#xff0c;这种NHS酯允许将炔基连接到氨基上&#xff0c;氨基在自然界中普遍存在&#xff0c;存在于蛋白质、肽、合成氨基DNA和许多小分子中。炔基随后可以通过铜…

langchain+gpt+agent

一.agentConversation 通过用户问题&#xff0c;来选择 import json import os import refrom langchain import FAISS, PromptTemplate, LLMChain from langchain.agents import initialize_agent, Tool, AgentType from langchain.chains import RetrievalQA from langchai…

C++ | C++11新特性(下)

前言 前面我们介绍了C11列表初始化、新的类功能以及右值引用等新特性&#xff0c;本文继续介绍关于可变参数模板以及lambda表达式等新语法&#xff1b; 一、可变参数模板 在C11前&#xff0c;我们有普通固定数量模板参数&#xff0c;但对于可变参数&#xff0c;我们无从下手&am…

淘宝电商必备的大数据应用

在日常生活中&#xff0c;大家总能听到“大数据”“人工智能”的说法。现在的大数据技术应用&#xff0c;从大到巨大科学研究、社会信息审查、搜索引擎&#xff0c;小到社交联结、餐厅推荐等等&#xff0c;已经渗透到我们生活中的方方面面。到底大数据在电商行业可以怎么用&…

什么是EventEmitter?它在Node.js中有什么作用?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 什么是EventEmitter&#xff1f;⭐ 它在Node.js中的作用是什么&#xff1f;⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为…

轻松上手Docker:学习如何创建和运行自己的Docker容器

文章目录 轻松上手Docker&#xff1a;学习如何创建和运行自己的Docker容器容器的介绍Docker的技术架构容器的工作机制&#xff08;Docker&#xff09;容器的关键技术 - NamespaceNamespace隔离说明 容器的关键技术 - CgroupDocker环境搭建1&#xff09;安装基础软件包2&#xf…

分类预测 | Matlab实现SSA-CNN-SVM麻雀算法优化卷积支持向量机分类预测

分类预测 | Matlab实现SSA-CNN-SVM麻雀算法优化卷积支持向量机分类预测 目录 分类预测 | Matlab实现SSA-CNN-SVM麻雀算法优化卷积支持向量机分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现SSA-CNN-SVM麻雀算法优化卷积支持向量机分类预测&#xff0…

跟着顶级科研报告IPCC学绘图:温度折线/柱图/条带/双y轴

复现IPCC气候变化过程图 引言 升温条带Warming stripes&#xff08;有时称为气候条带&#xff0c;目前尚无合适且统一的中文释义&#xff09;是数据可视化图形&#xff0c;使用一系列按时间顺序排列的彩色条纹来视觉化描绘长期温度趋势。 在IPCC报告中经常使用这一方案 IPCC是…

自学——网络安全——黑客技术

想自学网络安全&#xff08;黑客技术&#xff09;首先你得了解什么是网络安全&#xff01;什么是黑客&#xff01;&#xff01;&#xff01; 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队…

【小程序 - 基础】WXML、WXSS语法以及小程序的配置、网络数据请求_03

目录 一、WXML模板语法 1. 数据绑定 1.1 数据绑定的基本原则 1.2 在 data 中定义页面的数据 1.3 Mustache 语法的格式 1.4 Mustache 语法的应用场景 2. 事件绑定 2.1 什么是事件 2.2 小程序中常用的事件 2.3 事件对象的属性列表 2.4 target 和 currentTarget 的区别…

510758-28-8,用于标记蛋白质和酶的配体TBTA

产品简介&#xff1a;Tris(benzyltriazolylmethyl)amine (TBTA)是一种配体&#xff0c;能作为生化工具用于标记蛋白质和酶。 CAS号&#xff1a;510758-28-8 中文名&#xff1a;三[(1-苄基-1H-1,2,3-三唑-4-基)甲基]胺 英文名&#xff1a;TBTA 化学式&#xff1a;C30H30N10…

NestJs和Vite使用monorepo管理项目中,需要使用共享的文件夹步骤

NestJs和Vite使用monorepo管理项目中,需要使用共享的文件夹步骤 1 首先需要将nest-cli打包的功能通过webpack接管 nest-cli.json文件内容 {"$schema": "https://json.schemastore.org/nest-cli","collection": "nestjs/schematics",…