It seems like this should be easy, but I have spent nearly a week on this trying every possible bination of how to drag multiple items as a group in Three.js. It started out simple, I used this example / to get the ball working. I thought I could just add some TextGeometry, which of course had some major API changes in the last couple releases rendering most examples obsolete.
After finally getting it to work as a single line, I wanted to add in wordwrap and move it as a group, but I can't seem to do so.
Here you can see it working just fine with the ball, but you can't drag the text /
By swapping around three lines of code (location line 93-99), I can get it to where you can drag the individual lines around, which you can see here: /
function addText(text, fontSize, boundingWidth) {
var wrapArray;
wrapArray = text.wordwrap(10,2);
var loader = new THREE.FontLoader();
loader.load( '.js-74/examples/fonts/helvetiker_bold.typeface.js',
function ( font ) {
group = new THREE.Group();
group.name = "infoTag";
for (var i = 0; i < wrapArray.length; i++) {
var objectID=i;
var line = wrapArray[objectID];
var textGeo = new THREE.TextGeometry( line, {font: font,size: fontSize,height: 10,curveSegments: 12,bevelThickness: 0.02,bevelSize: 0.05,bevelEnabled: true});
textGeoputeBoundingBox();
var centerOffset = -0.5 * ( textGeo.boundingBox.max.x - textGeo.boundingBox.min.x );
var textMaterial = new THREE.MeshPhongMaterial( { color: 0xff0000, specular: 0xffffff } );
var mesh = new THREE.Mesh( textGeo, textMaterial );
mesh.position.x = centerOffset +200;
mesh.position.y = i*fontSize*-1+11;
mesh.position.z = 280;
mesh.castShadow = true;
mesh.receiveShadow = true;
mesh.geometry.center();
mesh.lookAt(camera.position);
mesh.name = i;
group.add( mesh ); //this should work - ment out and swap for other two lines to see
scene.add(mesh); // this should work- ment out and swap for other two lines to see
//objects.push(mesh);//works on individual lines if you unment this
//scene.add(mesh); //works on individual lines if you unment this
}
objects.push( group ); // this should work- ment out and swap for other two lines to see
});
}
That "should" be working according to everything I had researched over the last week. I had one moment where it was "working" but because of the size of the group
object, the pivot points were wrong, the setLength
function didn't work, and it flipped the object away from the camera. All in all it was a mess.
I did try using 2d objects such as canvases and sprites, but for reasons detailed here Three.js TextGeometry Wordwrap - drag as group couldn't get it working.
Please, someone help me!
It seems like this should be easy, but I have spent nearly a week on this trying every possible bination of how to drag multiple items as a group in Three.js. It started out simple, I used this example https://jsfiddle/mz7Lv9dt/1/ to get the ball working. I thought I could just add some TextGeometry, which of course had some major API changes in the last couple releases rendering most examples obsolete.
After finally getting it to work as a single line, I wanted to add in wordwrap and move it as a group, but I can't seem to do so.
Here you can see it working just fine with the ball, but you can't drag the text https://jsfiddle/ajhalls/h05v48wd/
By swapping around three lines of code (location line 93-99), I can get it to where you can drag the individual lines around, which you can see here: https://jsfiddle/ajhalls/t0e2se3x/
function addText(text, fontSize, boundingWidth) {
var wrapArray;
wrapArray = text.wordwrap(10,2);
var loader = new THREE.FontLoader();
loader.load( 'https://cdn.coursesaver./three.js-74/examples/fonts/helvetiker_bold.typeface.js',
function ( font ) {
group = new THREE.Group();
group.name = "infoTag";
for (var i = 0; i < wrapArray.length; i++) {
var objectID=i;
var line = wrapArray[objectID];
var textGeo = new THREE.TextGeometry( line, {font: font,size: fontSize,height: 10,curveSegments: 12,bevelThickness: 0.02,bevelSize: 0.05,bevelEnabled: true});
textGeo.puteBoundingBox();
var centerOffset = -0.5 * ( textGeo.boundingBox.max.x - textGeo.boundingBox.min.x );
var textMaterial = new THREE.MeshPhongMaterial( { color: 0xff0000, specular: 0xffffff } );
var mesh = new THREE.Mesh( textGeo, textMaterial );
mesh.position.x = centerOffset +200;
mesh.position.y = i*fontSize*-1+11;
mesh.position.z = 280;
mesh.castShadow = true;
mesh.receiveShadow = true;
mesh.geometry.center();
mesh.lookAt(camera.position);
mesh.name = i;
group.add( mesh ); //this should work - ment out and swap for other two lines to see
scene.add(mesh); // this should work- ment out and swap for other two lines to see
//objects.push(mesh);//works on individual lines if you unment this
//scene.add(mesh); //works on individual lines if you unment this
}
objects.push( group ); // this should work- ment out and swap for other two lines to see
});
}
That "should" be working according to everything I had researched over the last week. I had one moment where it was "working" but because of the size of the group
object, the pivot points were wrong, the setLength
function didn't work, and it flipped the object away from the camera. All in all it was a mess.
I did try using 2d objects such as canvases and sprites, but for reasons detailed here Three.js TextGeometry Wordwrap - drag as group couldn't get it working.
Please, someone help me!
Share Improve this question edited May 23, 2017 at 12:31 CommunityBot 11 silver badge asked Mar 30, 2016 at 15:27 AlanAlan 2,0962 gold badges23 silver badges48 bronze badges 2- Hello, I think that if you use an object for join all meshes could works, create a transparent cube or you could use your sphere as main object, add all items into main objects using '.add', all objects move following at parent because they have relative position, in resume you only must move a main object – Juan Caicedo Commented Mar 30, 2016 at 16:19
- I dont understand the question.. you want to be able to drag the whole text around? all three lines at once? Because that seems to be working for me in the second example you linked (the one where you say that you only can drag the ball) – micnil Commented Mar 30, 2016 at 23:42
1 Answer
Reset to default 4The issue ended up being with the group
. Previously I was creating it, adding objects to it with a position.z
which increased the size of the box around the group, then after doing that I moved the box to in front of the camera and did a group.lookAt
which meant that when I was dragging it everything including pivot point and looking at it from the back was wrong. The right way was to create the group, position it, face the camera, then add the text.
function addText(text, fontSize, wrapWidth, tagColor, positionX, positionY, positionZ) {
var wrapArray;
wrapArray = text.wordwrap(wrapWidth,2);
var loader = new THREE.FontLoader();
loader.load( '/js/fonts/helvetiker_bold.typeface.js', function ( font ) {
group = new THREE.Group();
group.position.x=positionX;
group.position.y=positionY;
group.position.z=positionZ;
group.lookAt(camera.position);
group.tourType = "infoTag";
group.name = "infoTag-" + objects.length;
group.dataID=objects.length;
group.textData=text;
for (var i = 0; i < wrapArray.length; i++) {
var objectID=i;
var line = wrapArray[objectID];
var textGeo = new THREE.TextGeometry( line, {
font: font,
size: fontSize,
height: 1,
curveSegments: 12,
bevelThickness: 0.02,
bevelSize: 0.05,
bevelEnabled: true
});
textGeo.puteBoundingBox();
var centerOffset = -0.5 * ( textGeo.boundingBox.max.x - textGeo.boundingBox.min.x );
var textMaterial = new THREE.MeshPhongMaterial( { color: tagColor, specular: 0xffffff } );
var mesh = new THREE.Mesh( textGeo, textMaterial );
mesh.dataID=objects.length;
mesh.position.x = 0;
mesh.position.y = (i*mesh.geometry.boundingBox.max.y*-1)*1.15;
mesh.position.z = 0;
mesh.castShadow = true;
mesh.receiveShadow = true;
mesh.geometry.center();
//mesh.lookAt(camera.position);
mesh.name = "infoTag-mesh-" + objects.length;
group.add( mesh );
}
scene.add(group);
objects.push( group );
});
}
Of course there were some changes to be made in the mouse events to take into account that you want to move the parent of the object, which looks something like this:
function onDocumentMouseDown(event) {
event.preventDefault();
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(objects, true);
if (intersects.length > 0) {
if (intersects[0].object.parent.tourType == 'infoTag') {
var manipulatingInfoTag = true;
SELECTED = intersects[0].object.parent;
}else{
SELECTED = intersects[0].object;
}
var intersects = raycaster.intersectObject(plane);
if (intersects.length > 0) {
offset.copy(intersects[0].point).sub(plane.position);
}
container.style.cursor = 'move';
}
isUserInteracting = true;
onPointerDownPointerX = event.clientX; onPointerDownPointerY = event.clientY; onPointerDownLon = lon; onPointerDownLat = lat;
}