Animation of a floating string in Three.js

I am seeking a creative way to incorporate an intriguing effect into my project. Specifically, I envision drawing a floating line with dynamic curves and interactive hover effects.

To provide a visual reference, the project timeline featured on the home page of captures a similar essence through its design elements, including the loading bar.

The goal is to establish an array of points for the line's trajectory and allow it to meander unpredictably across the screen.

My initial experimentation involved utilizing Three.js and the CatmullRomCurve3 class to define crucial points along the curve (refer to code snippet below). While setting up six key points proved manageable, there are some vital components that still require fine-tuning:

  • Implementing a random slow-floating animation
  • Incorporating hover interactions
  • Crafting a smooth line-drawing animation

If anyone has insights or suggestions on enhancing my code snippet, your input would be greatly appreciated!

Thank you! :)

const renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xffffff, 0 );

document.body.appendChild( renderer.domElement );

const camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 500 );
camera.position.set( 0, 0, 100 );
camera.lookAt( 0, 0, 0 );

const scene = new THREE.Scene();


const getPosFromPX = (x, y) => {
    const vec = new THREE.Vector3();
    const pos = new THREE.Vector3();
    vec.set(
        ( x / window.innerWidth ) * 2 - 1,
        - ( y / window.innerHeight ) * 2 + 1,
        0.5 );
    vec.unproject( camera );
    vec.sub( camera.position ).normalize();
    const distance = - camera.position.z / vec.z;
    pos.copy( camera.position ).add( vec.multiplyScalar( distance ) );
    return pos
}

const getLine = () => {
  const curve = new THREE.CatmullRomCurve3( [
    getPosFromPX(10, 50),
    getPosFromPX(document.body.clientWidth - 50, 50),
    getPosFromPX(document.body.clientWidth - 10, document.body.clientHeight / 2),
    getPosFromPX(50,document.body.clientHeight / 2),
    getPosFromPX(50,document.body.clientHeight -60),
    getPosFromPX(document.body.clientWidth - 50, document.body.clientHeight - 70)
  ] );

  const points = curve.getPoints( 80 );
  const geometry = new THREE.BufferGeometry().setFromPoints( points );
  const material = new THREE.LineBasicMaterial( { color : "#000000" } );
  return new THREE.Line( geometry, material );
}

scene.add(getLine());

renderer.render( scene, camera );
<!DOCTYPE html>
<html>
  <body>
    <script src="https://threejs.org/build/three.js"></script>
  </body>
</html>

Answer №1

Expanding further on my initial comment...

To create a more visually appealing final result, I have introduced a slight range variation to the mandatory points. Currently, you are passing an array of six points to CatmullRomCurve3. You have the option to pass even more points that are fully random or maintain a similar structure with added ranges to confine the line within specific boundaries.

function rand(min, max) {
  return Math.random() * (max - min) + min;
}

function getLine() {
  const curve = new THREE.CatmullRomCurve3([
    new THREE.Vector3(-37 + rand(-8, 8),  20 + rand(-8, 8), 0),
    new THREE.Vector3( 20 + rand(-8, 8),  20 + rand(-8, 8), 0),
    new THREE.Vector3( 37 + rand(-8, 8),   0 + rand(-8, 8), 0),
    new THREE.Vector3(-20 + rand(-8, 8),   0 + rand(-8, 8), 0),
    new THREE.Vector3(-20 + rand(-8, 8), -16 + rand(-8, 8), 0),
    new THREE.Vector3( 20 + rand(-8, 8), -12 + rand(-8, 8), 0)
  ]);

  const points = curve.getPoints(80);
  const geometry = new THREE.BufferGeometry().setFromPoints(points);
  const material = new THREE.LineBasicMaterial({ color: "#000000" });
  return new THREE.Line(geometry, material);
}

const renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setSize(200, 200);
document.body.appendChild(renderer.domElement);

const camera = new THREE.PerspectiveCamera(45, 1, 1, 500);
camera.position.set(0, 0, 100);
camera.lookAt(0, 0, 0);

const scene = new THREE.Scene();
scene.add(getLine());
renderer.render(scene, camera);
<script src="https://threejs.org/build/three.js"></script>

I've simplified your code for brevity in this example

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The iPhone header position switches when an HTML5 input type number is selected

I am currently working on a project that involves jQuery Mobile and PhoneGap. One issue I am encountering is when using the iPhone version, the header position changes when I click on an input type number. NOTE: When I focus on the input type number in my ...

What are some ways to utilize the pseudo elements ::before and ::after within the Material-UI framework?

