The function of d3.behavior.zoom() unexpectedly shifts the graph to the corner rather than the center

I am looking to implement mousewheel zoom functionality for my sunburst visualization:
I have made changes to the following code snippet:

var zoom = d3.behavior.zoom()
    .scaleExtent([1, 10])
    .on("zoom", zoomed);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .attr("transform", "translate(" + width/2 + "," + height * .52 + ")")
    .call(zoom);

function zoomed() {
  svg.attr('transform', 'translate(' + d3.event.transform.x + ',' + d3.event.transform.y + ') scale(' + d3.event.scale + ')');
}

Initially, everything appears fine on page load. However, when using the mousewheel to scroll, the sunburst ends up in the upper left corner:
https://i.sstatic.net/6B6xG.jpg

To address this issue, I modified the code as follows:

function zoomed() {
  svg.attr("transform", "translate(" + width/2 + "," + height * .52 + ")scale(" + d3.event.scale + ")");
}

The sunburst now remains centered, but unfortunately does not zoom to the cursor position and restricts further zoom out capability.
Any pointers on how I can achieve zooming to the cursor position (as shown in the original code) without the sunburst disappearing into the upper left corner?

To view the complete code, please refer to this JSFiddle link. While it may not work here, running it locally should demonstrate the desired behavior.

Answer №1

d3.event.translate retrieves an array of values. To incorporate width/2 and height/2, they need to be added separately:

function zoomed() {
    svg.attr('transform', 'translate(' + (d3.event.translate[0] + width / 2) +
        ',' + (d3.event.translate[1] + height / 2) + ') scale(' + d3.event.scale + ')');
}

If you prefer using your original zoomed function...

function zoomed() {
    svg.attr("transform", "translate(" + d3.event.translate +
        ")scale(" + d3.event.scale + ")");
}

...you can simply rename the svg selection to another name for the group:

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

var foo = svg.append("g")
    .attr("transform", "translate(" + width / 2 + "," + height * .52 + ")")
    .call(zoom);

Answer №2

When implementing the Zoomed function, I initially used the standard d3.event.translate and d3.event.scale like this:

function zoomed() {
svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")");
}

Everything seemed to be working fine until I encountered an issue where the entire sunburst diagram would suddenly jump to the top left corner when I first attempted to scroll. Although it would return to its proper position after dragging it back to the center, this initial glitch was quite frustrating.

After struggling with this problem for several hours, I eventually found a solution by modifying the viewBox attribute on the svg element:

.attr({viewBox: "" + (-width / 2) + " " + (-height / 2) + " " + width + " " + height})

This resolution was inspired by an example I came across: Basic Sunburst

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

How to safely add multiple objects to an array in TypeScript & React without replacing existing objects - Creating a Favorites list

I'm in the final stages of developing a weather application using TypeScipt and React. The last feature I need to implement is the ability for users to add queried locations to a favorites list, accessed through the "favorites" page. By clicking on a ...

Exploring the process of connecting right and left nodes using Cypher and Neo4j

Utilizing a Neo4J graph database for my project has presented me with a challenge that I hope to explain to you. I aim to identify the longest path, limited to 8 nodes, on both the left and right side of each result. However, determining the last node at ...

Code error: JSON unexpected token "&" encountered

