Creating a three.js visualization of a cheerful X-Y coordinate graph

I am looking to generate a positive X-Y plane in mesh format using three.js. Additionally, I would like the ability to click on any intersection point and retrieve the coordinate values, resembling a graph paper layout.

Design.prototype.mouseUp = function (event) {

    var material = new THREE.LineDashedMaterial({
        color:0xffeedd  , dashSize:2 , gapSize:2
    });
    this.container.offsetHeight = 30 , this.container.offsetWidth = 70;
    var a = 0;
    for(var i = 0; i <= this.container.offsetWidth ; i++) {
        var geometry = new THREE.Geometry();
        geometry.vertices.push( new THREE.Vector3( -90 + a,-50, 0 ) );
        geometry.vertices.push( new THREE.Vector3( -90 + a, 50, 0 ) );

        var line = new THREE.Line( geometry, material );
        this.scene.add( line);
        a = a + 1;
    }

    var b = 0;
    for(var j = 0; j <= this.container.offsetHeight; j++) {
        var geometry1 = new THREE.Geometry();
        geometry1.vertices.push( new THREE.Vector3( -90,-50 +b , 0 ) );
        geometry1.vertices.push( new THREE.Vector3(  90,-50 +b , 0 ) );

        var line1 = new THREE.Line( geometry1, material );
        this.scene.add( line1);
        b = b + 1;
    }

};

Design.prototype.onDocumentMouseMove = function( event ) {

    mouseX = event.clientX - (this.container.offsetWidth * 0.5);
    mouseY = event.clientY - (this.container.offsetHeight-window.innerHeight * 0.875);

};

Design.prototype.onDocumentMouseDown = function(event) {

    event.preventDefault();
    alert("X: " + mouseX + " Y: " + mouseY);
    var projector = new THREE.Projector();
    var vector = new THREE.Vector3( ( mouseX / this.container.offsetWidth )*(2-1), - ( mouseY / this.container.offsetHeight )*(2+1), 0.5 );
    projector.unprojectVector( vector, camera );

    var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
    var intersects = raycaster.intersectObjects( objects );

    if ( intersects.length > 0 ){

        var sphere = new THREE.Mesh(new THREE.SphereGeometry(size / 4), new THREE.MeshLambertMaterial(intensity));
        sphere.position = intersects[ 0 ].point;
        scene.add(sphere);
    }
};

//three.js code

window.vv = {};
window.vv.messages = {

NO_CONTAINER: "No Container provided."
};
function DesignSpace() {

    this.activeDesign = 0;
this.designes = [];
}

DesignSpace.prototype.getDesignByIndex = function(index) {

    var returnValue = null;
if (index < this.designes.length) {
    returnValue = this.designes[index];
}
return returnValue;
};

DesignSpace.prototype.setActiveDesign = function(index) {

this.activeDesign = index;
};

DesignSpace.prototype.addDesign = function(container) {

var design = new Design(container);
this.designes.push(design);
return design;
};

DesignSpace.prototype.run = function() {

var design = window.vv.designSpace.getDesignByIndex(window.vv.designSpace.activeDesign);
design.getRenderer().render(design.getScene(), design.getCamera());
window.requestAnimationFrame(window.vv.designSpace.run);
};

function Design(container) {

this.renderer = null,
this.scene = null,
this.camera = null,
this.cube = null,
this.animating = null,
this.light = [];
this.grid = null;
this.container = container;
}

Design.prototype.setUp = function() {

if (!this.container) {
    console.log(window.vv.NO_CONTAINER);
    return null;
}
this.container = document.getElementById(this.container);
this.renderer = new THREE.WebGLRenderer({antialias: true});
this.renderer.setSize(this.container.offsetHeight, this.container.offsetHeight);
this.container.appendChild(this.renderer.domElement);


this.scene = new THREE.Scene();

this.camera = new THREE.PerspectiveCamera(90, this.container.offsetWidth / this.container.offsetHeight, 1, 4000);
this.camera.position.set(0, 0, 3);

if (this.light && !this.light.length) {

    this.light.push(new Light({intensity: 1.0, x: 0, y: 1, z:1}));
}
for (var i in this.light) {

    this.scene.add(this.light[i].getLight());
}

this.addMouseHandler();

};
Design.prototype.addMouseHandler = function (event) {

this.renderer.domElement.addEventListener('mouseup', $.proxy(this.mouseUp, this), false);
this.renderer.domElement.addEventListener('mousemove', $.proxy(this.onDocumentMouseMove, this), false);
this.renderer.domElement.addEventListener('mousedown', $.proxy(this.onDocumentMouseDown, this), false);

};

Answer №1

I had difficulty following your code, so I developed something similar to convey the idea. Although it's not finished and requires further work.

