我正在将three.js用于图形网站。
它的概念是有很多文字的宇宙。
如果我单击文本,无论距离多远,物体都必须移动到固定位置(或相机的前部)
所以我写了这样的代码。
[index.html]
<html>
<head>
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="https://gitcdn.xyz/repo/thesmart/jquery-scrollspy/0.1.3/scrollspy.js"></script>
<script src="./src/WOW.js"></script>
<script src="./src/three.js"></script>
<script src="//cdn.rawgit.com/mrdoob/three.js/master/examples/js/loaders/ColladaLoader.js"></script>
<script src="https://unpkg.com/three.texttexture"></script>
<script src="https://unpkg.com/three.textsprite"></script>
<script src="./src/DeviceOrientationControls.js"></script>
<script src="./src/hammer.js"></script>
<script src="./src/Detector.js"></script>
<script src="./src/perlin.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<link rel="stylesheet" href="animate.css">
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1">
<meta charset="UTF-8">
</head>
<body>
<header>
<div class="header-left">
<a href="#loading-screen" onclick="topFunction()">MAIN</a>
</div>
<div class="header-right">
<a href="#">MISSION</a>
<a href="#section1">PRODUCT</a>
<a href="#">CULTURE</a>
<a href="#">STORY</a>
</div>
</header>
<main>
<!-- Universe -->
<section id="universe" class="wow" data-wow-duration="0.5s"></section>
<!-- Main -->
<section class="main" id="main">
</section>
<script src="./src/src.js"></script>
</main>
</body>
</html>
[src.js]
// VARIABLES
let clock, camera, scene, renderer, mixer;
const sleep = ms => new Promise(res => setTimeout(res, ms));
var myElement = document.getElementById("threejs");
const mouse = new THREE.Vector2();
const clicked = new THREE.Vector2();
const target = new THREE.Vector2();
const windowHalf = new THREE.Vector2( window.innerWidth / 2, window.innerHeight / 2 );
const moveState = {forward: 0, back: 0};
var isMobile = false;
var textCount = 500;
var firstTime = true;
var fontFamily = '"Courier New", Courier, monospace';
var lock = true;
var group = new THREE.Group();
const scrollPosition = document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop;
checkMobile()
// WOW.js
var wow = new WOW();
wow.init();
init();
async function init() {
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
scene = new THREE.Scene();
// CAMERA
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2100 );
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 1200;
camera.lookAt(scene.position);
clock = new THREE.Clock();
// HELPER
const gridHelper = new THREE.PolarGridHelper( 8, 16 );
scene.add( gridHelper );
// LIGHT
const ambientLight = new THREE.AmbientLight( 0xffffff, 0.2 );
scene.add( ambientLight );
const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.8 );
directionalLight.position.set( 1, 1, - 1 );
scene.add( directionalLight );
// CONTROLS
if(isMobile) { // 모바일이면
var controls = new THREE.DeviceOrientationControls(camera);
console.log('isMobile true');
} else {
console.log('isMobile false');
}
// SATISFY THE DESIRES OF LOVE
let sprite = new THREE.TextSprite({
textSize: 5,
redrawInterval: 250,
texture: {
text: 'MAIN TEST',
fontFamily: fontFamily,
},
material: {
color: 'white',
},
});
sprite.position.x = 0;
sprite.position.y = 0;
sprite.position.z = 10;
scene.add(sprite);
// ADD MESH
var size = ( isMobile ? 2 : 2 );
var starsLights = new THREE.Group();
var starGeometry = new THREE.SphereGeometry(0.3, 16, 16);
var emptyGeometry = new THREE.Geometry();
for ( let i = 0; i < textCount; i ++ ) {
var lod = new THREE.LOD();
// Text
let sprite = new THREE.TextSprite({
textSize: size,
redrawInterval: 250,
texture: {
text: 'For Test',
fontFamily: fontFamily,
},
material: {
color: 'white',
transparent: true,
},
});
// Star
var starMaterial = new THREE.MeshBasicMaterial({color: 0xffffff, transparent: true});
var star = new THREE.Mesh(starGeometry, starMaterial);
// Dummy
var dummy = new THREE.Mesh(emptyGeometry, new THREE.MeshBasicMaterial());
// Add
lod.addLevel(sprite, 1);
lod.addLevel(star, 100, 240);
lod.addLevel(dummy, 200, 300);
lod.position.x = (Math.random() * 180-100);
lod.position.y = Math.random() * 180-100;
lod.position.z = Math.random() * 1000-40;
group.add(lod);
}
scene.add(group);
// Renderer
renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.getElementById("universe").appendChild(renderer.domElement);
// Event handler
window.addEventListener('load', refreshCheck, false);
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousemove', onMouseMove, false);
document.addEventListener('mousewheel', onMouseWheel, false);
document.addEventListener('contextmenu', onContextMenu, false);
document.addEventListener('mouseup', onMouseClick, false);
function animate() {
target.x = ( 1 - mouse.x ) * 0.002;
target.y = ( 1 - mouse.y ) * 0.002;
camera.rotation.x += 0.05 * ( target.y - camera.rotation.x );
camera.rotation.y += 0.05 * ( target.x - camera.rotation.y );
if(isMobile) {
controls.update();
}
// Object change related to distance
group.children.forEach(function(child) {
child.update(camera);
})
// Render
requestAnimationFrame( animate );
render(scene, camera);
}
animate();
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onMouseWheel(event) {
event.preventDefault();
camera.position.z -= event.deltaY * 0.2;
}
function render() {
const delta = clock.getDelta();
if ( mixer !== undefined ) mixer.update( delta );
renderer.render( scene, camera );
}
function onTransitionEnd( event ) {
console.log("Loading Complete");
event.target.remove();
}
// Exist functions
function checkMobile() {
var UserAgent = navigator.userAgent;
if (UserAgent.match(/iPhone|iPod|Android|Windows CE|BlackBerry|Symbian|Windows Phone|webOS|Opera Mini|Opera Mobi|POLARIS|IEMobile|lgtelecom|nokia|SonyEricsson/i) != null || UserAgent.match(/LG|SAMSUNG|Samsung/) != null) {
isMobile = true;
} else {
isMobile = false;
}
}
var raycaster = new THREE.Raycaster();
var mouseVector = new THREE.Vector3();
function getIntersects( x, y ) {
x = ( x / window.innerWidth ) * 2 - 1;
y = - ( y / window.innerHeight ) * 2 + 1;
mouseVector.set( x, y, 0.5 );
raycaster.setFromCamera( mouseVector, camera );
return raycaster.intersectObject( group, true );
}
var selectedObject = null;
var intersects;
function onMouseMove(event) {
event.preventDefault();
mouse.x = ( (event.clientX/2) - (windowHalf.x/2) );
mouse.y = ( (event.clientY/2) - (windowHalf.y/2) );
clicked.x = ( event.clientX / window.innerWidth ) * 2 - 1;
clicked.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
// Select object
if ( selectedObject ) {
selectedObject.material.color.set( '#ffffff' );
selectedObject = null;
}
intersects = getIntersects( event.layerX, event.layerY );
if ( intersects.length > 0 ) {
var res = intersects.filter( function ( res ) {
return res && res.object;
} )[ 0 ];
if ( res && res.object ) {
selectedObject = res.object;
selectedObject.material.color.set( '#f00' );
}
}
}
function onMouseClick() {
if(intersects[0]) {
console.log(intersects[0].point);
intersects[0].object.position.z += intersects[0].distance-70;
intersects[0].object.position.x = 0;
intersects[0].object.position.y = 0;
}
}
function onResize(event) {
const width = window.innerWidth;
const height = window.innerHeight;
windowHalf.set( width / 2, height / 2 );
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize( width, height );
}
function onContextMenu(event) { // Mouse right click
event.preventDefault();
}
function refreshCheck() {
if(window.performance) {
if(performance.navigation.type === 1) {
setTimeout(() => {
document.body.scrollTop = 0; // Other Browser
document.documentElement.scrollTop = 0; // IE
}, 0);
}
}
}
在onMouseWheel()
函数中,我检测当前光标是否指向对象。
因此,对象的信息将存储在var intersects
中。
还要添加onMouseClick()
。在该函数内部,我这样更改对象的位置。
if(intersects[0]) {
console.log(intersects[0].point);
intersects[0].object.position.z += intersects[0].distance-70;
intersects[0].object.position.x = 0;
intersects[0].object.position.y = 0;
}
因此,如果单击对象,则对象的x,y,z坐标将更改为0、0,距离70。
但这不适用于场景。
请访问此网站https://50-jahre-hitparade.ch/
如果您单击文本,文本将移到相机的前面。
我的目标是像上面的网站一样。
为什么在我的代码中不起作用?
这里有解决方案吗?
谢谢。
(也许我必须更新为animate()吗?)
答案 0 :(得分:0)
代替
if(intersects[0]) {
intersects[0].point.z = 100;
intersects[0].point.x = 100;
intersects[0].point.y = 100;
}
尝试像这样更改intersects[0].object.position
的位置,
if(intersects[0]) {
intersects[0].object.position.z = 100;
intersects[0].object.position.x = 100;
intersects[0].object.position.y = 100;
}