本文适合对vue,arcgis4.x,threejs,ES6较熟悉的人群食用。
(资料图片)
效果图:
素材:
主要思路:
先用arcgisexternalRenderers封装了一个ExternalRendererLayer,在里面把arcgis和threejs的context关联,然后再写个子类继承它,这部分类容在上一个帖子里面有讲过。
子类AreaLayer继承它,并在里面实现绘制流光边界线的方法,我这里其实就是绘制城市区域的边界线。尝试过直线LineCurve3,三维二次贝塞尔曲线QuadraticBezierCurve3,三维三次贝塞尔曲线CubicBezierCurve3,结果感觉差不多=_=,所以最后还是用CatmullRomCurve3这个来构建管道,这个类使用也比其他的方便。
1:创建一个基于图片的材质
1 const lineImg = require("../../../../public/static/img/line.png") 2 let lineTexture = new THREE.TextureLoader().load(lineImg) 3 lineTexture.wrapS = lineTexture.wrapT = THREE.RepeatWrapping; //每个都重复 4 lineTexture.repeat.set(1, 1) 5 lineTexture.needsUpdate = true 6 7 let lineMaterial = new THREE.MeshBasicMaterial({ 8 map: lineTexture, 9 side: THREE.DoubleSide,10 transparent: true11 })
2:处理坐标转换数据
1 let linePoints = []2 for(let i = 0; i < pointList.length; i++) {3 var item = pointList[i];4 var renderLinePoints = this.lngLatToXY(this.view, [item[0], item[1], 10]);5 var vector3List = renderLinePoints.vector3List;6 7 linePoints.push(new THREE.Vector3(vector3List.x, vector3List.y, vector3List.z));8 }
3:构建TubeGeometry,创建Mesh
1 const curvePath = new THREE.CatmullRomCurve3(linePoints) // 曲线路径2 3 let geometry = new THREE.TubeGeometry(curvePath, 64, 30, 8, true )4 let lineMesh = new THREE.Mesh(geometry, lineMaterial);
4:最后再updateModels里面更新贴图的位置(其实就是render事件)。
1 updateModels(context) {2 super.updateModels(context);3 4 if (this.textures.length > 0) {5 this.textures.forEach(texture => {6 if (texture) texture.offset.x -= 0.01;7 })8 }9 }
ExternalRendererLayer:
1 import * as THREE from "three" 2 import Stats from "three/examples/jsm/libs/stats.module.js" 3 import * as webMercatorUtils from "@arcgis/core/geometry/support/webMercatorUtils" 4 import * as externalRenderers from "@arcgis/core/views/3d/externalRenderers" 5 6 export default class ExternalRendererLayer { 7 constructor({ 8 view, 9 options 10 }) { 11 this.view = view 12 this.options = options 13 14 this.objects = [] 15 this.scene = null 16 this.camera = null 17 this.renderer = null 18 19 this.setup(); 20 } 21 22 setup() { 23 if (process.env.NODE_ENV !== "production") { 24 const sid = setTimeout(() => { 25 clearTimeout(sid) 26 //构建帧率查看器 27 let stats = new Stats() 28 stats.setMode(0) 29 stats.domElement.style.position = "absolute" 30 stats.domElement.style.left = "0px" 31 stats.domElement.style.top = "0px" 32 document.body.appendChild(stats.domElement) 33 function render() { 34 stats.update() 35 requestAnimationFrame(render) 36 } 37 render() 38 }, 5000) 39 } 40 } 41 42 apply() { 43 let myExternalRenderer = { 44 setup: context => { 45 this.createSetup(context) 46 }, 47 render: context => { 48 this.createRender(context) 49 } 50 } 51 52 externalRenderers.add(this.view, myExternalRenderer); 53 } 54 55 createSetup(context) { 56 this.scene = new THREE.Scene(); // 场景 57 this.camera = new THREE.PerspectiveCamera(); // 相机 58 59 this.setLight(); 60 61 // 添加坐标轴辅助工具 62 const axesHelper = new THREE.AxesHelper(10000000); 63 this.scene.Helpers = axesHelper; 64 this.scene.add(axesHelper); 65 66 this.renderer = new THREE.WebGLRenderer({ 67 context: context.gl, // 可用于将渲染器附加到已有的渲染环境(RenderingContext)中 68 premultipliedAlpha: false, // renderer是否假设颜色有 premultiplied alpha. 默认为true 69 // antialias: true 70 // logarithmicDepthBuffer: false 71 // logarithmicDepthBuffer: true 72 }); 73 this.renderer.setPixelRatio(window.devicePixelRatio); // 设置设备像素比。通常用于避免HiDPI设备上绘图模糊 74 this.renderer.setViewport(0, 0, this.view.width, this.view.height); // 视口大小设置 75 76 // 防止Three.js清除ArcGIS JS API提供的缓冲区。 77 this.renderer.autoClearDepth = false; // 定义renderer是否清除深度缓存 78 this.renderer.autoClearStencil = false; // 定义renderer是否清除模板缓存 79 this.renderer.autoClearColor = false; // 定义renderer是否清除颜色缓存 80 // this.renderer.autoClear = false; 81 82 // ArcGIS JS API渲染自定义离屏缓冲区,而不是默认的帧缓冲区。 83 // 我们必须将这段代码注入到three.js运行时中,以便绑定这些缓冲区而不是默认的缓冲区。 84 const originalSetRenderTarget = this.renderer.setRenderTarget.bind( 85 this.renderer 86 ); 87 this.renderer.setRenderTarget = target => { 88 originalSetRenderTarget(target); 89 if (target == null) { 90 // 绑定外部渲染器应该渲染到的颜色和深度缓冲区 91 context.bindRenderTarget(); 92 } 93 }; 94 95 this.addModels(context); 96 97 context.resetWebGLState(); 98 } 99 100 createRender(context) {101 const cam = context.camera;102 this.camera.position.set(cam.eye[0], cam.eye[1], cam.eye[2]);103 this.camera.up.set(cam.up[0], cam.up[1], cam.up[2]);104 this.camera.lookAt(105 new THREE.Vector3(cam.center[0], cam.center[1], cam.center[2])106 );107 // this.camera.near = 1;108 // this.camera.far = 100;109 110 // 投影矩阵可以直接复制111 this.camera.projectionMatrix.fromArray(cam.projectionMatrix);112 113 this.updateModels(context);114 115 this.renderer.state.reset();116 117 context.bindRenderTarget();118 119 this.renderer.render(this.scene, this.camera);120 121 // 请求重绘视图。122 externalRenderers.requestRender(this.view);123 124 // cleanup125 context.resetWebGLState();126 }127 128 //经纬度坐标转成三维空间坐标129 lngLatToXY(view, points) {130 131 let vector3List; // 顶点数组132 133 let pointXYs;134 135 136 // 计算顶点137 let transform = new THREE.Matrix4(); // 变换矩阵138 let transformation = new Array(16);139 140 // 将经纬度坐标转换为xy值\141 let pointXY = webMercatorUtils.lngLatToXY(points[0], points[1]);142 143 // 先转换高度为0的点144 transform.fromArray(145 externalRenderers.renderCoordinateTransformAt(146 view,147 [pointXY[0], pointXY[1], points[148 2]], // 坐标在地面上的点[x值, y值, 高度值]149 view.spatialReference,150 transformation151 )152 );153 154 pointXYs = pointXY;155 156 vector3List =157 new THREE.Vector3(158 transform.elements[12],159 transform.elements[13],160 transform.elements[14]161 )162 163 return {164 vector3List: vector3List,165 pointXYs: pointXYs166 };167 }168 169 setLight() {170 console.log("setLight")171 let ambient = new THREE.AmbientLight(0xffffff, 0.7);172 this.scene.add(ambient);173 let directionalLight = new THREE.DirectionalLight(0xffffff, 0.7);174 directionalLight.position.set(100, 300, 200);175 this.scene.add(directionalLight);176 }177 178 addModels(context) {179 console.log("addModels")180 }181 182 updateModels(context) {183 // console.log("updateModels")184 }185 186 }View Code
AreaLayer:源码中mapx.queryTask是封装了arcgis的query查询,这个可以替换掉,我只是要接收返回的rings数组,自行构建静态数据也行
1 import * as THREE from "three" 2 import ExternalRendererLayer from "./ExternalRendererLayer.js" 3 import Graphic from "@arcgis/core/Graphic"; 4 import SpatialReference from "@arcgis/core/geometry/SpatialReference" 5 import * as externalRenderers from "@arcgis/core/views/3d/externalRenderers" 6 7 import mapx from "@/utils/mapUtils.js"; 8 9 export default class AreaLayer extends ExternalRendererLayer { 10 constructor({ 11 view, 12 options 13 }) { 14 super({ 15 view, 16 options 17 }) 18 } 19 20 setup() { 21 super.setup() 22 23 this.textures = [] 24 } 25 26 addModels(context) { 27 // super.addModels(context) 28 // =====================mesh加载=================================// 29 const url = config.mapservice[1].base_url + config.mapservice[1].jd_url; 30 // const url = "http://10.100.0.132:6080/arcgis/rest/services/wuchang_gim/gim_region/MapServer/2"; 31 mapx.queryTask(url, { 32 where: "1=1", 33 returnGeometry: true 34 }).then(featureSet => { 35 if (featureSet.length > 0) { 36 featureSet.forEach(feature => { 37 const polygon = feature.geometry; 38 const rings = polygon.rings; 39 rings.forEach(ring => { 40 this._addModel(ring); 41 }) 42 }) 43 } 44 }).catch(error => { 45 console.log(error) 46 }) 47 } 48 49 _addModel(pointList) { 50 const lineImg = require("../../../../public/static/img/line.png") 51 let lineTexture = new THREE.TextureLoader().load(lineImg) 52 lineTexture.wrapS = lineTexture.wrapT = THREE.RepeatWrapping; //每个都重复 53 lineTexture.repeat.set(1, 1) 54 lineTexture.needsUpdate = true 55 56 let lineMaterial = new THREE.MeshBasicMaterial({ 57 map: lineTexture, 58 side: THREE.DoubleSide, 59 transparent: true 60 }) 61 62 //确定几何体位置 63 let linePoints = [] 64 // let curvePath = new THREE.CurvePath(); 65 for(let i = 0; i < pointList.length; i++) { 66 var item = pointList[i]; 67 var renderLinePoints = this.lngLatToXY(this.view, [item[0], item[1], 10]); 68 var vector3List = renderLinePoints.vector3List; 69 70 linePoints.push(new THREE.Vector3(vector3List.x, vector3List.y, vector3List.z)); 71 72 // if(i < pointList.length - 1) { 73 // var item1 = pointList[i + 1]; 74 // var renderLinePoints1 = this.lngLatToXY(this.view, [item1[0], item1[1], 10]); 75 // var vector3List1 = renderLinePoints1.vector3List; 76 77 // // var item2 = pointList[i + 1]; 78 // // var renderLinePoints2 = this.lngLatToXY(this.view, [item2[0], item2[1], 10]); 79 // // var vector3List2 = renderLinePoints2.vector3List; 80 81 // const line = new THREE.LineCurve3(vector3List, vector3List1); 82 // // const line = new THREE.QuadraticBezierCurve3(vector3List, vector3List1, vector3List2); 83 // curvePath.curves.push(line) 84 // } 85 } 86 87 // console.log(curvePath) 88 89 // CatmullRomCurve3创建一条平滑的三维样条曲线 90 const curvePath = new THREE.CatmullRomCurve3(linePoints) // 曲线路径 91 92 let geometry = new THREE.TubeGeometry(curvePath, 64, 30, 8, true ) 93 let lineMesh = new THREE.Mesh(geometry, lineMaterial); 94 95 this.scene.add(lineMesh); 96 97 this.textures.push(lineTexture); 98 this.objects.push(lineMesh); 99 }100 101 102 updateModels(context) {103 super.updateModels(context);104 105 if (this.textures.length > 0) {106 this.textures.forEach(texture => {107 if (texture) texture.offset.x -= 0.01;108 })109 }110 }111 112 }View Code
标签:
成都车展|电动车大降价,某豪华品牌优惠30万?
新车在线|近日亮相的三款自主新能源新车分享
线下体验奔腾T90:上驼峰桥,过涉水路面,一脚油门轻松搞定
一波未平又来一波,丰田暂停日本工厂生产,日系车彻底“火了”?
本文适合对vue,arcgis4 x,threejs,ES6较熟悉的人群食用。效果图:素
绽放绿色低碳魅力岚图梦想家助力2023绿色低碳高质量发展大会
踢球者:莫里巴被莱比锡从一线队除名,巴萨未来难以获得转会分成,夏窗,
途锐评测由新车评网专业汽车评测团队为您提供途锐试驾测评,包括途锐底
中国建筑主要从三个方面来做好应对风险的工作:一是源头治理,预防为主
CB4-4-47、48两宗地均位于西安浐灞生态区湿地文旅产业园版块(行政辖区
不少房企似乎仍未找回节奏,而灵活调整销售节奏的五矿却实现了增长。
华远地产上半年营收45 99亿元,同比增长16 91%;归属于上市公司股东的
富瑞表示,将中国海外在2023年至24年盈利预测上调3%至5%,并将其目标价
BigC行政总裁AswinTechajareonvikul发表声明指,管理层考虑到股东及其
8月29日,蔚来汽车发布了2023年第二季度财报。财报数据显示,第二季度
据恒生沪深港通AH股溢价(HSAHP)指数显示,AH股溢价于8月22日上升至近50
OvoloSouthside位于黄竹坑道64号,楼高24层,设有162间客房,于2014年
每经AI快讯,有投资者在投资者互动平台提问:请问一下贵公司具有中低放
中国人民银行金融市场司副司长马贱阳介绍称,金融支持民营企业发展有关
中信银行福州分行通过阿里资产拍卖网发布“关于福建省福州市喜来登酒店
路特斯官方发布了首款纯电高性能轿车的预告视频,新车将于9月7日全球首
中国男篮背水一战,姚明作出铁血决定,陪乔帅周琦走完最后3条路,姚明,
“台商台青走晋来”晋台农业合作交流会召开,主流媒体,山西门户。山西新
作为汽车从业者,我们也会非常注意关注身边朋友的选车动态,发现虽然比
8月29日,华勤技术西安研发中心举行开园仪式,标志着丝路软件城又一省
美的置业一年内到期有息负债为124亿元,月均还债仅10 31亿元,还债压力
杭州玖航房地产开发有限公司拟在湘湖旅游度假区内,东至规划金西路,南
央行上海总部通报上海市银行跨境人民币业务结算量情况:截至7月末,上
据悉,共有18个重点项目在会上签约,总投资170亿元,涉及汽车“新四化
本次集中开工的9个项目包括5个新能源大基地项目和4个文旅产业集群项目
8月29日,天津滨海新区发布9宗地块挂牌公告,总出让面积约43 70万平方
“今年美的置业广州佛山、长沙等地新拿地3个项目,三宗地块增加权益货
具体原因包括,1、因公司存续债务的问题,公司正积极与相关债权人沟通
报告期内,公司主营业务板块实现营收7 41亿元,毛利率25 4%。其中工程
中信证券研报指出,展望下半年,一方面安卓品牌逐步迎来秋季旗舰机型发
MSCI与谷歌云深化合作伙伴关系加速开发投资行业生成式人工智能解决方案
官张村,关于官张村介绍这个很多人还不知道,现在让我们一起来看看吧!1
近期,在古装剧市场上有一部非常吸引人的大剧,叫做《鹊刀门传奇》。这
欧曼智蓝底部换电重卡以技术进阶直面续航、安全难题
晋力十足燃动未来JH6燃气车新品在山西隆重上市
江苏淮安市发布关于调整住房公积金有关政策的通知,提高多子女家庭住房
深圳市南山区宝能城花园(东区)四期工程1单元1301等260套公寓即将拍卖
8月30日,地产服务板块午后回暖,特发服务涨超3%,新大正、我爱我家等
标的建筑面积73642 90平方米,含地下面积18575 97平方米,其中地下三层
报告期内,公司主营业务实现营收73 85亿元,毛利率为18 27%。其中房地
该项目片策范围共6 15公顷,位于百兴路两边,东至大㘵工业街、西至拥军
【环球网财经讯】8月29日晚间,汤姆猫(300459 SZ)发布2023年半年度报
2023年8月18日0:00前签订个人住房贷款合同的,按原政策执行。2023年8月
值得关注的是,张甦毅将成为费列罗集团任命进入中国市场以来的首位本土
新政策支持灵活就业人员“灵活存,灵活取”“多缴快贷”“长缴多贷”。
售28 28-41 98万元,起亚EV6正式上市
理想汽车官方发文称,为庆祝理想L系列交付一周年,累计交付突破25万辆
最终,北京华融综合投资有限公司及重庆市江北区国有资本投资运营管理集
传祺又一销冠:真7座全能MPV传祺M6Pro!
特斯拉ModelY车身开裂被曝光!特斯拉:车没问题!
“布局者”吉利:是否“轻舟已过万重山”?
就在今日,家庭六座旗舰SUV——理想L9迎来交付一周年,并顺利完成第十
日前,有媒体获得了一张宝马新世代概念车的预告图。据悉,新车将在9月2
油耗低的才是王者皓瀚DH-i和宋ProDM-i怎么选?
当地时间8月29日,被称为“越南特斯拉”的越南电动车生厂商VinFastAuto
日前,腾势销售事业部总经理赵长江透露,腾势汽车将在3年内推出8车型。
Öлª¾µäËжÁ´ó»áɽÎ÷ÏßÏÂÕçÑ¡×÷Æ·¡
法拉利488Pista,这是一辆令人瞩目的超级跑车,以其惊人的性能和令人印
朝阳区八里庄街道八里庄西里1号楼、2号楼的污水管道因为老化等原因时
每经AI快讯,国金证券08月30日发布研报称,给予中远海控(601919 SH,
北京住总房地产开发有限责任公司会议决议批准子公司北京住总众邦地产有
报告期内,该集团的营业额及毛利分别为人民币200 02亿元及人民币20 07
仲量联行香港研究部资深董事钟楚如表示,上月整体市场租金按月下跌0 6%
支持公积金“又提又贷”。缴存职工家庭无住房公积金贷款记录且商业性个
根据协议,泸州老窖将借助蚂蚁链的智能合约、跨链等技术,通过数字人民
本次拟出让清单分别位于14个区域,包括南开区、河西区、河东区、和平区
隔夜HIBOR跌7点子至1 76869%。
地块位于广花公路以东、雅瑶路以北,是二类居住用地,占地面积43169 84
佳源服务预计借以审议及批准集团的2023年中期业绩的董事会会议将延迟至
8月30日,中国建筑(SH601668,股价5 64元,市值2360亿元)召开2023年
2022年10月27日,金周轨道获取到金周路站TOD综合开发项目用地,土地位
就在今日,比亚迪汽车官宣,比亚迪汽车App 小程序将于8月31日正式升级
如果想买一款沃尔沃中型车30万左右车型,很多人纠结怎么选择才不后悔,
在红旗15万左右车型中,有不少的车型卖点很足,有的省油、有的空间大、
1、只提供上门服务400-011-6181壁挂炉维修公司名称:啄木鸟家庭维修通
此页面是否是列表页或首页?未找到合适正文内容。
嬴彻卡车NOA(导航辅助驾驶)率先突破5000万公里,并与申通快递、中通
明隽提供76个单位,涵盖开放式及1房单位,标准户实用面积231至260方呎。
房地产经纪机构要合理降低住房买卖和租赁经纪服务费用。鼓励按照成交价
报告期内,上海电影营业收入371,957,699 30元(上年同期223,443,369 73
李家超表示,欢迎中央公布《河套深港科技创新合作区深圳园区发展规划》
海航集团财务有限公司应立即停止一切经营活动,将金融许可证缴回国家金
据中国汽车工业协会整理的海关总署数据显示,2023年7月,汽车整车进口
其中,北京华融综合投资有限公司拍得30 31%股权,重庆市江北区国有资本
报告期内,天恒置业录得营业收入52 38亿元,归属于母公司股东的净利润4
该公司上半年营业总收入9 0亿元,同比增长约12 30%,其中,安置房销售
发行人合并口径有息债务方面,报告期初和报告期末,发行人合并报表范围
截至2023年6月30日财务数据,标的企业营业收入87 77万元,营业利润8 14
一代人有一代人的“恶作剧之吻”,向往甜蜜爱情的当代年轻人,开始在短
美银证券发表报告指,小米今年第二季实际经营利润为40亿元,按年增长19
想要买一辆称心的车型,对大多数人来说,都需要花费不少时间和精力,如
手握13万左右,想购置一款13万左右福特5座SUV,市面上的车型那么多,到
我省征集医药领域商业贿赂问题线索,主流媒体,山西门户。山西新闻网是经
内部非常棒!有一辆超豪华的“流行车”!有趣的是,所有这些东西在时尚
“免费送戏进景区”惠民演出壶关站活动落下帷幕,主流媒体,山西门户。山
摘要:携程美食林围场美食定制榜单同步发布8月18日,首届木兰围场御
8月11日-8月12日晚,以“让音乐响彻云丘山”为主题的,云丘山音乐节
7月24日,我市第六届运动会开幕式在乡宁县第一中学校体育场举行。市
2023年7月25日,蓝电汽车在双福工厂正式向重庆市公安局沙坪坝公安分