Adding intricate SVG components onto a chosen group

My current project involves creating an interactive schema that includes complex SVG elements, such as groups containing multiple sub-objects like rect, path, and text.

I am wondering if there is a way to store the description of these elements in a variable and then directly use it with .append() function?

Here is an example of one object:

<g id="Titre_x5F_A11">
    <g>
        <g id="Cadre_3_">
            <rect x="13.2" y="636" class="st14" width="157.5" height="26.8"/>
            <rect x="12.3" y="636" class="st15" width="13.7" height="26.8"/>
        </g>
        <g id="IN_3_">
            <rect x="142.6" y="654.5" class="st16" width="10" height="5.7"/>
            <text transform="matrix(0.9497 0 0 1 145.6079 658.4658)" class="st17 st4 st18">IN</text>
        </g>
        <g id="OUT_3_">
            <rect x="155.9" y="654.5" class="st19" width="10" height="5.7"/>
            <text transform="matrix(0.9497 0 0 1 156.8984 658.4434)" class="st17 st4 st18">OUT</text>
        </g>
        <rect x="28.2" y="637.7" class="st20" width="111.1" height="7.4"/>
        <text id="TitreAction_18_" transform="matrix(0.9497 0 0 1 28.1768 643.1006)" class="st4 st21">A11 - xxxxxe</text>
        <rect x="28.2" y="646.7" class="st20" width="106.5" height="14.8"/>
        <text id="DescrAction_3_" transform="matrix(0.9497 0 0 1 28.1768 650.082)" class="st22 st4 st18">To be completed</text>
        <g id="IconePeople_3_">
            <circle class="st23" cx="155" cy="644.8" r="6.5"/>
            <path class="st24" d="M153.4,644.1c0.9,0.9,2.3,0.9,3.1,0c0.9-0.9,0.9-2.4,0-3.4c-0.9-0.9-2.3-0.9-3.1,0l0,0
                C152.5,641.6,152.5,643.1,153.4,644.1z M151.2,649c1.1,0,6.6,0,7.7,0c1.1,0,0.5-1.1,0.5-1.1s-2.2-2.7-4.4-2.7
                s-4.4,2.7-4.4,2.7l0,0C150.6,648,150.1,649,151.2,649z"/>
        </g>
    </g>
</g>

and my main objective is:

var complexObject = ... description of complexObject            

var circles = svgContainer.selectAll("complexObject")
    .data(data)
    .enter()
    .append("complexObject");

Answer №1

selection.append function allows you to customize the creation of nodes using a specified argument. You can use an object definition as a template to generate nodes as needed.

For instance, imagine defining a complex object like this:

<script type='text/template' id='Titre_x5F_A11'>
<g>
  <circle class="st23" cx="20" cy="20" r="10"/>  
  <circle class="st19" cx="50" cy="20" r="10"/>  
  <circle class="st21" cx="70" cy="20" r="10"/>  
</g>
</script>

This could be loaded from an external file using a template engine like Handlebars.

Then, you can define your enter sequence as shown below:

// HTML template to use
var tpl = d3.select('#Titre_x5F_A11').html();

// selection
svgContainer.selectAll(".complexObject")
.data(data)
.enter()
.append(function() {
    //create a node
    var g = document.createElementNS("http://www.w3.org/2000/svg", "g");

    // fill with the HTML
    g.innerHTML = tpl;

    //set a class for identification
    g.setAttribute('classname', 'complexObject');

    return g;
})

// adjust positions
.attr('transform', function(d, i) {
    return "translate(0, " + (i * 40) + ")";
});

Check out the demo with embedded SVG code provided above.

Alternatively, you can load an external SVG file and clone it as demonstrated in the following example.

View the Observable version here.

Answer №2

After coming across this helpful question on Stack Overflow about bringing a circle to the front with D3, I decided to create my own function for adding functionality to D3.

Here is the function I created to generate a circle:

d3.selection.prototype.appendCircle = function(data, x,y,r,fill) {
  return this
  .data(data)
  .enter()
  .append('circle')
  .attr('cx', x)
  .attr('cy', y)
  .attr('r', r)
  .style('fill', fill);
  }

This function allows customization of attributes such as data, x, y, radius, and fill color.

To use the function, follow these steps:

var svg = d3.select('body').append('svg');

var circles = svg.selectAll('circle')
.appendCircle([1],100,100,15,'red')  

By following these steps, you can easily create your desired shape using D3. The possibilities are endless in terms of complexity.

Feel free to check out the fiddle where I experimented with this function: https://jsfiddle.net/thatoneguy/4x3rrd27/1/

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

Upon clicking the link, the JavaScript functionality failed to activate

When I click on a link and try to add a class, it's not working. I want to create a "modal" div. Here is the PHP/HTML code: <?php if(isset($_GET['ido'])) { ?> <div id="modal" class="modal" style="background: blue; width: 1 ...

