|
|
@ -1,203 +1,205 @@ |
|
|
|
<!DOCTYPE html> |
|
|
|
<html lang="en"> |
|
|
|
<html> |
|
|
|
|
|
|
|
<head> |
|
|
|
<title></title> |
|
|
|
<meta charset="utf-8"> |
|
|
|
<meta name="generator" content="Three.js Editor"> |
|
|
|
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> |
|
|
|
<title>Threejs鼠标点击场景对象获取对象信息,Threejs使用Raycaster拾取对象信息</title> |
|
|
|
<meta charset="UTF-8"> |
|
|
|
<script type="text/javascript" src="libs/statistics.js"></script> |
|
|
|
<script type="text/javascript" src="libs/steak.js"></script> |
|
|
|
<script type="text/javascript" src="libs/three.js"></script> |
|
|
|
<script type="text/javascript" src="libs/OrbitControls.js"></script> |
|
|
|
<style> |
|
|
|
body { |
|
|
|
font-family: sans-serif; |
|
|
|
font-size: 11px; |
|
|
|
background-color: rgb(23, 14, 111); |
|
|
|
margin: 0px; |
|
|
|
} |
|
|
|
|
|
|
|
canvas { |
|
|
|
display: block; |
|
|
|
} |
|
|
|
|
|
|
|
.label { |
|
|
|
color: #FFF; |
|
|
|
font-family: sans-serif; |
|
|
|
padding: 2px; |
|
|
|
background: rgba(255, 0, 0, .6); |
|
|
|
} |
|
|
|
|
|
|
|
.table { |
|
|
|
color: #FFF; |
|
|
|
font-family: sans-serif; |
|
|
|
padding: 2px; |
|
|
|
display: block; |
|
|
|
position: absolute; |
|
|
|
left: 100px; |
|
|
|
top: 150px; |
|
|
|
margin: 0; |
|
|
|
overflow: hidden; |
|
|
|
} |
|
|
|
|
|
|
|
</style> |
|
|
|
<script type="importmap"> |
|
|
|
{ |
|
|
|
"imports": { |
|
|
|
"three": "../build/three.module.js", |
|
|
|
"jsm/": "../examples/jsm/" |
|
|
|
} |
|
|
|
} |
|
|
|
</script> |
|
|
|
</head> |
|
|
|
|
|
|
|
<body ontouchstart=""> |
|
|
|
<div class="table">2d 数据显示位置</div> |
|
|
|
<script type="module"> |
|
|
|
|
|
|
|
import * as THREE from 'three'; |
|
|
|
import { APP } from './js/app.js'; |
|
|
|
import { VRButton } from './js/VRButton.js'; |
|
|
|
|
|
|
|
import { OrbitControls } from 'jsm/controls/OrbitControls.js'; |
|
|
|
import { CSS2DRenderer, CSS2DObject } from '/examples/jsm/renderers/CSS2DRenderer.js'; |
|
|
|
|
|
|
|
|
|
|
|
window.THREE = THREE; // Used by APP Scripts. |
|
|
|
window.VRButton = VRButton; // Used by APP Scripts. |
|
|
|
|
|
|
|
var loader = new THREE.FileLoader(); |
|
|
|
loader.load('app.json', function (text) { |
|
|
|
|
|
|
|
var player = new APP.Player(); |
|
|
|
player.load(JSON.parse(text)); |
|
|
|
player.setSize(window.innerWidth, window.innerHeight); |
|
|
|
player.play(); |
|
|
|
|
|
|
|
document.body.appendChild(player.dom); |
|
|
|
|
|
|
|
window.addEventListener('resize', function () { |
|
|
|
|
|
|
|
player.setSize(window.innerWidth, window.innerHeight); |
|
|
|
|
|
|
|
}); |
|
|
|
var orbitControls = new OrbitControls(window.camera, player.dom); |
|
|
|
initLable(); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
//添加这个就可以用鼠标拖动 |
|
|
|
|
|
|
|
var raycaster = new THREE.Raycaster() |
|
|
|
var mouse = new THREE.Vector2() |
|
|
|
//点击模型 |
|
|
|
window.addEventListener('click', onMouseClick); |
|
|
|
|
|
|
|
function onMouseClick(event) { |
|
|
|
|
|
|
|
//将鼠标点击位置的屏幕坐标转换成threejs中的标准坐标 |
|
|
|
mouse.x = (event.clientX / window.innerWidth) * 2 - 1 |
|
|
|
mouse.y = -((event.clientY / window.innerHeight) * 2 - 1) |
|
|
|
//console.log("mouse:"+mouse.x+","+mouse.y) |
|
|
|
|
|
|
|
// 通过鼠标点的位置和当前相机的矩阵计算出raycaster |
|
|
|
raycaster.setFromCamera(mouse, window.camera); |
|
|
|
<body> |
|
|
|
<div id="dom"></div> |
|
|
|
<script type="text/javascript"> |
|
|
|
var camera; |
|
|
|
var renderer; |
|
|
|
var length = 36; |
|
|
|
var ws = 2; |
|
|
|
var graph = []; |
|
|
|
var mesh = []; |
|
|
|
|
|
|
|
function init() { |
|
|
|
// 创建一个场景,它将包含我们所有的元素,如物体,相机和灯光。 |
|
|
|
var scene = new THREE.Scene(); |
|
|
|
|
|
|
|
var urls = [ |
|
|
|
'assets/bgImage/skyBox4/posx.jpg', |
|
|
|
'assets/bgImage/skyBox4/negx.jpg', |
|
|
|
'assets/bgImage/skyBox4/posy.jpg', |
|
|
|
'assets/bgImage/skyBox4/negy.jpg', |
|
|
|
'assets/bgImage/skyBox4/posz.jpg', |
|
|
|
'assets/bgImage/skyBox4/negz.jpg' |
|
|
|
]; |
|
|
|
|
|
|
|
var cubeLoader = new THREE.CubeTextureLoader(); |
|
|
|
scene.background = cubeLoader.load(urls); |
|
|
|
|
|
|
|
// 创建一个摄像机,它定义了我们正在看的地方 |
|
|
|
camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 0.1, 1000); |
|
|
|
// 将摄像机对准场景的中心 |
|
|
|
camera.position.x = 60; |
|
|
|
camera.position.y = 35; |
|
|
|
camera.position.z = 60; |
|
|
|
camera.lookAt(scene.position); |
|
|
|
var orbit = new THREE.OrbitControls(camera); |
|
|
|
|
|
|
|
// 创建一个渲染器并设置大小,WebGLRenderer将会使用电脑显卡来渲染场景 |
|
|
|
// initialize basic renderer |
|
|
|
renderer = new THREE.WebGLRenderer(); |
|
|
|
renderer.setSize(window.innerWidth, window.innerHeight); |
|
|
|
|
|
|
|
// 将平面添加到场景中 |
|
|
|
var plane = createPlaneGeometryBasicMaterial(); |
|
|
|
scene.add(plane); |
|
|
|
|
|
|
|
// 在屏幕上显示坐标轴 |
|
|
|
var axes = new THREE.AxesHelper(100); |
|
|
|
scene.add(axes); |
|
|
|
scene.add(new THREE.AmbientLight(0x666666)); |
|
|
|
scene.add(new THREE.AmbientLight("#ffffff", 1)); |
|
|
|
document.getElementById("dom").appendChild(renderer.domElement); |
|
|
|
|
|
|
|
initGround(); |
|
|
|
initGrid(); |
|
|
|
|
|
|
|
// 启动动画 |
|
|
|
renderScene(); |
|
|
|
|
|
|
|
// 创建一个地面 |
|
|
|
function createPlaneGeometryBasicMaterial() { |
|
|
|
var textureLoader = new THREE.TextureLoader(); |
|
|
|
var cubeMaterial = new THREE.MeshStandardMaterial({ |
|
|
|
map: textureLoader.load("assets/textures/cd.jpg"), |
|
|
|
}); |
|
|
|
cubeMaterial.map.wrapS = THREE.RepeatWrapping; |
|
|
|
cubeMaterial.map.wrapT = THREE.RepeatWrapping; |
|
|
|
cubeMaterial.map.repeat.set(18, 18) |
|
|
|
// 创建地平面并设置大小 |
|
|
|
var planeGeometry = new THREE.PlaneGeometry(500, 500); |
|
|
|
var plane = new THREE.Mesh(planeGeometry, cubeMaterial); |
|
|
|
|
|
|
|
// 设置平面位置并旋转 |
|
|
|
plane.rotation.x = -0.5 * Math.PI; |
|
|
|
plane.position.x = 0; |
|
|
|
plane.position.z = 0; |
|
|
|
return plane; |
|
|
|
} |
|
|
|
|
|
|
|
// 获取raycaster直线和所有模型相交的数组集合 |
|
|
|
var intersects = raycaster.intersectObjects(scene.children); |
|
|
|
console.log(intersects); |
|
|
|
// debugger |
|
|
|
//将所有的相交的模型的颜色设置为红色 |
|
|
|
for (var i = 0; i < intersects.length; i++) { |
|
|
|
let obj = intersects[i]; |
|
|
|
if (obj.object) { |
|
|
|
// 初始化线路 |
|
|
|
function initLine(pArr) { |
|
|
|
var points = []; |
|
|
|
var geometry = new THREE.Geometry(); |
|
|
|
for (var i = 0; i < pArr.length; i++) { |
|
|
|
var randomX = pArr[i].x; |
|
|
|
var randomY = pArr[i].y; |
|
|
|
var randomZ = pArr[i].z; |
|
|
|
var vector = new THREE.Vector3(randomX, randomY, randomZ); |
|
|
|
geometry.vertices.push(vector); |
|
|
|
points.push(vector); |
|
|
|
} |
|
|
|
var material = new THREE.LineBasicMaterial({ |
|
|
|
color: 0x0000FF |
|
|
|
}); |
|
|
|
var line = new THREE.Line(geometry, material); |
|
|
|
scene.add(line); |
|
|
|
return points; |
|
|
|
} |
|
|
|
|
|
|
|
if (obj.object.name == "视频监控1") { |
|
|
|
// 绘制路网 |
|
|
|
function initGround() { |
|
|
|
var geometry = new THREE.Geometry(); |
|
|
|
geometry.vertices.push(new THREE.Vector3(0, 0, 0)); |
|
|
|
geometry.vertices.push(new THREE.Vector3(length, 0, 0)); |
|
|
|
|
|
|
|
for (var i = 0; i <= length / ws; i++) { |
|
|
|
var material = new THREE.LineBasicMaterial({ |
|
|
|
color: 0x808080 |
|
|
|
}); |
|
|
|
var line = new THREE.Line(geometry, material); |
|
|
|
line.position.z = i * ws; |
|
|
|
scene.add(line); |
|
|
|
|
|
|
|
var line = new THREE.Line(geometry, material); |
|
|
|
line.position.x = i * ws; |
|
|
|
line.position.z = length; |
|
|
|
line.rotation.y = 90 * Math.PI / 180; |
|
|
|
scene.add(line); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
obj.object.material[0].color.set(0xff6666); |
|
|
|
alert("视频"); |
|
|
|
} else { |
|
|
|
obj.object.material[0].color.set(0xff0000); |
|
|
|
// 初始化障碍物 |
|
|
|
function initGrid() { |
|
|
|
for (var i = 0; i < length / ws; i++) { |
|
|
|
var nodeRow = []; |
|
|
|
for (var j = 0; j < length / ws; j++) { |
|
|
|
var salt = Math.random() * 7; |
|
|
|
if (salt > 2) { |
|
|
|
nodeRow.push(1); |
|
|
|
} else { |
|
|
|
nodeRow.push(0); |
|
|
|
} |
|
|
|
if (salt <= 2) { |
|
|
|
var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1), new THREE.MeshBasicMaterial({ |
|
|
|
color: 0xC0C0C0 |
|
|
|
})); |
|
|
|
let x = ws * j + ws / 2; |
|
|
|
let z = ws * i + ws / 2; |
|
|
|
cube.position.set(x, 1.2, z); |
|
|
|
scene.add(cube); |
|
|
|
mesh.push(cube); |
|
|
|
} |
|
|
|
} |
|
|
|
graph.push(nodeRow); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function createCSSLabel(text, parent) { |
|
|
|
|
|
|
|
const labelDiv = document.createElement('div'); |
|
|
|
labelDiv.className = 'label'; |
|
|
|
labelDiv.name = "csslabeldiv" |
|
|
|
labelDiv.textContent = text; |
|
|
|
|
|
|
|
labelDiv.style.pointerEvents = 'none';//避免HTML标签遮挡三维场景的鼠标事件 |
|
|
|
const moonLabel = new CSS2DObject(labelDiv); |
|
|
|
moonLabel.position.set(1, 2, 0); |
|
|
|
moonLabel.name = "datalabel" |
|
|
|
moonLabel.userData = { name: "datalable", id: "", url: "" } |
|
|
|
return moonLabel; |
|
|
|
|
|
|
|
} |
|
|
|
const css2DLabelList = [] |
|
|
|
function addLabel(obj, scene, i) { |
|
|
|
|
|
|
|
const labelDiv = document.createElement('div'); |
|
|
|
labelDiv.className = 'label'; |
|
|
|
labelDiv.name = "label" + i; |
|
|
|
labelDiv.textContent = obj.text; |
|
|
|
|
|
|
|
|
|
|
|
labelDiv.style.pointerEvents = 'none';//避免HTML标签遮挡三维场景的鼠标事件 |
|
|
|
const css2DLabel = new CSS2DObject(labelDiv); |
|
|
|
css2DLabel.position.set(obj.x, obj.y, obj.z); |
|
|
|
css2DLabel.name = "datalabel" + i; |
|
|
|
css2DLabel.userData = { name: "datalable", id: "", url: "" } |
|
|
|
// css2DLabelList.add(css2DLabel); |
|
|
|
scene.add(css2DLabel); |
|
|
|
document.addEventListener('click', onDocumentMouseDown, false); |
|
|
|
|
|
|
|
function onDocumentMouseDown(event) { |
|
|
|
// 点击屏幕创建一个向量 |
|
|
|
var vector = new THREE.Vector3((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window |
|
|
|
.innerHeight) * 2 + 1, 0.5); |
|
|
|
vector = vector.unproject(camera); // 将屏幕的坐标转换成三维场景中的坐标 |
|
|
|
var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize()); |
|
|
|
var intersects = raycaster.intersectObjects(mesh, true); |
|
|
|
if (intersects.length > 0) { |
|
|
|
intersects[0].object.material.color.set("#ff0000"); |
|
|
|
alert(JSON.stringify(intersects[0])) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
function initLable() { |
|
|
|
const labobjarr = [{ text: "测试标签1", x: -1, y: 1, z: 1 }, { text: "测试标签2", x: 10, y: 10, z: 10 }] |
|
|
|
for (var i = 0, length = labobjarr.length; i < length; i++) { |
|
|
|
// 动画渲染 |
|
|
|
var step = 5; |
|
|
|
|
|
|
|
addLabel(labobjarr[i], window.scene, i); |
|
|
|
function renderScene() { |
|
|
|
orbit.update(); |
|
|
|
|
|
|
|
// 使用requestAnimationFrame函数进行渲染 |
|
|
|
requestAnimationFrame(renderScene); |
|
|
|
renderer.render(scene, camera); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
</script> |
|
|
|
<!-- Code injected by live-server --> |
|
|
|
<script> |
|
|
|
// <![CDATA[ <-- For SVG support |
|
|
|
if ('WebSocket' in window) { |
|
|
|
(function () { |
|
|
|
function refreshCSS() { |
|
|
|
var sheets = [].slice.call(document.getElementsByTagName("link")); |
|
|
|
var head = document.getElementsByTagName("head")[0]; |
|
|
|
for (var i = 0; i < sheets.length; ++i) { |
|
|
|
var elem = sheets[i]; |
|
|
|
var parent = elem.parentElement || head; |
|
|
|
parent.removeChild(elem); |
|
|
|
var rel = elem.rel; |
|
|
|
if (elem.href && typeof rel != "string" || rel.length == 0 || rel.toLowerCase() == "stylesheet") { |
|
|
|
var url = elem.href.replace(/(&|\?)_cacheOverride=\d+/, ''); |
|
|
|
elem.href = url + (url.indexOf('?') >= 0 ? '&' : '?') + '_cacheOverride=' + (new Date().valueOf()); |
|
|
|
} |
|
|
|
parent.appendChild(elem); |
|
|
|
} |
|
|
|
} |
|
|
|
var protocol = window.location.protocol === 'http:' ? 'ws://' : 'wss://'; |
|
|
|
var address = protocol + window.location.host + window.location.pathname + '/ws'; |
|
|
|
var socket = new WebSocket(address); |
|
|
|
socket.onmessage = function (msg) { |
|
|
|
if (msg.data == 'reload') window.location.reload(); |
|
|
|
else if (msg.data == 'refreshcss') refreshCSS(); |
|
|
|
}; |
|
|
|
if (sessionStorage && !sessionStorage.getItem('IsThisFirstTime_Log_From_LiveServer')) { |
|
|
|
console.log('Live reload enabled.'); |
|
|
|
sessionStorage.setItem('IsThisFirstTime_Log_From_LiveServer', true); |
|
|
|
} |
|
|
|
})(); |
|
|
|
// 渲染的场景 |
|
|
|
renderer.render(scene, camera); |
|
|
|
} |
|
|
|
else { |
|
|
|
console.error('Upgrade your browser. This Browser is NOT supported WebSocket for Live-Reloading.'); |
|
|
|
window.onload = init; |
|
|
|
|
|
|
|
function onResize() { |
|
|
|
camera.aspect = window.innerWidth / window.innerHeight; |
|
|
|
camera.updateProjectionMatrix(); |
|
|
|
renderer.setSize(window.innerWidth, window.innerHeight); |
|
|
|
} |
|
|
|
// ]]> |
|
|
|
// 监听调整大小事件 |
|
|
|
window.addEventListener('resize', onResize, false); |
|
|
|
</script> |
|
|
|
</body> |
|
|
|
|
|
|
|