Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error when trying to implement zoom in application #32

Closed
brettvitaz opened this issue Jun 15, 2016 · 10 comments
Closed

Error when trying to implement zoom in application #32

brettvitaz opened this issue Jun 15, 2016 · 10 comments

Comments

@brettvitaz
Copy link

brettvitaz commented Jun 15, 2016

I am trying to port existing working code from d3 version 3.5 to 4.0. I am getting the error Uncaught TypeError: Cannot read property 'button' of null (zoom.js:82) when trying to implement zooming in a webpacked React application. I have written a simple example which demonstrates the issue:

import { zoom } from 'd3-zoom';
import { select, event } from 'd3-selection';

function zoomed() {
  console.log(event);
}

function selectSvgRef(ref) {
  const svg = select(ref);

  svg.append('rect')
    .attr('width', 960)
    .attr('height', 500)
    .style('pointer-events', 'all')
    .style('fill', 'steelblue')
    .call(zoom().on('zoom', zoomed))
}

class ZoomBox extends React.Component {
  render() {
    return (
      <svg ref={selectSvgRef} width={960} height={500} >
      </svg>
    );
  }
}

Clicking or scrolling on the svg rect causes the error to be thrown. It is entirely possible that I am messing up the new syntax. Can you please help?

Stack trace:

defaultFilter @ d3-zoom.js:82
wheeled @ d3-zoom.js:261
(anonymous function) @ d3-selection.js:97

edit: fixed code snippet

@mbostock
Copy link
Member

mbostock commented Jun 15, 2016

I see you edited the code snippet, but if you want to look at d3.event, you need to import it, too:

import { select, event } from 'd3-selection';

And you need to refer to event rather than d3Selection.event.

If that doesn’t do it, I am not a Webpack expert, so unfortunately I can’t give specific advice on how to configure Webpack to import from D3’s ES6 modules. I believe that Webpack does not observe jsnext:main (webpack/webpack#1979), so you may need to configure Webpack to import from node_modules/d3-selection/index.js rather than using the provided UMD bundle. Per d3/d3-brush#9 it appears possible to change how Webpack resolves d3-selection, so you can point it to node_modules/d3-selection/index.js rather than the generated UMD bundle (d3-selection.js).

Related, it seems that Babel / Babelify / Browserify observes the __esModule flag that was added in recent builds of the D3 bundles (see d3/d3#2850), and that toolchain at least appears to correctly import the event binding…

See also the comment on d3.event regarding bundlers.

@brettvitaz
Copy link
Author

I had hoped that I didn't make an error when editing the code snippet, but it seems that I did.

I had tried

import { select, event } from 'd3-selection';

as well as

import d3Selection from 'd3-selection';

which is where my hybrid zoomed code came from. I will look into the bundler issue.

Thank you

@ocombe
Copy link

ocombe commented Jul 1, 2016

Here is how you can get the live event with webpack, with require: require("d3-selection").event, this will work if you require it inside your callback. Otherwise it returns null :(
I made a function that I named getEvent:

d3.getEvent = () => require("d3-selection").event;

This way I'm sure I always get a fresh binding on d3.event !

@yanofsky
Copy link

yanofsky commented Jan 31, 2017

To use @ocombe's solution with ES5

d3.getEvent = function(){return require("d3-selection").event}.bind(this);

@cssagogo
Copy link

Using a modified solution of @ocombe's above, I had success with the following:

import { select, event } from 'd3-selection';
import { sum } from 'd3-array';
import { arc, pie } from 'd3-shape';
import { interpolate } from 'd3-interpolate';
import { transition } from 'd3-transition';

const getEvent = () => event;

export const d3 = Object.assign({}, {
    select, event, sum, arc, pie, transition, interpolate, getEvent
});

And then to use it...

const pageX = d3.getEvent().pageX;
const pageY = d3.getEvent().pageY;

@Yohandah
Copy link

Yohandah commented Mar 27, 2020

@ocombe
@yanofsky
@cssagogo

Still doesn't work for me how to apply your fix in my code ? same problem with Angular but it was working before ....

   import * as d3Selection from "d3-selection";
   import * as d3Zoom from "d3-zoom";

   this._svg = d3Selection.select("svg");

    this.zoomD3Event = d3Zoom
      .zoom()
      .scaleExtent([this.ZOOM_MIN, this.ZOOM_MAX])
      .wheelDelta(this.wheelDelta.bind(this))
      .on("zoom", () => {
        if (this.scale !== d3Selection.event.transform.k) {
          this.scale = d3Selection.event.transform.k;
        }

        d3Selection.select("g").attr("transform", d3Selection.event.transform);
      });

    this.scale = 1;

    this._svg.call(this.zoomD3Event).on("dblclick.zoom", undefined);

When I click on the SVG :

core.js:5873 ERROR TypeError: Cannot read property 'ctrlKey' of null
at SVGSVGElement.defaultFilter (zoom.js:13)
at SVGSVGElement.mousedowned (zoom.js:251)

When I scroll :

core.js:5873 ERROR TypeError: Cannot read property 'ctrlKey' of null
at SVGSVGElement.defaultFilter (zoom.js:13)
at SVGSVGElement.wheeled (zoom.js:215)

I have tried to to this but this doesn't work :

   import * as d3Selection from "d3-selection";
   import * as d3Zoom from "d3-zoom";
const getEvent = () => require("d3-selection").event;
this._svg = d3Selection.select("svg");
this.zoomD3Event = d3Zoom
      .zoom()
      .scaleExtent([this.ZOOM_MIN, this.ZOOM_MAX])
      .wheelDelta(this.wheelDelta.bind(this))
      .on("zoom", () => {
        if (this.scale !== getEvent().transform.k) {
          this.scale = getEvent().transform.k;
        }

        d3Selection.select("g").attr("transform", getEvent().transform);
      });

    this.scale = 1;

    this._svg.call(this.zoomD3Event).on("dblclick.zoom", undefined);

@amannn
Copy link

amannn commented Sep 1, 2020

I'm experiencing the same bug as @Yohandah with d3-zoom@2.0.0. Any pointers would be appreciated.

@Fil
Copy link
Member

Fil commented Sep 1, 2020

https://observablehq.com/@d3/d3v6-migration-guide#event_zoom

@HarelM
Copy link

HarelM commented Jun 30, 2021

I'm also getting the ctrlKey issue.
I'm using @katze/ngx-d3 which uses d3 version 5.9.1.
I'm using d3-zoom 3.0.
Should I be using a different version?
Any help would be appreciated, let me know if I should open a new issue for this...

@rafim25
Copy link

rafim25 commented Dec 3, 2021

Please upgrade to latest version to solve the issue . it worked for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

10 participants