-
Notifications
You must be signed in to change notification settings - Fork 144
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
D3 Zoom on Selections? #59
Comments
As documented, d3.zoomTransform takes a node, not a selection. This is because a selection may consist of multiple nodes, and d3.zoomTransform only returns a single transform. I’ve added some clarifying text to the README to make this more obvious. Regarding the implementation: perhaps it could be changed to use the first node from the selection if passed a selection, similar to selection getter methods, but I’d rather avoid overloading the method signature and have usage be consistent. Often this method is used from within an event handler, where you want to pass in Or it could be changed to throw an error if node is a selection, but that seems tailored to the exact error here. Wouldn’t it be better if it throw an error if the given node is not a node? Yet there isn’t a strict definition of what a “node” is in the context of selections, though More generally, D3 does not try very hard to protect against incorrect usage. This is partly a language consequence: JavaScript is a weakly-typed language. Some operations enforce types, while others do not. For example, consider the following abuse of function.apply, which takes an array of arguments as the second argument: function log(message) {
console.log(message);
}
log.apply(null, "hello"); // TypeError: CreateListFromArrayLike called on non-object(…) Yet JavaScript is perfectly happy to take other questionably-array inputs: log.apply(null, {0: "hello"}); // logs "undefined"
log.apply(null, {0: "hello", length: 1}); // logs "hello" As another example, d3.dispatch throws an error if you try to register a callback listener that is not a function. This is so because callbacks are typically invoked asynchronously, and so it’s much easier to debug if there error is thrown when the callback is registered rather than when it is invoked. But if you pass the wrong sort of thing to d3.zoomTransform, the result is synchronous: the returned transform will always be the default identity transform. If you use a debugger, you can step through the code and see why (node.__zoom is undefined). So, I’m not convinced it’s worthwhile to add an assertion here, though if people continue to run into this confusion, then I’ll consider it again in the future. Another option for stronger protection is a language enhancement such as TypeScript; see tomwanzek/d3-v4-definitelytyped and DefinitelyTyped/DefinitelyTyped#9936. |
Thank you for the long and informative response! |
Maybe not an issue but I have a question of whether this is meaningful or not. Consider the example below
The first line is the d3.zoomTransform object on the selection, the second is the zoom transform on the element.
My twofold question is
Is passing a selection to zoomTransform meaningful? I especially ask because all the documentation shows node as an argument.
If not would it be better for d3 to raise an error if I try passing a selection to d3.zoomTransform instead of a node? I spent a couple of hours scratching my head trying to figure out why the initial_transform was not working and it took a while for me to realize I needed to pass the svg node, not the svg selection.
also thanks for the great library!
The text was updated successfully, but these errors were encountered: