背景: 公司产品预演全景参访
实现: 场景查看 锚点标注
关键点: 二维点击转换三维坐标轴、 锚点绘制、场景切换、数据格式设计

未实现: 标注点添加gif 图片
添加视屏未实践 文档中有 添加视频的材质 可以尝试一下

场景查看

一、 创建一个场景
为了真正能够让你的场景借助three.js来进行显示,我们需要以下几个对象:场景、相机和渲染器,这样我们就能透过摄像机渲染出场景。
直接看官网文档 贼详细 three.js

实操

场景创建

// 场景
const scene = new THREE.Scene();
// 透视相机
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );/***  透视相机四个参数 :视野角度*      长宽比*      近截面*      远截面**/       // 渲染器
const renderer = new THREE.WebGLRenderer();
// 渲染大小
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// 几何体 --------
const geometry = new THREE.BoxGeometry();
// 球体 ----// SphereGeometry(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength)// - radius:球体半径// - widthSegments,// - heightSegments:水平方向和垂直方向上分段数。widthSegments最小值为3,默认值为8。heightSegments最小值为2,默认值为6。// - phiStart:水平方向上的起始角,默认值0// - phiLenght:水平方向上球体曲面覆盖的弧度,默认Math.PI * 2// - thetaStart : 垂直方向上的起始角, 默认0// - thetaLength: 垂直方向是球体曲面覆盖的弧度,默认值为Math.PIconst geometry = new THREE.SphereGeometry(500, 60, 40)
// -------------const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );/**默认情况下,当我们调用scene.add()的时候,物体将会被添加到(0,0,0)坐标。但将使得摄像机和立方体彼此在一起。为了防止这种情况的发生,我们只需要将摄像机稍微向外移动一些即可。*/
camera.position.z = 5;const animate = function () {requestAnimationFrame( animate );cube.rotation.x += 0.01;cube.rotation.y += 0.01;renderer.render( scene, camera );
};
animate();
 图片加载- 加载图片 贴到纹理图  然后add 创建网格 添加到场景- 引用图片有两种方式(第二种方式 引入图片不清晰 应该是canvas 绘图的原因)
 let demo = new THREE.TextureLoader().load(vrImgurl)
// 方法一//防止跨域用canvas作为纹理let canvas = document.createElement("canvas");canvas.style.backgroundColor = "rgba(255,255,255,0)";let context = canvas.getContext("2d");let img = new Image();img.src = imgurl// img.src='';      //绘制全景图img.onload = function () {canvas.width = this.width;canvas.height = this.height;context.drawImage(img, 0, 0, this.width, this.height);let texture = new THREE.Texture();texture.image = canvas;texture.needsUpdate = true;//开启纹理更新texture.minFilter = THREE.LinearFilter;//minFilter属性:指定纹理如何缩小let material = new THREE.MeshBasicMaterial({map: texture,transparent: false});mesh = new THREE.Mesh(geometry, material);scene.add(mesh);};
// 方法二、let demo = new THREE.TextureLoader().load(vrImgurl)let material = new THREE.MeshBasicMaterial({map: demo, // 此处使用 demo 的参数 图片更为清晰transparent: false,})mesh = new THREE.Mesh(geometry, material)// 几何体  材料(渲染图)scene.add(mesh)}

场景切换

 1、先获取挂载元素的子节点2、由于mesh  和scene 是全局定义 所以需要清除  mesh && scene.remove(mesh)3、重新实例化即可
 // 初始化先删除子节点let container = document.getElementById('container')if (container.childNodes.length) {container.removeChild(container.childNodes[0])}

轨道控制

`在轨道控制中 全景图方向与鼠标拖拽方向一致  如果需要翻转 则在源码找到`function rotateLeft( angle ) {sphericalDelta.theta -= angle;}function rotateUp( angle ) {sphericalDelta.phi -= angle;}// ---- 修改为 即可修正方向function rotateLeft( angle ) {sphericalDelta.theta += angle;}function rotateUp( angle ) {sphericalDelta.phi += angle;}
 import OrbitControls from 'three-orbitcontrols'// 在场景初始化完成后 初始化控制器// 初始化控制器const initcontrols = () => {controls = new OrbitControls(camera, renderer.domElement)console.log(controls,'--controls')//是否可以缩放controls.enableZoom = false//是否自动旋转controls.autoRotate = autoRotate // 动态控制是否制动旋转、// 使动画循环使用时阻尼或自转 意思是否有惯性controls.enableDamping = true;}

锚点添加 关键点 二维视图获取三维场景中的点击坐标 (THREE.Raycaster)

1、获取点击时的坐标位置1-1、 创建场景时绑定 点击事件1-2、在当前相机所正视的世界方向建立 三维向量vector31-3、 根据页面展示大小 设置该向量的x、y 和 z 分量。1-4、(重点)使用 光线投射Raycaster 计算鼠标在三维坐标中点击的坐标位置1-5、传入鼠标点击点击坐标在三维坐标中的中位置信息
2、绘制需要标注的精灵 Sprite在下面代码中可以 有具体添加步骤
3、将绘制的精灵添加到 场景 全局 scene
    // 鼠標点击添加一个 确定点击位置  --  锚点 ---待配置 热点图片const onDocumentMouseDown = event => {/*** 1、 camera.target 当前相机所正视的世界空间方向 赋值给 vector* 2、根据配置页面 展示的宽高值 设置XYZ 轴* 3、 vector.unproject(camera) 在投影中使用的摄像机。* 4、 使用 光线投射Raycaster 计算鼠标在三维坐标中点击的坐标位置*     这将创建一个新的raycaster对象。*        let raycaster = new THREE.Raycaster(*            camera.position,*            vector.sub(camera.position).normalize() //初始化*        )*      Raycaster( origin : Vector3, direction : Vector3, near : Float, far : Float ) {origin —— 光线投射的原点向量。direction —— 向射线提供方向的方向向量,应当被标准化。near —— 返回的所有结果比near远。near不能为负值,其默认值为0。far —— 返回的所有结果都比far近。far不能小于near,其默认值为Infinity(正无穷。)* */isUserInteracting = trueif (forType === 'Equirectangular') {event.preventDefault()// let vector = new THREE.Vector3() //三维坐标对象let vector = camera.targetconsole.log(vector, 'vector预计是坐标轴的位置')vector.set(((event.clientX - 248) / (window.innerWidth - 248)) * 2 - 1,-((event.clientY - 32) / (window.innerHeight - 32)) * 2 + 1,0.5)// 在投影中使用的摄像机。vector.unproject(camera)// 这将创建一个新的raycaster对象。let raycaster = new THREE.Raycaster(camera.position,vector.sub(camera.position).normalize() //初始化 光线投射的原点向量)raycaster.camera = camera// 得到 点击的坐标 或 点击的标注点 // intersects 每项中的object 的type 可以分辨 点击的是标注还是 场景图let intersects = raycaster.intersectObjects(scene.children)//如果绘制热点属于激活状态// 此处需要判断 是否有两个坐标为0let isOnShaft = []Object.keys(intersects[0].point).forEach(v => {if (intersects[0].point[v] === 0) {isOnShaft.push(1)}})//---------------------------添加標注-----------------------------------------// 打开添加热点 true    坐标轴中是否存在两坐标为0  打开删除热点开关 为fasleif (refIsHotspot.current && isOnShaft.length < 2 && !refIsDelete.current) {// 绘制热点 //  绘制图片有两种方式// 一种直接引入 new img  //  一种使用 canvas  /**let canvas = document.createElement('canvas')canvas.style.backgroundColor = 'rgba(255,255,255,0)'let context = canvas.getContext('2d')canvas.width = 128canvas.height = 128context.drawImage(img, 0, 0, 128, 128)*/let img = new Image()img.src = hotspot //( 标注使用的图片) 也可以使用canvas 绘制文字 img.onload = function () {let texture = new THREE.Texture(img)texture.needsUpdate = truetexture.minFilter = THREE.LinearFiltervar spriteMaterial = new THREE.SpriteMaterial({map: texture,transparent: false,})// 创建一个 sprite  物体var sprite = new THREE.Sprite(spriteMaterial)sprite.scale.set(30, 30, 30)let rate = 0.8var endV = new THREE.Vector3(intersects[0].point.x * rate,intersects[0].point.y * rate,intersects[0].point.z * rate)sprite.position.copy(endV)scene.add(sprite)// addHotspot(intersects[0].point) //同步到全局数据}//移除热点} else {if (!refIsDelete.current) returnif (intersects.length > 0) {const target = intersects[0]console.log(!refIsHotspot.current, refIsDelete.current, '删除打印结果')try {if (target.object && target.object.type.length > 0) {if (target.object.type.toLowerCase() === 'sprite') {scene.remove(target.object)}}} catch (e) {console.log(e)}}}}}

初始化 绘制热点

//绘制多个跳转热点const drawJumpHotSpots = (variable, newsrc) => {console.log(variable, '锚点坐标轴数据 参数')variable.forEach(item => {let position = item.point// TextureLoader 异步记载图片var texture = new THREE.TextureLoader().load(gif)// SpriteMaterial 材质var spriteMaterial = new THREE.SpriteMaterial({map: texture,transparent: true,})// 物体 Spritevar sprite = new THREE.Sprite(spriteMaterial)sprite.scale.set(30, 30, 30)/*** 此处添加自定义属性 不能跟原有属性重复避免报错* name: 添加锚点名称* ids: 唯一ID* iconUrl: 图标*/sprite.name = item.namesprite.ids = item.idsprite.iconUrl = ''let rate = 0.8var endV = new THREE.Vector3(position.x * rate, position.y * rate, position.z * rate)sprite.position.copy(endV)scene.add(sprite)})}

操作

纹理图引入图片 ( 材质 加载图片)

// 方案一、let texture = new THREE.TextureLoader().load(img)// // TextureLoader 异步记载图片var texture = new THREE.TextureLoader().load(gif)//  SpriteMaterial 材质var spriteMaterial = new THREE.SpriteMaterial({map: texture,transparent: true,})
// 方案二、let texture = new THREE.Texture(img)texture.needsUpdate = truetexture.minFilter = THREE.LinearFiltervar spriteMaterial = new THREE.SpriteMaterial({map: texture,transparent: false,})// 创建一个 sprite  物体var sprite = new THREE.Sprite(spriteMaterial)

鼠标点击二维坐标 转换三维坐标轴 信息 绘制标注点 ( Raycaster)

 // 我其实也没太理解里面的 API的具体参数// camera.target 全局声明的 透视相机//    (event.clientX - 248) / (window.innerWidth - 248)) * 2 - 1// 页面布局 全景图距离左方 248px // (event.clientY - 32) / (window.innerHeight - 32)) * 2 + 1// 页面布局 全景图距离左方32pX    //  scene.children  >>> scene 为全局声明  let scene = new THREE.Scene()let vector = camera.targetconsole.log(vector, 'vector预计是坐标轴的位置')vector.set(((event.clientX - 248) / (window.innerWidth - 248)) * 2 - 1,-((event.clientY - 32) / (window.innerHeight - 32)) * 2 + 1,0.5)// 在投影中使用的摄像机。vector.unproject(camera)// 这将创建一个新的raycaster对象。let raycaster = new THREE.Raycaster(camera.position,vector.sub(camera.position).normalize() //初始化 光线投射的原点向量)raycaster.camera = camera// 得到 点击的坐标 或 点击的标注点 // intersects 每项中的object 的type 可以分辨 点击的是标注还是 场景图点击的坐标点上的 物体let intersects = raycaster.intersectObjects(scene.children)//如果绘制热点属于激活状态// 此处需要判断 是否有两个坐标为0 两个为0 时 添加的锚点会很大let isOnShaft = []  // 是否在坐标轴上Object.keys(intersects[0].point).forEach(v => {if (intersects[0].point[v] === 0) {isOnShaft.push('靓仔')}})

坐标轴展示 开发实用 (AxesHelper)

   //  三维坐标轴 坐标轴长度var axesHelper = new THREE.AxesHelper(150);scene.add(axesHelpe  r);

