无法使Three.js onDocumentMouseDown正常工作 [英] Can't get Three.js onDocumentMouseDown to work correctly
问题描述
我看了很多示例-并从中借来了一些-似乎无法使其正常工作.我想要的是让onDocumentMouseDown中的raycaster在用户单击Sprite可见表面上的任意位置时拾取Sprite.我得到的是未对齐的结果,因为如果用户在精灵的上方,下方或下方单击一些,则可能会拾取该精灵,如果用户单击左侧边缘,则根本不会拾取它精灵的所以基本上有些事情是错位的,而我弄不清自己在做什么错.任何指导将不胜感激.
I've looked at a lot of examples -- and borrowed from some -- and can't seem to get this to work right. What I want is for the raycaster in onDocumentMouseDown to pick up sprites when the user clicks anywhere on the visible surface of a sprite. What I'm getting is a misaligned result, in that a sprite may be picked up if the user clicks somewhat to the right, above, or below the sprite, and will not pick it up at all if the user clicks on the left edge of the sprite. So basically something is misaligned, and I am at a loss for figuring out what I am doing wrong. Any guidance would be appreciated.
<script src="/common/three.js"></script>
<script src="/common/Detector.js"></script>
<script src="/common/CanvasRenderer.js"></script>
<script src="/common/GeometryUtils.js"></script>
<script src="/common/OrbitControls.js"></script>
<div id="WebGLCanvas"></div>
<script>
var container, scene, camera, renderer, controls;
var keyboard;
</script>
<script>
// custom global variables
var mouse = { x: 0, y: 0 };
var raycaster;
var sprites = new Array();
init();
try {
for (i = 0; i < 10; i++) {
var text = "Text " + i;
var x = Math.random() * 100;
var y = Math.random() * 100;
var z = Math.random() * 100;
var spritey = addOrUPdateSprite(text, i, x, y, z);
}
}
catch (ex) {
alert("error when creating sprite: " + ex.message);
}
animate();
function init() {
try {
scene = new THREE.Scene();
// CAMERA
var cont = document.getElementById("WebGLCanvas");
var SCREEN_WIDTH = window.innerWidth;
OFFSET_TOP = document.getElementById("WebGLCanvas").getBoundingClientRect().top;
var SCREEN_HEIGHT = window.innerHeight - OFFSET_TOP; //; //-document.getElementById("upper").clientHeight;
var VIEW_ANGLE = 60;
var ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT;
var NEAR = 0.1;
var FAR = 1000;
camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
scene.add(camera);
camera.position.set(0, 100, 200);
camera.lookAt(new THREE.Vector3());
renderer = new THREE.WebGLRenderer({ antialias: true });
container = document.getElementById('WebGLCanvas');
container.appendChild(renderer.domElement);
renderer.setSize(window.innerWidth, SCREEN_HEIGHT);
controls = new THREE.OrbitControls(camera, renderer.domElement);
// spritey.position.normalize();
raycaster = new THREE.Raycaster();
document.addEventListener('mousedown', onDocumentMouseDown, false);
document.addEventListener('touchstart', onDocumentTouchStart, false);
}
catch (ex) {
alert("error " + ex.message);
}
}
function animate() {
requestAnimationFrame(animate);
render();
update();
}
function update() {
controls.update();
}
function render() {
renderer.render(scene, camera);
}
function addOrUPdateSprite(text, name, x, y, z) {
var sprite = scene.getObjectByName(name);
if (sprite == null) {
sprite = makeTextSprite(text, { fontsize: 36, borderColor: { r: 255, g: 0, b: 0, a: 1.0 }, backgroundColor: { r: 255, g: 100, b: 100, a: 0.8 } });
sprite.name = name;
sprites.push(sprite);
scene.add(sprite);
}
sprite.position.set(x, y, z);
}
function makeTextSprite(message, parameters) {
if (parameters === undefined) parameters = {};
var fontface = parameters.hasOwnProperty("fontface") ? parameters["fontface"] : "sans-serif";
var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 36;
var borderThickness = parameters.hasOwnProperty("borderThickness") ? parameters["borderThickness"] : 1;
var borderColor = parameters.hasOwnProperty("borderColor") ? parameters["borderColor"] : { r: 0, g: 0, b: 0, a: 1.0 };
var backgroundColor = parameters.hasOwnProperty("backgroundColor") ? parameters["backgroundColor"] : { r: 255, g: 255, b: 255, a: 1.0 };
var textColor = parameters.hasOwnProperty("textColor") ? parameters["textColor"] : { r: 0, g: 0, b: 0, a: 1.0 };
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
context.font = fontsize + "px " + fontface;
var metrics = context.measureText(message);
var textWidth = metrics.width;
context.fillStyle = "rgba(" + backgroundColor.r + "," + backgroundColor.g + "," + backgroundColor.b + "," + backgroundColor.a + ")";
context.strokeStyle = "rgba(" + borderColor.r + "," + borderColor.g + "," + borderColor.b + "," + borderColor.a + ")";
context.lineWidth = borderThickness;
roundRect(context, borderThickness / 2, borderThickness / 2, (textWidth + borderThickness) * 1.1, fontsize * 1.4 + borderThickness, 8);
context.fillStyle = "rgba(" + textColor.r + ", " + textColor.g + ", " + textColor.b + ", 1.0)";
context.fillText(message, borderThickness, fontsize + borderThickness);
var texture = new THREE.Texture(canvas)
texture.needsUpdate = true;
var spriteMaterial = new THREE.SpriteMaterial({ map: texture, useScreenCoordinates: false });
var sprite = new THREE.Sprite(spriteMaterial);
sprite.scale.set(1.0 * fontsize, 0.5 * fontsize, 1.5 * fontsize);
return sprite;
}
// function for drawing rounded rectangles
function roundRect(ctx, x, y, w, h, r) {
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.lineTo(x + w - r, y);
ctx.quadraticCurveTo(x + w, y, x + w, y + r);
ctx.lineTo(x + w, y + h - r);
ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
ctx.lineTo(x + r, y + h);
ctx.quadraticCurveTo(x, y + h, x, y + h - r);
ctx.lineTo(x, y + r);
ctx.quadraticCurveTo(x, y, x + r, y);
ctx.closePath();
ctx.fill();
ctx.stroke();
}
function onDocumentTouchStart(event) {
event.preventDefault();
event.clientX = event.touches[0].clientX;
event.clientY = event.touches[0].clientY;
onDocumentMouseDown(event);
}
function onDocumentMouseDown(event) {
mouse.x = (event.clientX / renderer.domElement.clientWidth) * 2 - 1;
mouse.y = -((event.clientY) / renderer.domElement.clientHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(sprites, true);
if (intersects.length > 0) {
var obj = intersects[0].object;
alert(obj.name);
event.preventDefault();
}
}
</script>
推荐答案
在您的 makeTextSprite()
函数中,
var textWidth = metrics.width;
添加此
context.strokeStyle = "white";
context.lineWidth = 5;
context.strokeRect(0,0,canvas.width, canvas.height);
您会看到,您的精灵没有您想像的大小.
and you will see, that your sprites have not the size you think of.
UPD.您可以像这样设置画布的大小
UPD. You can set the size of a canvas like this
var ctxFont = "bold " + fontsize + "px " + fontface;
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
context.font = ctxFont;
var metrics = context.measureText(message);
var textWidth = metrics.width;
canvas.width = textWidth + borderThickness * 2;
canvas.height = fontsize * 1.2 + (borderThickness * 2);
context = canvas.getContext('2d');
context.font = ctxFont;
然后设置精灵的比例
sprite.scale.set(canvas.width / 10, canvas.height / 10, 1);
jsfiddle 示例
这篇关于无法使Three.js onDocumentMouseDown正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!