Is there a way to incorporate d3 zoom and pan functionality into a Power BI visualization?

I have a Power BI scatterchart visual that I would like to incorporate d3 zoom and pan functionality into. While I've come across several simple examples of using d3 for zoom and pan in HTML, none of them are tailored specifically for Power BI. I am struggling to adapt these examples into my Power BI typescript visual as I am unsure of where each component should be placed within the code. For instance, I'm uncertain about what should be included in the constructor section versus the update section.

Within my constructor, I have the following setup:

        constructor(options: VisualConstructorOptions) {
        this.host = options.host;
        this.selectionManager = options.host.createSelectionManager();
        this.tooltipServiceWrapper = createTooltipServiceWrapper(this.host.tooltipService, options.element);

        let svg = this.svg = d3.select(options.element)
            .append('svg')
            .classed('scatterChart', true);

        this.plotContainer = svg.append('g')
            .classed('plotContainer', true);

        this.xAxis = svg.append('g')
            .classed('xAxis', true);

        this.yAxis = svg.append('g')
            .classed('yAxis', true);
    }

I initially thought that I should connect the zoom feature either to this.svg or this.plotContainer. However, if that is the case, should this integration take place in the constructor or later in the code, possibly in the update section? I have predominantly attempted to implement it in the update area under the assumption that zoom would be activated by an event, which typically warrant handling in such a section.

Whenever I have attempted to incorporate various components of the examples into my code, aligning them where I believe they belong, the compiler consistently throws errors with the function:

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

The issue seems to revolve around d3.event.translate and d3.event.scale.

I find myself quite perplexed and would greatly appreciate your assistance!

Answer №1

After some trial and error, I managed to solve the issue. Here is a breakdown of what worked for me:

I made an addition at the beginning of the visual's class, right after the line that reads "export class [VISUAL'S NAME (e.g., scatterChart)] implements IVisual {":

        private container: d3.Selection<SVGElement>;

Next, I included this snippet inside the 'constructor' function as a wrapper:

        this.container = svg.append("g");  

The remaining code was placed within the 'update' function.

A crucial element here is what I think is known as a 'listener':

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

Below is where we invoke the zoom functionality.

        this.svg.call(zoom);

Lastly, this is the 'zoomed' function responsible for handling both zooming and panning:

    private zoomed() {
        this.container.attr("transform", "translate(" + ((<any>d3.event).translate) + ")scale(" + ((<any>d3.event).scale) + ")";}

Answer №2

I faced a similar challenge, but eventually found my answer by updating my unique visual to the latest D3 version 7 along with the newest TypeScript bindings available.

You can read more about my journey at

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

"Utilizing @types in npm and the latest version of TypeScript

We've encountered an issue where the files installed via npm on our build machine are not matching the files used locally on our developers' machines. Since we are using TypeScript, we need to install @types for some npm packages. In our package ...

Guide to setting up a Cordova and TypeScript project using the command line interface

For my mobile application development, I rely on Cordova and execute cordova create MyApp in the command-line to initiate a new project. I am familiar with JavaScript but now require TypeScript for my project. Please assist me in setting up a Cordova pro ...

Using Angular 2: leveraging the power of spread and barrel imports!

I've been working on streamlining my code and reducing the amount of import statements needed everywhere. So, in index.ts within my services directory, I created a barrel file: import { Service1} from "./service1.service"; import { Service2 } from " ...

Creating dynamic charts by formatting JSON data for optimal display

Greetings! I'm currently using a c3 chart and have provided the link to the jsfiddle for reference. My goal is to display content based on button clicks. For instance, there are four buttons such as 7Day, and when clicked, it should show the stats of ...

Dispatching an asynchronous function error in React with TypeScript and Redux - the parameter type is not assignable to AnyAction

Currently, I am in the process of developing a web application that utilizes Firebase as its database, along with Redux and TypeScript for state management. Within my code, I have a dispatch function nested inside a callback function like so: export const ...

Please refrain from proceeding until the data recovery process is complete

I am currently facing a priority issue in my code. The problem arises when I call a web service and attempt to retrieve usernames based on user IDs from an array (listePasseoDemandesEnCours) using a foreach loop. this.ws_demandes_en_cours.getDemandesEnCour ...

Retrieve the Document ID from Firebase

I'm currently exploring the functionality of Firebase and enhancing my workflow with "react-firebase-hooks". Is there a way for me to retrieve both the doc id and doc data simultaneously and pass them as props? Currently, I am only able to access the ...

Is NestJS the best choice for enforcing strong typing with TypeScript configurations?

My app has a main configuration expressed through environment variables (process.env). How can I expose it as one object using Next.js? In the code example below, I am able to retrieve values by keys. However, since I am passing a string, TypeScript is not ...

Personalizing list elements with SVG symbols

I have been experimenting with customizing the bullet points of an unordered list in HTML by using icons that I sourced from various websites. Here is the SVG code for the first icon, which is stored in home.svg: <svg xmlns="http://www.w3.org/2000/sv ...

Modified Expression Problem

Scenario : On the left side of the screen, all unpaid bills are displayed. When a user clicks on a bill, its details appear on the right side. Upon clicking the pay button, the bill is marked as paid and should no longer be visible on the left side. This ...

Using TypeScript to define a constant array as a type

I've hit a roadblock in my typescript project while trying to define a suitable type. Here's the setup: Within my project, I have the following constant: export const PROPERTYOPTIONS = [ { value: "tag", label: "Tag" }, { ...

Angular2: Obtain a promise that has already been resolved

Is there a way to generate and return a pre-resolved (even if it's fake) Promise in angular2? In angularjs, you could achieve this by using return $q.defer().promise I have considered trying: return new Observable<any>.toPromise() but I'm ...

What is a more effective approach for managing form data with React's useState hook?

Seeking a more efficient solution to eliminate redundancy in my code. Currently, I am utilizing useState() for managing user data, which results in repetition due to numerous fields. Below is a snippet of my current code: const [lname, setLast] = useState& ...

Explore the differences between the "date" type in HTML and the Date object in Typescript

Here is some code in HTML: <div class="form-group row"> <label class="col-sm-2 col-form-label">Due date: </label> <div class="col-sm-10"> <input type="date" class="form-control" #due_date> ...

Ways to retrieve `CompilerOptions` from the `tsconfig.json` file

Currently, I am delving into the TypeScript compiler API. In order to initialize a program, I need to provide a CompilerOptions object. My goal is to utilize the CompilerOptions specific to a particular tsconfig.json file, but I am struggling to determine ...

Cannot locate AngularJS + Typescript controller

I'm encountering an error while attempting to integrate TypeScript with AngularJS. The issue I'm facing is: Error: [$controller:ctrlreg] The controller named 'MyController' has not been registered Does anyone have any insights on what ...

The maximum nested function level has been reached at tsc:1. Consider increasing the FUNCNEST limit

Having an issue while trying to compile a typescript file, encountering the following error: work/gigMax [typescriptMigration●] » tsc src/mutate.ts tsc:1: maximum nested function level reached; increase FUNCNEST? work/gigMax [typescriptMigration●] ...

Trouble Sending Data from Angular HttpClient to ASP.NET CORE Web API

I have recently developed a new component called "form-page" within the "form" module: The HTML code for form-page.component.html is shown below: <form [formGroup]="form" (submit)="onSubmit()"> <div> <label f ...

Issue with JSON encoding in Embed message/interaction reply in Discord.js v14

I am currently utilizing Discord.js version 14.8, which was developed in typescript. Here is a snippet from my package.json file: "dependencies": { "@discordjs/rest": "^1.1.0", "@supabase/supabase-js": &quo ...

"Encountering difficulties while setting up an Angular project

I am currently working on setting up an Angular project from scratch. Here are the steps I have taken so far: First, I installed Node.js Then, I proceeded to install Angular CLI using the command: npm install -g @angular/cli@latest The versions of the ...