Creating a visual representation of an image within a Three.js environment using SVGRenderer, or alternatively generating spheres for rendering

I have a <circle> element within an SVG file, where I've used a <radialGradient> to create the appearance of it being a sphere:

<svg version="1.1" id="sphere_svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="640px" height="640px" viewBox="0 0 640 640" enable-background="new 0 0 640 640" xml:space="preserve">
    <defs>
        <radialGradient id="sphere_gradient" cx="292.3262" cy="287.4077" r="249.2454" fx="147.7949" fy="274.5532" gradientTransform="matrix(1.0729 0 0 1.0729 -23.3359 -23.3359)" gradientUnits="userSpaceOnUse">
            <stop id="sphere_gradient_0" offset="0" style="stop-color:#F37D7F"/>
            <stop id="sphere_gradient_1" offset="0.4847" style="stop-color:#ED1F24"/>
            <stop id="sphere_gradient_2" offset="1" style="stop-color:#7E1416"/>
        </radialGradient>
    </defs>
    <circle fill="url(#sphere_gradient)" cx="320" cy="320" r="320"/>
</svg>

The visual representation is showcased here:

JSFiddle Link

To take this concept further into a three.js environment using a WebGLRenderer, I rely on Gabe Lerner's canvg library:

/* The svg asset containing the circle element */
var red_svg_html = new String($('#sphere_asset').html()); 
var red_svg_canvas = document.createElement("canvas");
canvg(red_svg_canvas, red_svg_html);
var red_svg_texture = new THREE.Texture(red_svg_canvas);
var red_particles = new THREE.Geometry();
var red_particle_material = new THREE.PointCloudMaterial({ 
    map: red_svg_texture, 
    transparent: true, 
    size: 0.15, 
    alphaTest: 0.10 
});
var red_particle_count = 25;
for (var p = 0; p < red_particle_count; p++) {
    var pX = 0.9 * (Math.random() - 0.5),
        pY = 0.9 * (Math.random() - 0.5),
        pZ = 0.9 * (Math.random() - 0.5),
        red_particle = new THREE.Vector3(pX, pY, pZ);
    red_particles.vertices.push(red_particle);
}
var red_particle_system = new THREE.PointCloud(red_particles, red_particle_material);
scene.add(red_particle_system);

The transition from WebGLRenderer to SVGRenderer aims to offer users control over orientation for exporting vector images (SVG or PDF) suitable for high-quality publications.

In my attempts utilizing three.js' SVG sandbox example as a foundation, I experimented with multiple methods but faced challenges. Any advice from experienced three.js users would be greatly appreciated.

Initially, I tried rendering PNG images through canvg and integrating them into <image> nodes:

// Code snippet

No results were visible within the viewbox.

Another approach incorporated THREE.Sprite objects along with canvg and THREE.Texture:

// Additional code segment

While there was slight progress, white opaque boxes replaced the spheres in the output.

A third method involved creating nested <svg> elements linked to a referenced <radialGradient>, failing to render any nodes successfully:

// More code examples

Changing the fill attribute provided some insight but fell short compared to desired outcomes.

In conclusion, is there a feasible and efficient way to generate spherical entities or similar rounded particles within space using a SVGRenderer in conjunction with three.js?

Answer №1

Most attributes within SVG typically exist in the null namespace.

red_node.setAttributeNS('http://www.w3.org/2000/svg', 'height', '10');
red_node.setAttributeNS('http://www.w3.org/2000/svg', 'width', '10');

A more accurate representation would be:

red_node.setAttribute('height', '10');
red_node.setAttribute('width', '10');

For what it's worth,

red_node.setAttributeNS('http://www.w3.org/1999/xlink', 'href', red_png_data);

ideally should be written as

red_node.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', red_png_data);

although, your original format will still function in most user agents.

In the last example, the stop elements must belong to the SVG namespace, for instance:

var stop0 = document.createElementNS(null, "stop");

should be

var stop0 = document.createElementNS(xmlns, "stop");

If a gradient lacks stops, it won't be visible until you change the fill to red.

SVG follows a painter's model where objects are drawn based on their order in the file. To overlay something on top of another object, it needs to be placed later in the file.

Answer №2

To solve the issue you are experiencing with rendering Particles in your SVGRenerer.js file, follow these steps:

function renderParticle( v1, element, material, scene ) {


        _svgNode = getCircleNode( _circleCount++ );
        _svgNode.setAttribute( 'cx', v1.x );
        _svgNode.setAttribute( 'cy', v1.y );
        _svgNode.setAttribute( 'r', element.scale.x * _svgWidthHalf );

        if ( material instanceof THREE.ParticleCircleMaterial ) {

            if ( _enableLighting ) {

                _color.r = _ambientLight.r + _directionalLights.r + _pointLights.r;
                _color.g = _ambientLight.g + _directionalLights.g + _pointLights.g;
                _color.b = _ambientLight.b + _directionalLights.b + _pointLights.b;

                _color.r = material.color.r * _color.r;
                _color.g = material.color.g * _color.g;
                _color.b = material.color.b * _color.b;

                _color.updateStyleString();

            } else {

                _color = material.color;

            }

            _svgNode.setAttribute( 'style', 'fill: ' + _color.__styleString );

        }

        _svg.appendChild( _svgNode );


    }

Answer №3

When attempting to manipulate SVG elements, one approach is to implement the Snap.svg library. By extracting the svg element(s) from canvg and organizing it into a snap structure (resembling a paper for snap), you can utilize the paper.toString() method to generate the code for the SVG File.

