Place an element in the middle of the svg

I have a D3.js svg element measuring (1000,1000) with a circle positioned randomly, such as (100,200).

My goal is to adjust the svg so that the circle is centered at (500,500). I want to create a function that can do this for any randomly positioned circle.

Can anyone assist me with this task? The svg's upper left point is currently at (0,0). If I use

.attr("transform", "translate(10,10)");
, the upper left point will then be at (10,10). I've also considered using the centroid function, as shown in this example: https://bl.ocks.org/mbostock/2206529

However, I'm unsure if this method only applies to world maps.

var svg = d3.select("body").append("svg:svg") 
    .attr("width", 1000)
    .attr("height", 1000);

function move(){
    svg.transition()
        .duration(750)
        .attr("transform", "translate(0,0)");
}

Answer №1

One approach, as suggested in the comments, might not be the ideal solution for your specific needs, but it is, in my view, the most straightforward and neat: rather than moving the circles individually, consider shifting the entire group that contains them, known as the <g> element.

The equation for translating the group is quite simple:

.attr("transform", "translate(" + (w/2 - pX) + "," + (h/2 - pY) + ")")

Here, w represents the SVG's width, h is the height, pX stands for the circle's x-coordinate, and pY represents the circle's y-coordinate.

A basic demonstration is provided below. I have created 20 circles and, every 2 seconds, I select one circle at a time (in sequence) and center it, highlighting it in red:

var svg = d3.select("svg");
var g = svg.append("g")
var circles = g.selectAll(null)
  .data(d3.range(20).map(function() {
    return {
      x: Math.random() * 500,
      y: Math.random() * 300
    }
  }))
  .enter()
  .append("circle")
  .attr("cx", function(d) {
    return d.x
  })
  .attr("cy", function(d) {
    return d.y
  })
  .attr("r", 10)
  .style("fill", "lime");

var counter = 0;

