Currently seeking a solution to wrap text around a sphere in either Babylon or Three.js. I am willing to explore different JavaScript technologies for this task.
Currently seeking a solution to wrap text around a sphere in either Babylon or Three.js. I am willing to explore different JavaScript technologies for this task.
To generate text, explore this example. Each letter can be generated individually with their widths recorded to calculate the total width of the string to display.
You can then group each mesh under an Object3D
and adjust its rotation y using the following code:
widthSoFar = 0;
for each letter
obj3d.rotation.y = widthSoFar / totalWidth * Math.PI * 2;
widthSoFar += widthOfCurrentLetter;
The letters' position.z can be set to a radius to form them around a circle.
For the radius calculation:
circumference = 2 * PI * radius
thus,
radius = circumference / (2 * PI)
Given that the needed circumference is the total width of the string.
If you want more guidance on organizing nodes within a scene graph, check out this tutorial.
'use strict';
/* global THREE */
function main() {
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas});
const fov = 40;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 1000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 70;
const scene = new THREE.Scene();
scene.background = new THREE.Color('black');
function addLight(...pos) {
const color = 0xFFFFFF;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(...pos);
scene.add(light);
}
addLight(-4, 4, 4);
addLight(5, -4, 4);
const lettersTilt = new THREE.Object3D();
scene.add(lettersTilt);
lettersTilt.rotation.set(
THREE.Math.degToRad(-15),
0,
THREE.Math.degToRad(-15));
const lettersBase = new THREE.Object3D();
lettersTilt.add(lettersBase);
{
const letterMaterial = new THREE.MeshPhongMaterial({
color: 'red',
});
const loader = new THREE.FontLoader();
loader.load('https://threejsfundamentals.org/threejs/resources/threejs/fonts/helvetiker_regular.typeface.json', (font) => {
const spaceSize = 1.0;
let totalWidth = 0;
let maxHeight = 0;
const letterGeometries = {
' ': { width: spaceSize, height: 0 }, // prepopulate space ' '
};
const size = new THREE.Vector3();
const str = 'threejs fundamentals ';
const letterInfos = str.split('').map((letter, ndx) => {
if (!letterGeometries[letter]) {
const geometry = new THREE.TextBufferGeometry(letter, {
font: font,
size: 3.0,
height: .2,
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 0.5,
bevelSize: .3,
bevelSegments: 5,
});
geometry.computeBoundingBox();
geometry.boundingBox.getSize(size);
letterGeometries[letter] = {
geometry,
width: size.x / 2, // no idea why size.x is double size
height: size.y,
};
}
const {geometry, width, height} = letterGeometries[letter];
const mesh = geometry
? new THREE.Mesh(geometry, letterMaterial)
: null;
totalWidth += width;
maxHeight = Math.max(maxHeight, height);
return {
mesh,
width,
};
});
let t = 0;
const radius = totalWidth / Math.PI;
for (const {mesh, width} of letterInfos) {
if (mesh) {
const offset = new THREE.Object3D();
lettersBase.add(offset);
offset.add(mesh);
offset.rotation.y = t / totalWidth * Math.PI * 2;
mesh.position.z = radius;
mesh.position.y = -maxHeight / 2;
}
t += width;
}
{
const geo = new THREE.SphereBufferGeometry(radius - 1, 32, 24);
const mat = new THREE.MeshPhongMaterial({
color: 'cyan',
});
const mesh = new THREE.Mesh(geo, mat);
scene.add(mesh);
}
camera.position.z = radius * 3;
});
}
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function render(time) {
time *= 0.001;
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
lettersBase.rotation.y = time * -0.5;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();
body {
margin: 0;
}
#c {
width: 100vw;
height: 100vh;
display: block;
}
<canvas id="c"></canvas>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/three.min.js"></script>
How can I utilize the Post component in a way that assigns unique classes to new and old posts following BEM recommendations? Assign a unique className to every element Avoid cascading dependencies like (.posts-new post or .posts-old post) Each component ...
Having just started working with redux-saga, I'm encountering an issue where I can't seem to be redirected back to the login page after successfully creating an account. Even though I've implemented the necessary code for redirection, I keep ...
When resizing the window, I am facing an issue with the image going outside of the box. I believe adjusting the position top of the image based on the box height might help in fitting the image properly within the box. $(window).resize(function() { va ...
Here is the data I received from an API: { "data": { "City": { "zip": "75000", "appointment": { "2020-10-12": { "08:00:00": 3, "09:15:0 ...
When encountering a date format in en-GB or European style (mm.dd.yyyy), it should be converted to the en-US format (mm/dd/yyyy). If the date is not already in en-US format, then it needs to be converted accordingly. ...
Having trouble with my first generation iPad while trying to implement a basic ngRoute and ngAnimate setup. It's working fine on desktop and iPhone 6, but not on the iPad. The error message I'm encountering is: Error[$injector:modulerr]http://e ...
Could someone assist me in identifying the issue with this code that only displays the same image, tree.png, three times? var bankImages = ["troyano", "backup", "tree"]; jQuery.each( bankImages, function( i, val ) { $('#imagesCon ...
I am in search of a solution that will allow an AJAX API call to finish before the containing function does without relying on jQuery as a dependency for just one REST call... After going through multiple solutions, all of which involve using jQuery, I ca ...
After transforming an XML file with xsl and loading it into a browser as html, I am making the html editable using the content editable attribute of html5. How can I transform their edits back to the original xml document, even if they add new nodes to e ...
I'm having trouble finding a solution to this issue, as the form data is not being output. var app = angular.module('myApp', []); app.controller('mainController', ['$scope', function($scope) { $scope.update = funct ...
In my current project using Sails.js (built on top of Express), I encountered an issue with sending a form input named length with a value of '1000'. Here is how it was implemented: <select name="length"> <option value="1000">100 ...
I am a beginner in AngularJS and I am trying to grasp its concepts by studying example codes. Currently, I have found an interesting code snippet that involves the $http.get function. You can find it here: I attempted to replace the URL with my own, but ...
Hello, I am currently working on creating a system where my index page refreshes when a value in my database is set to 1. However, I am having trouble with the code as only my index.php is not refreshing. index.php <script> interval_timer = setInt ...
I have the need to save favorite and deleted IDs in my database. I created two functions for this purpose: function ADD_BLOCKED(id) { chrome.storage.local.get("blocked", function (data) { if (data.blocked == null) data.blocked = [] ...
I have implemented a form that allows users to select an item from a multi-select dropdown (A). If the desired item is not listed, users can manually add it using another text input box (B). Once added, an AJAX call saves the item to the database. After su ...
Currently, I am attempting to utilize the Ajax AutoCompleteExtender provided below: <asp:TextBox runat="server" Width="300" ID="tbxItem" CssClass="NormalUpper" /> <asp:AutoCompleteExtender ID="autoCompleteExtenderItemName" runat="server" Mini ...
I have been working on styling a React project where App.js mainly handles routing and navigation to its components: App.js import {useState, useEffect} from 'react'; import Models from './pages/Models'; import Loadingpage from ' ...
Currently, I am developing a Chat app using Flutter and attempting to send notifications to specific devices through Firebase functions. Initially, I retrieve the device token and store it in Firebase. Now, my challenge lies in fetching the token and invok ...
Currently using Primefaces 5.1, and I've encountered a situation where I want to hide a table until after the filter is applied in Javascript. My initial thought was to simply set the css of the table to visibility:hidden;, followed by running the fol ...
Having an issue with passport remember me and express router. When using: router.route("/login).(someController().postlogin) The authentication doesn't work properly as it fails to generate the token. However, when switching to app.post, it wor ...