var paper = Snap("#... ");        // Incorporating the canvg svg element into Snap structure 
console.log( paper.toString());   // Retrieve the SVG code

An alternative option is to employ fabric.js to convert canvas to SVG:

var svg = canvas.toSVG();

Another possibility is to utilize the canvas2svg library.

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

sending a parameter in the reverse url using JavaScript

coding in javascript let address = '{% url candidate_resume "cnd_id" %}'; address = address.replace("cnd_id",id); document.getElementById('cell2').innerHTML= '<a href="' + address + '"> View Resume < ...

In Javascript, when trying to call Firebase database child(), it may sometimes result in the return value being "

Here is the current setup: Firebase Database: setores: { -KkBgUmX6BEeVyrudlfK: { id: '-KkBgUmX6BEeVyrudlfK', nome: 'test' } -KkDYxfwka8YM6uFOWpH: { id: '-KkDYxfwka8YM6uFOWpH', nome ...

Configuring Angular routes based on service method invocation

I have my routes configured in @NgModule. I also have a service that determines which parts of the application to display based on specific conditions. I need to call this service and adjust the routes according to its output. Issue: The route configurati ...

The model is only loaded when I access the developer toolbar

Recently, I encountered an issue while working with a three.js mesh. Upon opening the webpage in Chrome or Firefox (I haven't tested it on IE), everything seemed fine but the canvas displaying the mesh did not appear. It was only after activating the ...

How can I create a jumping animation effect for my <li> element in JQuery?

I have a horizontal navigation bar with a "JOIN" option. My goal is to make the #jump item continuously jump up and down after the page has finished loading. Currently, I have this code which only triggers the jump effect once when hovering over the eleme ...

Attempting to condense an array of objects into a consolidated and combined array of objects

My array of objects is structured like this: dataArray = [ {Revenue: 5, Date: "2018-06-05T00:00:00", DateString: "6/5/2018"}, {Revenue: 10, Date: "2018-06-05T00:00:00", DateString: "6/5/2018"}, {Revenue: 5, Date: "2018-06-05T00:00:00", DateSt ...

What is the best way to personalize the collector for each individual?

Currently, I have a bot that is capable of collecting messages and replying if it detects a specific word. However, I am facing an issue where the bot keeps creating new collectors every time someone types the word tekong. As a result, the bot ends up resp ...

How can you quickly track the AJAX requests being sent?

Is there a tool, preferably a Firefox extension, that can show me all AJAX subrequests? I want to be able to see the URL being requested and any GET or POST variables that are sent with it whenever an XMLHTTPRequest() is made. I haven't found anythin ...

The total of a collection of values stored within a property nested within the main object

{ 'Amelia L. Jones': [ // o { author: 'Amelia L. Jones', likes: 7 }, { author: 'Amelia L. Jones', likes: 3 } ], 'Raymond T. Hayes': [ { author: 'Raymond T. Hayes', likes: 9 }, ...

Determine the number of centimeters on the page as you scroll with jQuery

While searching for plugins that count up and down, I came across many. However, I am looking for something more unique: Imagine having an HTML page that is 70,000cm high. Now picture a counter in one corner that displays the height you are currently at a ...

Erase the dynamically loaded page using ajax and conceal the div

Currently, I am utilizing the .on() method with jQuery to display a specific div, and also using .load() to fetch a particular div from a web page hosted on my server. My query is how can I close this div when clicking outside of it, along with removing i ...

"An error message stating 'Express: The body is not defined when

I'm encountering an issue while trying to extract data from a post request using express. Despite creating the request in Postman, the req.body appears empty (console.log displays 'req {}'). I have attempted various solutions and consulted s ...

Is it possible to swap out one div for another div from an external HTML page?

How can I replace a div with the id 'mainbox' in my 'index.html' page with another div found in the 'list-div.html' page? <body> <div id="divet"> Sempre caro mi fu quest'ermo colle, e questa si ...

Event delay with JavaScript and jQuery

In my WordPress (WooCommerce) website, I am working on creating a quantity field... It is functioning properly; however, I want to trigger an event when the + or - buttons next to Quantity are pressed in order to "Update cart". This is what I have tried: ...

Generating a JSON file by combining data from two separate lists in order to render a visually appealing stacked bar chart

Combining two lists to create a JSON for generating a stacked bar chart using JavaScript list1 = ['2019-03-05', '2019-02-20', '2019-02-20', '2019-02-19', '2019-02-18', '2019-02-16', '2019-02 ...

Is there a way to match the color of a fixed element with the background elements' color?

In my current website setup, I have multiple full-width content containers stacked on the Y-axis. Every other container is blue and red alternatively. I am looking to incorporate an SVG image or a button fixed in the top-left corner that moves with the use ...

Introduction to React with Typescript: Greeting the World

I am attempting to create a Hello World React application with Typescript. Below is the code I have written. Method 1 works without any issues, but method 2 throws an error. Method 1 - TypeScriptComponent.tsx import React from 'react' import Re ...

Issues with APIs surfaced following the transition from DataGridPro to DataGridPremium

In my current project, we initially implemented the MUI X DataGrid but later switched to DataGridPro due to business requirements. Recently, we upgraded our plan from Pro to Premium which has caused some unexpected issues in our existing code. I am using " ...

JS code is not executing

I am experiencing some issues with my code and I can't seem to figure out why it's not working as intended. Basically, all I'm trying to do is change the height attribute value from '1000' to '2'. Here's the snippet ...

Replace text using Selenium in Python

Currently, I am attempting to update specific text within a string on the Wagtail backend using Selenium and Python. Here is my approach: Locate the element that contains the desired text using contains(text() Identify and replace the target string (such ...