var timer = d3.interval(function() {
  if (counter === 19) {
    timer.stop()
  }
  var thisCircle = circles.filter(function(d, i) {
    return i === counter;
  });
  var position = thisCircle.datum();
  g.transition()
    .duration(1500)
    .attr("transform", "translate(" + (250 - position.x) + "," + (150 - position.y) + ")");
  thisCircle.style("stroke", "red").style("stroke-width", 4)
    .transition()
    .delay(2000)
    .duration(0)
    .style("stroke", "none")
  counter++;
}, 2000)
svg {
  border: 1px solid gray;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="300"></svg>

EDIT:

To trigger a similar action on click, you can employ the same concept. Below is a demo showcasing this functionality:

var svg = d3.select("svg");
var g = svg.append("g")
var circles = g.selectAll(null)
  .data(d3.range(20).map(function() {
    return {
      x: Math.random() * 500,
      y: Math.random() * 300
    }
  }))
  .enter()
  .append("circle")
  .attr("cx", function(d) {
    return d.x
  })
  .attr("cy", function(d) {
    return d.y
  })
  .attr("r", 10)
  .style("fill", "lime")
  .style("cursor", "pointer");

circles.on("click", function(d) {
  g.transition()
    .duration(1000)
    .attr("transform", "translate(" + (250 - d.x) + "," + (150 - d.y) + ")")
})
svg {
  border: 1px solid gray;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="300"></svg>

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

Increasing the font size on a document

Once again, faced with my own silly problems. This time I stumbled upon the following page: http://jsfiddle.net/g3VBT/ I am trying to style the "enter your U.R.L here" text with the following properties: font-weight: 600; font-size: 1.5em; The issue ...

Creating a box that is connected by lines using JSON data requires several steps. You

I am attempting to dynamically draw a line using the provided JSON data. I have heard that this can be easily achieved with flexbox. Important: I would greatly appreciate a solution involving flexbox This is what I hope to achieve: https://i.stack.imgu ...

Retrieving chosen row data in Angular 6 Material Table

I am attempting to send the value of a selected row from one component to another upon clicking a button. However, in this particular example, I'm unsure where to obtain the selected row values and how to pass them on button click. After that, routing ...

The issue of Jquery .click event handler failing to work for class selector specifically in CHROME

Is there a way to achieve the same opacity effect on click as on mouseover? I've tried various selectors without success. Any help on this issue would be greatly appreciated. Thank you in advance! .container { position: absolute; background:url(&a ...

Retrieving data from an anonymous function in AngularJS and outputting it as JSON or another value

Within the following code, I am utilizing a server method called "getUserNames()" that returns a JSON and then assigning it to the main.teamMembers variable. There is also a viewAll button included in a report that I am constructing, which triggers the met ...

Can the CSS be used to conceal the PNG image while still preserving the drop shadow effect?

I recently applied the "Filter: drop-shadow" effect to my png photo and it worked perfectly. However, I am now interested in hiding the actual png image while retaining the shadow effect. My initial attempt involved adjusting the translate and drop-shadow ...

Gradually conceal the final column of an HTML table with the combination of CSS and JavaScript

My challenge involves modifying a table on Sharepoint with responsive design in mind. The goal is to hide the last visible column in the table based on the screen's width. For instance, if a user creates a 10-column table and the screen size is 1200p ...

Tips for maintaining the height of the outer div consistent with that of the inner div

I am encountering an issue with an inner div that is used for overlay and set to a min-height property. Despite changes in the overlay's height, the height of the outer div remains unaffected. #outer { width: 70px; height: 70px; background-co ...

Changing the order on mobile devices in Bootstrap 4: A quick guide

Currently, I am working on a responsive layout using Bootstrap 4 with two columns. Each column contains a total of 9 divs - four in the first column and five in the second column. My goal is to rearrange the order of the divs within the columns when the vi ...

How to detect a click event in any area of an Angular2

Hey there, I'm new to typescript and angular 2 and I've encountered an error in my code. Can someone lend me a hand in fixing this? import { Component, HostListener } from '@angular/core' export class TooltipComponent { public sh ...

Issue with onDblClick event in Angular5 and PrimeNG's p-listbox

I encountered an issue while using p-listbox's onDblClick event as it does not return the selected list element. Instead, the event object only contains the value of 'this'. {"originalEvent":{"isTrusted":true}} HTML Blockquote <!-- S ...

A database table named after a pair of digits

My database tables are named "30" and "kev." When I query the table named "30," I receive the following error message: Warning: Invalid argument supplied for foreach() in # on line 94 However, when I query the kev table, I do get the desired results. B ...

Using regex for 'OR' conditions in regular expressions

I have been grappling with this issue for quite some time now. Can you offer any helpful hints or suggestions? When it comes to Outlook emails, we often see forwarded emails containing information within the email body like so: From: Jackson, Peter Sent: ...

The interaction between Vue components causing changes in each other's data

Currently, I am working on a project using vue/nuxt. In order to dynamically load data from a JSON file during compilation, I am utilizing nuxt and webpack (Dynamically get image paths in folder with Nuxt). The structure of my JSON file is as follows: { ...

The stylesheet's URL reference to the image is not functioning properly

I'm attempting to showcase images inside a table cell using CSS. Here's what I currently have: HTML: <td class="activity-status status_not_started">Not Started</td> CSS: td.activity-status { font: 0/0 a !important; color: transpar ...

Once the ajax request is finished, load only the <script> tags that have specific ids

I'm currently implementing infinite-scroll to dynamically load more content which includes <script> tags that need to be executed. To achieve this, I have created the following code as an ajax-callback: JS on load ajax callback: function a ...

The state returned by React Redux does not meet the expected results

I recently implemented a like function on the backend using Node and MongoDB. This function successfully returns the post with an updated likes counter, which I tested using Postman. The post object contains properties such as likes, _id, by, createdAt, an ...

Use the colResize function in R Shiny to establish communication and synchronize the column sizes between R and

I'm currently using a plugin called datatables.colResize to allow manual column resizing for DataTables in my R Shiny application. My goal now is to save the column width state once a user adjusts the table size. I want this information to be passed a ...

HTML and CSS link conflict

As a beginner in CSS, I am experimenting with creating a simple website using HTML and CSS. However, I have encountered an issue where the links on the left side of my page are being interfered with by a paragraph in the middle section. This causes some of ...

Switching images using jQuery

Issue I'm feeling overwhelmed by the abundance of JavaScript code hints and finding it difficult to determine where to begin. Any assistance would be greatly appreciated. Essentially, I have a primary full-screen background image set in the CSS on t ...