The element type provided is not valid: it should be a string for built-in components or a class/function for composite components. However, an object was received instead. - React Native

After conducting extensive research, I have been unable to find a solution as to why this issue persists. Can anyone shed some light on what the error might be referring to? Error: Element type is invalid: expected a string (for built-in components) or a c ...

A Guide to Triggering a Method Upon Component Change in Angular

When working with Angular, Components have an ngOnInit() method. I am looking for the opposite of this method. Is there a method that gets called when the component is closed? Is there a way to detect in the TypeScript file if the component is being clo ...

Encountering an issue while attempting to generate a dialog popup with jQuery

As a beginner in jQuery, I am attempting to implement a popup dialog box for users in case of an error. However, I'm encountering issues with the following jQuery code: <script type="text/javascript"> $(document).ready(function() { var $dia ...

Using PHP to enhance a select statement to return data when paired with JavaScript

How can I post JavaScript with PHP to enable select statement return? I have a script that is currently functioning as follows: $.post('2.php', { id: 12345 }, function(data) { // Increment vote count, etc }); This is the content of my 2.ph ...

Verifying if form submission was done through AJAX using PHP

Hey there, I need some help with checking whether or not this ajax method has been submitted. I want to display the result based on a certain condition. Below is the code for the Ajax POST request: $.ajax({ url: "addorderInfo.php", // This ...

Angular JS function is returning before the completion of the http.get request

I'm encountering an issue where this block of code is returning before it has received all the necessary information. Here's my current implementation: function (){ .... var promise = $http.get(...) promise.then (...){ //get info nee ...

Tips for adjusting the margin of a print document in a printTask?

Is there a way to achieve a borderless print? Currently, my printed output has a border around it. I would like the image to start at the top left corner without any borders. I attempted to set a negative margin to the print-style box, but it resulted in ...

having trouble retrieving information from the input field

I'm having trouble retrieving the user's input from the input field, can someone assist me with this issue? I can't seem to identify what the problem is here. var ftemp = document.getElementById("Farenheit").value; <td> <i ...

Problem with UV mapping when adjusting texture size

I am currently working on an application to modify minecraft models. To display the drawn texture mapped on the 3D player model, I am using ThreeJS. However, I'm facing a challenge related to changing the texture size. Initially, the texture is mappe ...

analyzing properties through unit testing

Currently in the process of writing unit tests for computed properties. I have a file called fileOne.ts : export const fileOne = () => { const fx1 = computed ( () => { ... } ); const fx2 = computed ( () => { ... } ); const fx3 = comp ...

Divide the information in the table across several pages for easier printing

I have encountered an architectural challenge with my server-side React app. The app renders charts and tables with page breaks in between to allow a puppeteer instance to print the report for users in another application. The issue I'm facing is mak ...

Displaying JSON data from the API on a webpage within a NodeJS weather application

Currently, I am in the process of developing a weather application using NodeJS. I have successfully retrieved JSON formatted data from the weather site's API. Nonetheless, I am perplexed about how to transmit this data to the application. Below is a ...

Tips for effectively reusing the modal component in Vue.js without encountering re-render issues

I'm encountering an issue where the same component content is being rendered despite having different components (Rendering problem). I have a reusable modal component called modal.vue, so every time I create a new component, I call the modal compone ...

Exploring deep nested writes within Prisma

Describing my database schema: model User { id Int @default(autoincrement()) @id createdAt DateTime @default(now()) email String @unique role String @default("user") sessions Sessio ...

What is the best way to ensure an AJAX get-request waits for the page to finish rendering before providing a response?

I've been working on a Greasemonkey Script for a specific section of this website (Site1). Site1 offers various deals and discounts, and my script is designed to perform the following task: When a user visits an offer on Site1, the script checks with ...

Issue with react-native-svg ForeignObject missing in project (React Native with Expo using TypeScript)

I am working on a React Native project in Expo and have incorporated the expo TypeScript configuration. Using "expo install," I added react-native-svg version 9.13.3 to my project. However, every time I attempt to render the SVG using react-native-svg, I ...

ordering the date and time in a reverse sequence using javascript

I am working with dynamically generated date and time data and I am looking to sort them in descending order using JavaScript. Here is an example of the data format I am dealing with: var array= ["25-Jul-2017 12:46:39 pm","25-Jul-2017 12:52:23 pm","25-Ju ...

Vue feature allows users to save favorite films

Welcome to my homepage where I showcase 3 movies taken from the store, each with an "add to fav" button. My goal is to have the selected movie appear on the favorites page when clicked. As a newcomer to Vue, any code or documentation suggestions would be h ...

Chosen selection is yielding tag instead of text value

Having an issue with my bootstrap select element <select id="createAxiomSelect" class="form-select"> <option selected vale="true">True</option> <option value="false">False</ ...