When utilizing the $http.get() method for a GET request, the response is in JSON format, but some characters are HTML encoded. For example, the double quote " is encoded as ". { "description":"invalid", ...

How to address hover problems in D3.js when dealing with Path elements and updating tooltip information after brushing the focus

Seeking assistance with a Multi Series, Focus + Context D3 chart and hoping to address my main queries all at once. The questions that need resolving are: How can I prevent the tooltips I've generated from being affected by the hair-line (which t ...

Make sure to save your data prior to using req.session.destroy() in Express

Before destroying the session in the logout route, I need to save the session value "image location" into the database. Here is the solution I have implemented: app.get('/logout',function(req,res){ Person.update({ username: req.session.use ...

Using regex in Javascript to find and match an ID within a string

JavaScript: var data='<div id="hai">this is div</div>'; I am looking to retrieve only the ID "hai" using a regular expression in JavaScript. The expected output should be, var id = regularexpression(data); The variable id should n ...

What is the proper method for setting up handlers in functional React components?

My knowledge of JavaScript tells me that there are three different ways to define functions. Let's take a look at them: 1. Declaration function handleEvent(e) {} 2. Assignment var handleEvent = function(e) {} 3. Arrow var handleEvent = (e) => ...

Using JQuery to send a POST request to a NODEJS server running on Express

UPDATE: Link to project on Github: https://github.com/jackphumphrey/medisearch Being new to NODEjs, I apologize in advance if this question seems trivial I am trying to issue a POST request using JQuery ($.post) from: /public/javascripts/user.js The use ...

Is my rtk slice's initial state not being saved correctly in the store?

Currently diving into the world of RTK with typescript. I have created 2 slices - one using RTK query to fetch data (called apiSlice.ts) and another utilizing createSlice for handling synchronous state changes in my todo app (named snackbarSlice.ts). The ...

JavaScript scroll event not firing

I have searched multiple questions on SO to avoid duplication, but none of the solutions worked for me. My goal is to toggle the visibility of a button based on scroll position. I tried creating a scroll event listener to trigger a function that checks th ...

Changing a global variable via an AJAX call

I seem to be facing a common issue that many others have encountered. Despite my understanding that global variables can be modified inside functions in Javascript, I am struggling with this concept in practice. var lastMessage = 0; function loadChat() { ...

What is the best way to retrieve the current quality label from JWPlayer using JavaScript?

My goal is to retrieve the Current Quality Label from JWPlayer 7 using JS, but instead of getting the defined labels like 360p, 480p, 720p, I'm only receiving numbers such as 1, 2, 3... This is what I've tried: playerInstance.getCurrentQuality( ...

React components can be used to dynamically render and display an array of objects through methods like reduce and

Here's the scenario at hand: (https://codesandbox.io/s/8p21n6p09l) I have an array of objects (referred to as modules) structured like this: const modules = [ { thematicArea: "Topic 1", id: 1, name: "Building assertive attitude", d ...

Updating the state of a React component through a button click using React-JS

In my React-JS project, I am using Semantic-ui to create form inputs and a submit button. These forms have a property called 'error', and the value of this property is determined by the state. The issue arises when I click on the 'Next&apos ...

Is there a way to eliminate validation-on-blur errors triggered by onBlur events?

I am currently working on a v-text-field that has the capability to handle simple math expressions like 1+1 and display the correct result (2) when the user either presses enter or moves away from the text field. Here's the code I have implemented so ...

Revise the list on the page containing MEANJS components

Utilizing MEAN JS, I am attempting to make edits to the list items on the page, but an error keeps appearing. I have initialized the data using ng-init="find()" for the list and ng-init="findOne()" for individual data. Error: [$resource:badcfg] Error in r ...

What is the process for deleting keys and values from a JSON object?

I am currently working with the Spring Framework and AngularJS in JavaScript. I have successfully made an AJAX request, but encountered an issue when trying to remove certain keys and values from the response data. Here is my code: $.ajax({ type: &apo ...

Using Typescript to collapse the Bootstrap navbar through programming

I've managed to make Bootstrap's navbar collapse successfully using the data-toggle and data-target attributes on each li element. If you're interested, here is a SO answer that explains a way to achieve this without modifying every single ...

Obtain the content enclosed within parentheses using JavaScript

const str = "(c) (d)"; I need to separate the given string into an array The result should be [0] => 'c' [1] => 'd' ...

Leveraging three.js through a content delivery network with the option of incorporating either S

Is it possible to optimize my Svelte or React application by declaring the Three.js module as a script tag that calls the module from a CDN instead of importing it via npm? I want to capitalize on the benefits of a framework while minimizing my final bundl ...