<!DOCTYPE html>
<html>
<head>
    <title>Sample X-Y Coordinate Example with Shader</title>
    <style>canvas { width: 100%; height: 100% ;}</style>
    <style>
        body {
            margin: 0px;
            overflow: hidden;
        }
    </style>
</head>
<body>      
<script src="https://rawgithub.com/mrdoob/three.js/master/build/three.min.js"></script>

<script id="vs" type="x-shader/x-vertex">       
    void main()
    {
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
    }           
</script>

<script id="fs" type="x-shader/x-fragment">

    uniform vec2 resolution;
    #define SCALES 5.0
    #define X_AXIS -5.0
    #define Y_AXIS -5.0
    #define AXIS_THICKNESS 0.08
    #define ORIGIN_INTENSITY 0.40

    void main()
    {
        vec2 point = -1.0 + 2.0 * ( gl_FragCoord.xy/resolution.xy );
        float aspect_ratio = resolution.x/resolution.y;
        float r = length (point);
        vec3 background = (1.0 - 0.15*r) * vec3(0.7-0.07*(point.y+1.0), 0.8, 1.0);
        vec3 col = vec3(1.0);

        point *= SCALES;
        float f = 1.0 - min (
            min( abs( aspect_ratio*point.x - ceil(aspect_ratio*point.x) ), abs( aspect_ratio*point.x - floor(aspect_ratio*point.x) ) ),
            min( abs( point.y - ceil(point.y) ), abs( point.y - floor(point.y) ) ) );
        col *= (1.0 - pow(f, 40.0));

        col = (abs(aspect_ratio*point.x - aspect_ratio*X_AXIS)<AXIS_THICKNESS || abs(point.y - Y_AXIS)<AXIS_THICKNESS) ? vec3(0.0) : col;
        col = (length (vec2(aspect_ratio*point.x, point.y) - vec2(aspect_ratio*X_AXIS, Y_AXIS)) < ORIGIN_INTENSITY )  ? vec3(0.0) : col;

        gl_FragColor = vec4( col*background , 1.0);
    }

</script>

<script type="text/javascript">

    var scene = new THREE.Scene();
    var camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 1000 );
    var renderer = new THREE.WebGLRenderer({ antialias: true});

    window.addEventListener( 'mousedown', onMousePress, false );

    // Assignments start here
    // More information can be found at https://github.com/mrdoob/three.js/wiki/Uniforms-types
    var uniforms = {
        resolution: {
            type: "v2",
            value: new THREE.Vector2( window.innerWidth, window.innerHeight )
        }
    }; 
    var myMaterial = new THREE.ShaderMaterial({
        uniforms: uniforms,
        vertexShader: document.getElementById( 'vs' ).textContent,
        fragmentShader: document.getElementById( 'fs' ).textContent
    });

    camera.position.z = 0.40;
    var itemGeometry = new THREE.PlaneGeometry( window.innerWidth / (window.innerWidth+window.innerHeight), window.innerHeight / (window.innerWidth+window.innerHeight), 0);
    var itemCube = new THREE.Mesh( itemGeometry, myMaterial );
    scene.add( itemCube );

    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );


    function onWindowResize() {

        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();

        renderer.setSize( window.innerWidth, window.innerHeight );
        uniforms.resolution.value = new THREE.Vector2( window.innerWidth, window.innerHeight );

    }

    function onMousePress(e){
        var scale = 10;
        var aspect = window.innerWidth / window.innerHeight;
        alert(scale*aspect* (e.clientX / window.innerWidth));
        alert(scale* ((window.innerHeight - e.clientY)/ window.innerHeight));
    }

    function render() {

        requestAnimationFrame(render);       
        renderer.render(scene, camera);

    }
    render();
</script>
</body>
</html>

I've created a plane mesh using plane geometry and a custom shader for drawing graph paper-like patterns on the plane in the fragment shader. Feel free to experiment with different parameters to see their impact. Check out the onWindowResize() function in the JavaScript code, where I handle window size changes for the camera, renderer, and update the fragment shader parameter. In onMousePress(e), I gather user input data and calculate coordinates accordingly.
Please note that the code is a work-in-progress but serves to illustrate the concept.

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

Encountering JSON parsing errors while using fetch() POST requests in Express

Currently, I am experimenting with HTTP requests and my main focus is on sending a POST request. The data for this request is coming from an input field and I am using fetch() to send it to a URL on my local host which is set up with express. My goal is to ...

Creating an object positioned to the right side of a div (div:right) is a matter of using CSS positioning properties

While we are familiar with pseudo-classes like :before and :after, have you ever wondered why there is no nav ul li a:left or :right? Do you think it's achievable? I'm open to using HTML5, CSS3, and JavaScript to make it happen. ...

The Jquery Object #<Object> does not have the 'getElement' method available