数据格式设计

 panoramicData: [{name: '会所',id: '2102271653',url: 'huisuo',active: true,// 锚点信息anchorPoint: [{point: {x: 180.01349809670057,y: 15.79023683858044,z: 465.07418151652786,},id: '2102091411',name: '海边',iconUrl: 'haibian',},{point: {x: 247.4793362659326,y: -189.1800093391692,z: 390.2798175065487,},id: '202102181619',name: '客厅',iconUrl: 'keting',},],},{name: '海边',id: '2102091411',url: 'haibian',active: false,autoRotate: false,// 锚点信息anchorPoint: [{point: {x: 374.5454984418328,y: -5.458415157221607,z: 330.55353704327746,},id: '202102181621',name: '豪宅',iconUrl: 'haozhai',},{point: {x: 140.18787952741366,y: -97.9969695393665,z: 468.933553788003,},id: '202102181619',name: '客厅',iconUrl: 'keting',},],},{name: '客厅',id: '202102181619',url: 'keting',active: false,autoRotate: false,// 锚点信息anchorPoint: [{point: {x: 481.8527362463277,y: -24.6389543862957,z: 127.17004633132723,},id: '2102271653',name: '会所',iconUrl: 'huisuo',},{point: {x: 347.09301641855546,y: -109.56249057173801,z: 341.54549425701236,},id: '2102091411',name: '海边',iconUrl: 'haibian',},],},{name: '豪宅',id: '202102181621',url: 'haozhai',active: false,autoRotate: false,// 锚点信息anchorPoint: [{point: {x: 85.2120582814672,y: -0.4428222360704279,z: 492.0249309249495,},id: '2102271653',name: '会所',iconUrl: 'huisuo',},{point: {x: 441.06070438164795,y: -157.51582618415583,z: 173.01486267642798,},id: '2102091411',name: '海边',iconUrl: 'haibian',},],},],

three.js全景搭建 、锚点标注添加、 OrbitControls 轨道方向控制 、 场景切换相关推荐

  1. 8 cocos2dx添加场景切换效果,控制场景切换彻底完成之后再执行动画

     1 添加场景切换效果 供场景切换的类: CCTransitionJumpZoom CCTransitionProgressRadialCCW CCTransitionProgressRadial ...

  2. paip.最好的脚本语言node js 环境搭建连接mysql

    paip.最好的脚本语言node js 环境搭建连接mysql #====下载node...走十一个exe..容易的.. 1 #0----Hello world   .js 2 #---------模 ...

  3. Node.js环境搭建npm安装

    Node.js环境搭建 什么使Node.js呢?我们知道JavaScript开始作为客户端语言,但早已在浏览器端一统江湖,这时,野心越来越大,它就想向服务器端拓展了,于是Node.js就是这样的,我们 ...

  4. 基于 next.js + mdx 搭建组件库文档项目(二) -- mdx 控件封装实现组件的演示与 Props 列表

    说明 经过上阶段的配置虽然可以在项目中使用 mdx 语法 来创建页面了,但是我们的组件库有一些定制化的需求:交互式的组件演示.组件 Props 列表展示.这些功能如果可以通过封装来实现,会大大提升开发 ...

  5. 百度地图 php,php+js实现百度地图多点标注的方法

    本文实例讲述了php+js实现百度地图多点标注的方法.分享给大家供大家参考,具体如下: 1.php创建json数据 $products = $this->product_db->selec ...

  6. 移动端百度地图多点标注php,PHP学习:php+js实现百度地图多点标注的方法

    <PHP学习:php+js实现百度地图多点标注的方法>要点: 本文介绍了PHP学习:php+js实现百度地图多点标注的方法,希望对您有用.如果有疑问,可以联系我们. PHP教程 PHP教程 ...

  7. 用Node.JS+MongoDB搭建个人博客(成品展示)

    在博客里可以随意畅写和分享自己喜欢的技术,和网友分享知识也是一种提升.根据自己所发表的博客也能更加加深印象. 与此同时写博客也可以提高自己的写作能力(虽然不咋地),但我相信博客只会越写越有质量的. 个 ...

  8. go html vue,用Go+Vue.js快速搭建一个Web应用(初级demo)

    Vue.js做为目前前端最热门的库之一,为快速构建并开发前端项目多了一种思维模式.本文给大家介绍用Go+Vue.js快速搭建一个Web应用(初级demo). 环境准备: 1. 安装go语言,配置go开 ...

  9. Lisp尺寸标注增加前后缀_CAD图纸标注添加前后缀的方法

    我们在日常使用CAD软件进行绘图的时候,为了使CAD图纸显示详细,经常会对CAD图纸进行标注.如果需要给CAD图纸的标注添加上前后缀,该如何操作?今天和大家分享一下,CAD图纸标注怎么添加前后缀?具体 ...

最新文章

  1. java url加密解密,java URL 编码解码,该如何解决
  2. Windows XP下如何设置电脑定时关机
  3. Swift 泛型函数补充
  4. Android AsyncTask简单用法
  5. python 字符串分割_如何使用python语言split方法对不同字符串分割
  6. 【semantic】如何理解 web 语义化?
  7. ief12执行一次js才有效_陈列到底多久调一次才有效?
  8. Spring Swagger URL传参问题(转)
  9. 异构广告混排在美团到店业务的探索与实践
  10. kafka 主从同步入门
  11. 21秋期末考试电子商务概论10250k2
  12. 百度地图 android SDKv2.2.0
  13. jmeter压力测试
  14. 读书笔记之《Redis开发与运维》—— 一
  15. 文章翻译软件-批量免费翻译软件支持各大翻译接口
  16. swfupload 无法加载_SwfUpload在IE10上不出现上传按钮的解决方法
  17. 基于ROS的机器人建图与导航仿真全过程
  18. 零基础学C/C++40——鸡兔同笼
  19. 2021WSB-day2-4: Raffaele教授演示利用OpenCV和Python实现一个指纹识别系统 (含代码) part6
  20. Windows 安装 KMS 与 MAK 的区别

热门文章

  1. 网站建设只需要这五步就可以搭建好
  2. 出门问问携手星网云,数字人赋能跨境电商新增长
  3. svn: E200002: line 19: Option expected错误解决
  4. 【对讲机的那点事】玩对讲机你了解TETRA系统吗?
  5. js中三种弹窗的使用
  6. Apollo 入门指导
  7. 栋的周评 | 第六回合(定期更新、动态、架构、云技术、算法、后端、前端、收听/收看、英文、书籍、影视、好歌、新奇)
  8. ospf协议HCIA级别知识点
  9. 达内python人工智能19年大纲_达内Python人工智能编程 入门干货
  10. 程序员MM一年的工作总结