3D区块多重渐变围栏

这里主要用到的就是threejs的shader,至于其他知识点,可以参考json生成3d区域

下面的主要代码: 

import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
import { OutputPass } from 'three/addons/postprocessing/OutputPass.js';
import * as d3geo from 'd3-geo'
import guangzhouJSON from '../assets/json/guangzhou.json'export default (domId) => {/* ------------------------------初始化三件套--------------------------------- */const dom = document.getElementById(domId);const { innerHeight, innerWidth } = windowconst scene = new THREE.Scene();const camera = new THREE.PerspectiveCamera(45, innerWidth / innerHeight, 1, 2000);camera.position.set(0, 0, 10);camera.lookAt(scene.position);const renderer = new THREE.WebGLRenderer({antialias: true,// 抗锯齿alpha: false,// 透明度powerPreference: 'high-performance',// 性能logarithmicDepthBuffer: true,// 深度缓冲})// renderer.setClearColor(0x000000, 0);// 设置背景色// renderer.clear();// 清除渲染器renderer.shadowMap.enabled = true;// 开启阴影renderer.shadowMap.type = THREE.PCFSoftShadowMap;// 阴影类型renderer.outputEncoding = THREE.sRGBEncoding;// 输出编码renderer.toneMapping = THREE.ACESFilmicToneMapping;// 色调映射renderer.toneMappingExposure = 1;// 色调映射曝光renderer.physicallyCorrectLights = true;// 物理正确灯光renderer.setPixelRatio(devicePixelRatio);// 设置像素比renderer.setSize(innerWidth, innerHeight);// 设置渲染器大小dom.appendChild(renderer.domElement);// 重置大小window.addEventListener('resize', () => {const { innerHeight, innerWidth } = windowcamera.aspect = innerWidth / innerHeight;camera.updateProjectionMatrix();renderer.setSize(innerWidth, innerHeight);})/* ------------------------------初始化工具--------------------------------- */const controls = new OrbitControls(camera, renderer.domElement) // 相机轨道控制器controls.enableDamping = true // 是否开启阻尼controls.dampingFactor = 0.05// 阻尼系数controls.panSpeed = -1// 平移速度// const axesHelper = new THREE.AxesHelper(10);// scene.add(axesHelper);/* ------------------------------正题--------------------------------- */// 相机控制器配置const cameraControl = {autoCamera: true,// 是否自动旋转height: 10,// 相机高度width: 0.5,// 相机宽度depth: 1,// 相机深度cameraPosX: 10,// 相机位置xcameraPosY: 181,// 相机位置ycameraPosZ: 116,// 相机位置zautoRotate: false,// 是否自动旋转rotateSpeed: 2000// 旋转速度}let geoFun;// 地理投影函数let guangzhouData = [];// 地图数据let shape = null;// 地图形状let time = 1;// 时间const group = new THREE.Group();const edgeMaterial = new THREE.ShaderMaterial({side: THREE.DoubleSide,transparent: true,depthTest: false,uniforms: {time: { value: 0.0 },num: { value: 5.0 },color1: { value: new THREE.Color('#00FFFF') }},vertexShader: ` varying vec2 vUv;varying vec3 vNormal;void main() {vUv=uv;vNormal=normal;           gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );}`,fragmentShader: `uniform vec3 color1;  uniform float time;  uniform float num;                                 varying vec2 vUv; varying vec3 vNormal;void main() {if(vNormal.z==1.0||vNormal.z==-1.0||vUv.y ==0.0){discard;}else{gl_FragColor =  vec4(color1, 1.0-fract((vUv.y-time ) *num) ) ;} }`});// 初始化地理投影const initGeo = (size) => {geoFun = d3geo.geoMercator().scale(size || 100)}// 经纬度转像素坐标const latlng2px = (pos) => {if (pos[0] >= -180 && pos[0] <= 180 && pos[1] >= -90 && pos[1] <= 90) {return geoFun(pos);}return pos;};// 处理地图数据const processData = () => {guangzhouData = guangzhouJSON.features[0].geometry.coordinates[0][0];// 数据 从 经纬度-> 像素坐标-> 三维坐标guangzhouData = guangzhouData.map(item => {const two = latlng2px(item);const three = new THREE.Vector3(two[0], 0, two[1]);return three;})}// 创建地图块const createMap = () => {const extrudeSettings = {depth: 0.2,// 区块厚度bevelEnabled: false// 是否使用倒角};shape = new THREE.Shape();shape.moveTo(guangzhouData[0].x, guangzhouData[0].z);// 移动到第一个点for (let i = 1; i < guangzhouData.length; i++) {shape.lineTo(guangzhouData[i].x, guangzhouData[i].z);// 连线}shape.lineTo(guangzhouData[0].x, guangzhouData[0].z);// 闭合const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);const img = new URL('../assets/images/tex.png', import.meta.url).href;const text = new THREE.TextureLoader().load(img);text.wrapS = THREE.RepeatWrapping;// 水平方向text.wrapT = THREE.RepeatWrapping;// 垂直方向const material = new THREE.MeshBasicMaterial({map: text,color: new THREE.Color('#00FFFF')})const mesh = new THREE.Mesh(geometry, material);mesh.rotateX(Math.PI / 2);// 旋转90度mesh.position.y = extrudeSettings.depth * 0.5;group.add(mesh);}// 创建边缘线const createEdge = () => {const extrudeSettings = {depth: 1,// 厚度bevelEnabled: false// 是否使用倒角};const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);const mesh = new THREE.Mesh(geometry, edgeMaterial);mesh.rotation.x = Math.PI * 0.5;mesh.position.y = extrudeSettings.depth + 0.1;group.add(mesh);}// 设置模型的中心点const setModeCenter = (object, viewControl) => {// 如果对象不存在,则返回   if (!object) {return;}if (object.updateMatrixWorld) {object.updateMatrixWorld();// 更新模型矩阵}// 获得包围盒得min和maxlet box = new THREE.Box3().setFromObject(object);let objSize;// 获取包围盒的尺寸try {objSize = box.getSize();} catch (error) {objSize = new THREE.Vector3(Math.abs(box.max.x - box.min.x),Math.abs(box.max.y - box.min.y),Math.abs(box.max.z - box.min.z));}// 返回包围盒的中心点const center = box.getCenter(new THREE.Vector3());object.position.x += object.position.x - center.x;object.position.y += object.position.y - center.y;object.position.z += object.position.z - center.z;let width = objSize.x;let height = objSize.y;let depth = objSize.z;// 设置相机位置let centroid = new THREE.Vector3().copy(objSize);centroid.multiplyScalar(0.5);if (viewControl.autoCamera) {camera.position.x =centroid.x * (viewControl.centerX || 0) + width * (viewControl.width || 0);camera.position.y =centroid.y * (viewControl.centerY || 0) + height * (viewControl.height || 0);camera.position.z =centroid.z * (viewControl.centerZ || 0) + depth * (viewControl.depth || 0);} else {camera.position.set(viewControl.cameraPosX || 0,viewControl.cameraPosY || 0,viewControl.cameraPosZ || 0);}camera.lookAt(0, 0, 0);}// 初始化const init = () => {initGeo(180)// 初始化地理投影processData()// 处理地图数据createMap()// 创建地图块createEdge()// 创建边缘线scene.add(group);// 添加到场景中setModeCenter(group, cameraControl)// 设置模型的中心点}init();/* ------------------------------动画函数--------------------------------- */const animation = () => {if (edgeMaterial) {if (time >= 1.0) {time = 0.0;}time += 0.005;edgeMaterial.uniforms.time.value = time;}controls.update();// 如果不调用,就会很卡renderer.render(scene, camera);requestAnimationFrame(animation);}animation();
}

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

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

相关文章

【NLP】使用 SpaCy、ollama 创建用于命名实体识别的合成数据集

命名实体识别 (NER) 是自然语言处理 (NLP) 中的一项重要任务&#xff0c;用于自动识别和分类文本中的实体&#xff0c;例如人物、位置、组织等。尽管它很重要&#xff0c;但手动注释大型数据集以进行 NER 既耗时又费钱。受本文 ( https://huggingface.co/blog/synthetic-data-s…

Git代码托管(三)可视化工具操作(1)

常见的可视化操作工具有 一、官方网页 如码云、gitlab&#xff0c;自带了常见的git操作。 以码云为例&#xff1a; 1、创建分支&#xff1a; 进入分支目录&#xff0c;点击 新建分支 按钮&#xff0c; 在弹出框中输入新分支名称&#xff0c;点击确定即可一键创建分支&…

STL学习-无序容器-unordered set和unorderde multiset

1.定义及初始化 #include <unordered set> #include <iostream> using namespace std; //输出s中的所有元素 template<typename T> void Show(const T& s) { for(auto&x:s) cout << x<<" ";cout << endl; } int main()…

鸿蒙(Harmony)实现滑块验证码

在Android和ios两端已经使用的滑块验证码框架还未适配鸿蒙版&#xff0c;于是需要自己去实现类似如下的滑块验证码&#xff1a; 那么实现这样的验证码主要涉及到几个内容&#xff1a; 1、自定义弹窗 2、base64图片转换 3、滑动组件与滑块的联动&#xff0c;以及横移距离转换…

《华为工作法》读书摘记

无论做什么事情&#xff0c;首先要明确的就是做事的目标。目标是引导行动的关键&#xff0c;也是证明行动所具备的价值的前提&#xff0c;所以目标管理成了企业与个人管理的重要组成部分。 很多时候&#xff0c;勤奋、努力并不意味着就一定能把工作做好&#xff0c;也并不意味…

三维测量与建模笔记 - 3.3 张正友标定法

上图中&#xff0c;提到了世界坐标系在张正友标定法中的设计&#xff0c;可以理解为将世界坐标系的原点放到了棋盘格左上角点的位置&#xff0c;并且棋盘格平面上所有点的Z为0&#xff0c;将Z规定为0的话&#xff0c;可以简化掉一个维度&#xff08;列向量r3&#xff09;。去掉…

【课程总结】day34:多模态大模型之ViT模型、CLIP模型论文阅读理解

前言 在【课程总结】day31&#xff1a;多模态大模型初步了解一文中&#xff0c;我们对多模态大模型的基本原理有了初步了解&#xff0c;本章内容将通过论文阅读理解&#xff0c;更进一步理解多模态大模型中所涉及的 Vit 架构、Transformer在视觉应用的理念以及 Clip图像与文本…

国药准字生发产品有哪些?这几款不错

头秃不知道怎么选的朋友们看这&#xff0c;基本上市面上火的育发精华我都用了个遍了&#xff0c;陆陆续续也花了有大几w了&#xff0c;都是真金白银总结出来的&#xff0c;所以必须要给掉发人分享一些真正好用的育发产品&#xff0c;大家可以根据自己实际情况来选择。 1. 露卡菲…

golang分布式缓存项目 Day 1

注&#xff1a;该项目原作者&#xff1a;https://geektutu.com/post/geecache-day1.html。本文旨在记录本人做该项目时的一些疑惑解答以及部分的测试样例以便于本人复习。 LRU缓存淘汰策略 三种缓存淘汰策略 FIFO&#xff08;First In, First Out&#xff09;先进先出 原理&…

Android View事件分发

目录 1.什么是View事件分发&#xff1f; 2.事件的类型 3.事件的发生 4.事件分发的方法 4.1 dispatchTouchEvent() 4.2 onTouchEvent() 4.3 onInterceptTouchEvent() 5.滑动冲突 5.1 外部拦截法 5.2内部拦截法 6.onTouch的执行高于onClick 7. onTouch()和onTouchEve…

Elasticsearch常用接口_添加数据

插入es数据&#xff1a;_index/_type/ POST { "tabTitle": "森图表_test", "chtTabTitle": "森图表_test", "status": 0 } 注意&#xff1a;Elasticsearch 6.0.0及更高版本中&#xff0c;索引只能包含一个映射类型

springboot养老院信息管理系统-计算机设计毕业源码30958

目 录 摘要 1绪论 1.1 研究背景 1.2 研究意义 1.3论文结构与章节安排 2 系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据新增流程 2.2.2 数据删除流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分析 2.5本章小结 3 系统总体设…

OkHttp网络请求框架

添加依赖 在 build.gradle 文件中添加 OkHttp 依赖&#xff1a; dependencies {implementation("com.squareup.okhttp3:okhttp:4.10.0") }使用OkHttp发起GET请求 同步请求 public class MainActivity extends AppCompatActivity {// Used to load the okhttptes…

基于sealos部署的集群部署dashboard

1、下载yaml文件进行部署 rootmaster-1:~# wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml2、修改service的访问模式 rootmaster-1:~# vim recommended.yaml kind: Service apiVersion: v1 metadata:labels:k8s-app: kube…

手机贴膜气泡识别组件定位图像分割系统:快速图像识别

手机贴膜气泡识别组件定位图像分割系统源码&#xff06;数据集分享 [yolov8-seg-C2f-Parc&#xff06;yolov8-seg-KernelWarehouse等50全套改进创新点发刊_一键训练教程_Web前端展示] 1.研究背景与意义 项目参考ILSVRC ImageNet Large Scale Visual Recognition Challenge …

C语言 | Leetcode C语言题解之第538题把二叉搜索树转换为累加树

题目&#xff1a; 题解&#xff1a; struct TreeNode* getSuccessor(struct TreeNode* node) {struct TreeNode* succ node->right;while (succ->left ! NULL && succ->left ! node) {succ succ->left;}return succ; }struct TreeNode* convertBST(stru…

SQL--查询连续三天登录数据详解

问题&#xff1a; 现有用户登录记录表&#xff0c;请查询出用户连续三天登录的所有数据记录 id dt1 2024-04-25 1 2024-04-26 1 2024-04-27 1 2024-04-28 1 2024-04-30 1 2024-05-01 1 2024-05-02 1 2024-05-04 1 2024-05-05 2 20…

数据结构和算法-01背包问题01-认识01背包

0-1背包 什么是0-1背包问题&#xff1f; [0-1背包问题Knapsack Problem] 假设有一个背包&#xff0c;可承载的最大重量是W(kg)&#xff0c; 现在有n个物品&#xff0c;每个物品的重量不等&#xff0c; 并且不可分割。我们期待选择几件物品放入背包中&#xff0c;在不超过背包最…

go-carbon 和 gorm 优雅处理数据库日期时间

一、简介 (一) carbon carbon 是一个简单、语义化、开发人员友好的 golang 时间包。carbon 提供了丰富的日期和时间处理功能&#xff0c;使得日期和时间操作更加简单和直观。 (二) gorm gorm 是一个用于 Go 语言的 ORM&#xff08;对象关系映射&#xff09;框架。它提供了简…

Java 抽象类 详解

文章目录 一、概述1.1、什么是抽象类1.2、定义抽象类1.3、什么是抽象方法1.4、定义抽象方法 二、特点2.1、抽象类的特点2.1.1、抽象类不可以实例化对象2.1.2、抽象类必须要被继承2.1.3、抽象类的子类2.1.4、抽象类的成员 2.2、抽象方法的特点2.2.1、只能有方法声明&#xff0c;…