Can someone please explain how to use the pseudo-element method in MUI? I couldn't find clear instructions in the documentation, so I decided to post a question here. The docs mention the following about pseudo elements: The box-sizing property is ...

Attach the button to the input tag so that they are always connected

While working on the layout for my webpage, I encountered an issue with an input area and a textarea that I wanted to clone. Everything was functioning correctly, however, I wanted the "+" button to remain attached to the input tag even when the screen siz ...

A guide to correcting alignment issues on a flex box containing both images and text

I am encountering a problem with my flexbox setup. It contains multiple products with images and text, but the issue arises when a product has more than one line of text causing the image to be slightly raised compared to others. Any suggestions on how to ...

PHP script encounters error while trying to modify CSS class

On my sticky login form, I am encountering an issue where the input fields should turn red when submitted with blank information. Interestingly, some fields behave correctly while others exhibit random behavior. The left photo below displays the initial lo ...

Label positioning for checkboxes

Is there a way to display the checkbox label before the actual checkbox without using the "for" attribute in the label tag? I need to maintain the specific combination of the checkbox and label elements and cannot use nested labels or place other HTML elem ...

Retrieve the current value of an item by scrolling through it

I have a functioning sample of a scrollable with item numbers 1 - 24. I am trying to retrieve the value of the current item, but my attempts to use alert have failed. How can this be achieved? Here is my code: UPDATE QUESTION: I managed to obtain the inde ...

Positioning Images in Bootstrap 4

I'm encountering an issue with Bootstrap 4. The left box isn't aligning properly with the right box. This involves both HTML and CSS. How can I go about resolving this issue? <section> <div class="container"> <div class="row"& ...

Guide to aligning a container to the left in Bootstrap 5

I have a grid container in Bootstrap 5 and I'd like to align it to the left on my webpage. <link href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3f5d50504b4c4b4b54e42f56b61a0acf40"&g ...

What could be causing my fixed header to disappear in Safari 5?

I am experiencing a strange issue with my fixed header on Safari 5 for iPad. The header disappears once it scrolls down to a certain point, even though it works fine in IE, Firefox, Chrome, and the latest version of Safari. Has anyone else encountered this ...

How can I leverage the new linewidth feature in Three.js r91 to make lines appear thicker or wider?

As I was working on my project, I encountered a situation where I needed to create wireframe-style lines with transparency inside to give the appearance of outlining shapes in a comic or cartoon style without actually creating solid objects. These outline ...

There is an unnecessary gap between the parent div and the image contained within it

Snippet of HTML code showcased below: <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link href="css/style.css" rel="style ...

Adjustment of Facebook button positioning in floating bar on Firefox

My floating bar currently has 5 social buttons, but I've noticed that the Facebook button is shifting about 20 pixels to the left. Could this be an issue with the CSS elements? After inspecting the elements, I found that when I remove position: absol ...

Experiencing a problem with JQuery Offset when a fixed position is applied to a

My website has a page layout and style similar to the example provided in this JsFiddle. When I use JQuery to click on a button, the content is displayed correctly as shown below: https://i.sstatic.net/V89qa.jpg However, if I scroll down the page first ...

Maintaining Proper Header Dimensions

Having some issues with aligning my fixed widget and floating navigation. The fixed widget is not respecting the height of the floating navigation and is appearing at the top when in its fixed position. I'm currently using "Q2W3 Fixed Widget" for the ...

Tooltips envelope around themselves

Several paragraphs contain tooltips, but some of them break onto a new line instead of staying within the text. <div class="row"> ... </div> Fiddle: https://jsfiddle.net/LhjmLw8k/29/ The issue is that certain words like "Trasimeno" and ...

No shadows are visible when using a collada model on a MeshPhongMaterial surface with a spotlight illuminating the scene

I have been trying to solve this issue for a long time but have been unsuccessful. I am attempting to add shadows to my .dea model using MeshPhongMaterial, but the shadows are not appearing. The camera is in the correct position, the ground is made of Mes ...

Is there a way for me to superimpose text onto an image in this instance?

I am attempting to place a "Text overlay goes here" over the profilepic.jpg image below. I believe there may be an issue with my CSS code. My approach was to create a new div class named overlay and embed that line within the imgcontainer class. Can some ...

AngularJS fetches the 'compiled HTML'

If I have this angularjs DOM structure <div ng-init="isRed = true" ng-class="{'red': isRed == true, 'black': isRed == false}"> ... content </div> How can I obtain the 'compiled' version of this on a cl ...

CSS Animation glitch with images

I am currently facing an issue with a slide that transitions between four pictures. The slide is set at a specific pace, but I am encountering a problem with the transition from the last slide back to the first one. I have attempted various solutions such ...