I've been attempting to set up this table, following the instructions here: Despite verifying that my browser is correctly pulling the CSS and .js files, I keep encountering an error related to my sortabletable.js file. (screenshot of the error) htt ...

Is it possible to apply styles to javascript elements without relying on img class? Additionally, how can I incorporate an onclick button while maintaining a fully functional navigation bar?

My current project involves creating an interactive collage where users can click around and have pictures pop up at the clicked location. The functionality works as intended, but now I'm facing issues with the navigation bar not being clickable. Addi ...

The perplexing results received when using the npm outdated command

Could someone provide an explanation for the meaning behind this output? $ npm --version 3.10.8 $ npm -g outdated npm Package Current Wanted Latest Location npm 3.10.8 4.0.2 3.10.9 As stated in the documentation, the "Wanted" column should d ...

Switching from a right arrow to a down arrow using jQuery for a collapsible accordion feature

I have developed a unique type of toggle feature similar to an accordion design. When I click on the right-arrow next to an item, such as Area A, it expands to reveal the list of items within Area A. The arrow also changes orientation to point downwards (L ...

Getting the entire data block in ReactJS: A step-by-step guide

I have encountered an issue with a component I created that only displays the value of block[0], rather than showing the entire block value. For instance, if I input: HI Stackoverflow It only shows "HI" and not the complete content of the field. Is th ...

A guide to effectively displaying JavaScript variables within a jQuery function

Initially, I believed this was a problem specific to WordPress, but after spending hours attempting to resolve it, I suspect that it may actually be a broader JavaScript issue. I've been grappling with this challenge for a few hours now and I'm ...

Combining AngularJS with Servlets: A Seamless Integration

I am attempting to retrieve a JSON object from a servlet by calling a function through a link in my HTML code. Below is the HTML link that calls the fTest function: <td><a href="" ng-controller="minaplantaCtrl" ng-click="fTest(x.id_camion_descar ...

What is causing the malfunction with this JQuery/AJAX request?

Currently in the process of setting up an autocomplete feature. Following the guidance from php academy at the moment. My goal is to display "suggestions go here" below the input field whenever something is typed in. I have two files for this task: home.ph ...

Animate the jQuery display property to show a table without changing any specified spatial dimensions

When utilizing jQuery's $.animate() on an element styled with display:table, any spatial dimensions that are not explicitly specified to change will animate. Check out the fiddle here In the scenario presented, the width is defined for animation, bu ...

Deploying a node application and a Java JAR to Heroku

Currently in the process of developing a node.js app, with plans to host it on Heroku. The only complication is that the app depends on a jar file that needs to be executed. Can Heroku support running Java for this purpose? ...

Is concealing content using Javascript or jQuery worth exploring?

While I have been hiding content using display:none; in css, there are concerns that Google may not like this approach. However, due to the needs of jQuery animations, it has been necessary for me. Recently, I have come across a new method for hiding conte ...

Toggle visibility between 2 distinct Angular components

In my application, I have a Parent component that contains two different child components: inquiryForm and inquiryResponse. In certain situations, I need to toggle the visibility of these components based on specific conditions: If a user clicks the subm ...

Ways to eliminate unnecessary re-rendering of components that remain unchanged?

I am struggling with a component that contains various other components, such as text fields. Whenever an input is made in the text field, all the components are re-rendered. My goal is to prevent this re-rendering and only update the component that has a ...

Testing a custom Angular directive that encapsulates the functionality of SlickGrid

Currently, I am working on testing an angular directive that acts as a wrapper for slickgrid. 'use strict'; describe('Unit: Grid Directive', function() { var $scope; var element; beforeEach(module('grid')); beforeEac ...

What is the method for transforming latitude and longitude coordinates into a physical address for a website?

I'm working with an API that provides latitude and longitude coordinates, and I need to retrieve the address information (city, area, etc.) based on these values. For example, there is a website like where if we enter the IP address of a location, i ...

What is the best method for integrating opensea-js using a script tag in a vanilla HTML/JS environment?

Is there a way to incorporate opensea-js into an html/js project that does not rely on node.js? The source code for opensea-js is only available on github and npm at https://github.com/ProjectOpenSea/opensea-js I came across this link: However, when I tr ...

A guide on incorporating a method using ES6 Rest into a JavaScript object

My goal is to enhance my Person constructor by adding a method that allows users to add friends. I wanted to utilize the "rest" feature of ES6 to pass a variable number of friends, but I seem to be stuck. My initial attempt resulted in an error ("Uncaught ...

Exploring the functionalities of Stripe's latest Search API integrated with metadata features

I'm currently working on a project to showcase products stored in the Stripe Database. I attempted to implement this using if statements, filters, and the new Search API of Stripe, but unfortunately, my attempts were unsuccessful. Any ideas on what el ...