Comments (5)
The error is here:
var sankey = sankey()
You’ve defined both a local var sankey
and an imported symbol import {sankey}
. The local var
takes priority (it masks the import), so you’re trying to initialize the var sankey
with the value undefined, making the above statement equivalent to var sankey = undefined()
.
You must use a different name for your local variable (the Sankey instance) and the Sankey constructor. For example, you could import the symbol with a capital letter:
import {sankey as Sankey} from "d3-sankey";
var sankey = Sankey();
Or you could use a different name for the local variable:
import {sankey} from "d3-sankey";
var graph = sankey();
Also note that your code is importing both the d3 default bundle and individual D3 modules (such as d3-scale). This should work if you have your bundler configured correctly, but is not idiomatic. If you are using ES imports, I recommend you import only the D3 modules and avoid the default bundle.
In the future, please use Stack Overflow tag d3.js to ask for help. Although I make an effort to assist everyone that asks, I am not always available to provide help promptly or directly. Stack Overflow provides a better collaborative forum for self-help: tens of thousands of D3-related questions have already been asked there, and some answered questions may be relevant to you.
When asking for help, please include a link to a live example that demonstrates the issue, preferably on bl.ocks.org. It is often impossible to debug from code snippets alone. Isolate the issue and reduce your code as much as possible before asking for help. The less code you post, the easier it is for someone to debug, and the more likely you are to get a helpful response.
If you have a question about D3’s behavior and want to discuss it with other users, also consider the d3-js Google Group or joining the d3-js Slack.
Thank you! 🤗
from d3-sankey.
You’ll need to use sankey.nodeId if you want to identify nodes by name rather than numeric index.
Again, please use Stack Overflow tag d3.js to ask for help. Although I make an effort to assist everyone that asks, I am not always available to provide help promptly or directly. Stack Overflow provides a better collaborative forum for self-help: tens of thousands of D3-related questions have already been asked there, and some answered questions may be relevant to you.
Thank you! 🤗
from d3-sankey.
Right, I've joined the Slack workspace and will reference this issue there. Just to update on this, as I feel a new post would be unnecessary. I've been trying out some different alterations to the code posted in the OC, including importing all the modules and leaving the import * as d3 out. I'm fine taking this approach as everything that was working seems to be working in this case as well. After posting I tried actually renaming the var declaration and that solved the undefined error. As of right now it looks like.
import React, { Component } from 'react';
import { json } from 'd3-request';
import { rgb } from 'd3-color';
import { interpolateHcl } from 'd3-interpolate';
import { scaleLinear, scaleOrdinal } from 'd3-scale';
import { arc, line, pie, curveMonotoneX } from 'd3-shape';
import { format } from 'd3-format';
import { min, max } from 'd3-array';
import { select } from 'd3-selection';
import { sankey as sankeyGraph, sankeyLinkHorizontal } from 'd3-sankey';
class Graph extends React.Component {
constructor(props) {
super(props);
this.createLineGraph = this.createLineGraph.bind(this);
this.createBarChart = this.createBarChart.bind(this);
this.createPieChart = this.createPieChart.bind(this);
this.createSankeyGraph = this.createSankeyGraph.bind(this);
// this.createRadialChart = this.createRadialChart.bind(this);
this.createTheGraphs = this.createTheGraphs.bind(this);
this.state = {
loading: false
};
}
getDimensions() {
const margin = {top: 20, right: 20, bottom: 20, left: 20},
padding = {top: 40, right: 40, bottom: 40, left: 40},
outerWidth = parseInt(this.props.size[0]),
outerHeight = parseInt(this.props.size[1]),
innerWidth = outerWidth - margin.left - margin.right,
innerHeight = outerHeight - margin.top - margin.bottom,
width = innerWidth - padding.left - padding.right,
height = innerHeight - padding.top - padding.botto,
radius = parseInt(min([innerWidth, innerHeight]) / 2),
donutHole = this.props.type === "DONUT" ? radius / 2 : 0,
color = scaleLinear()
.domain([1, this.props.data.length])
.interpolate(interpolateHcl)
.range([rgb("#AF2192"), rgb("#98D719")]);
// DON'T DO DATA MAPPING ON SANKEY GRAPH SINCE DATA STRUCTURE IS DIFFERENT
if (this.props.type !== "SANKEY") {
// HIGHEST VALUE OF ITEMS IN DATA ARRAY
const dataMax = max(this.props.data.map(item => item.value)),
dataSpread = (innerWidth / this.props.data.length),
// DEPEND SCALE OF ITEMS ON THE Y AXIS BASED ON HIGHEST VALUE
yScale = scaleLinear()
.domain([0, dataMax])
.range([0, innerHeight]),
// GENERATE THE LINE USING THE TOTAL SPACE AVAILABLE FROM THE SIZE PROP DIVIDED BY THE LENGTH OF THE DATA ARRAY
lineGen = line()
.x((d, i) => i * dataSpread)
.y(d => innerHeight - yScale(d))
// CURVEMONOTONEX GAVE THE BEST RESULTS
.curve(curveMonotoneX);
dimensions = {margin, padding, outerWidth, outerHeight, innerWidth, innerHeight, radius, donutHole, color, dataMax, dataSpread, yScale, lineGen};
} else {
dimensions = {margin, padding, outerWidth, outerHeight, innerWidth, innerHeight, radius, donutHole, color};
}
}
// *** ---
createSankeyGraph(data) {
const sankeyNode = this.node;
let graphData = this.props.data;
console.log(this.props.data);
console.log(this.props.data.links);
console.log(this.props.data.nodes);
// GET DIMENSIONS IN A GLOBAL-VAR-LIKE WAY
this.getDimensions();
const formatNumber = format('.1f');
const formatted = function(d) {return formatNumber(d) + " Potential Guests"};
const color = scaleLinear()
.domain([1, 3])
.interpolate(interpolateHcl)
.range([rgb('#126382'), rgb('#417685')]);
var sankey = sankeyGraph()
.nodeWidth(15)
.nodePadding(10)
.extent([1, 1], [dimensions.outerWidth - 1, dimensions.outerHeight - 6]);
var SVG = select(sankeyNode)
.append('g')
.attr('transform', 'translate(' + dimensions.margin.left + ',' + dimensions.margin.top +')');
var node = SVG.append('g')
.attr('class', 'nodes')
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.selectAll('g')
// .attr('class', 'node');
var link = SVG.append('g')
.attr('class', 'links')
.attr("fill", "none")
.attr("stroke", "#000")
.attr("stroke-opacity", 0.2)
.selectAll('path')
// .attr('class', 'link');
// console.log(sankey(this.props.data))
sankeyGraph(graphData);
node = node
.data(graphData.nodes)
.enter()
.append('g')
.attr('class', 'node');
node.append('rect')
.attr('x', function(d) { console.log(d.x0); return d.x0; }) // undefined
.attr('y', function(d) { console.log(d.y0); return d.y0; }) // undefined
.attr('height', function(d) { console.log(d.y1, d.y0); return d.y1 - d.y0}) // undefined undefined
.attr('width', function(d) { console.log(d.x1, d.x0); return d.x1 - d.x0}) // undefined undefined
.attr("fill", function(d, i) { return color(i); })
.attr('stroke', 'black');
node.append('text')
.attr('x', function(d) {return d.x0 - 6})
.attr('y', function(d) {return (d.y1 + d.y0) / 2})
.attr('dy', '.35em')
.attr('text-anchor', 'end')
.text(function(d) { return d.name; })
.filter(function(d) { return d.x0 < dimensions.innerWidth / 2; })
.attr('x', function(d) { return d.x1 + 6; })
.attr('text-anchor', 'start');
node.append('title')
.text(d => d.name + "\n" + formatted(d.value));
link = link
.data(graphData.links)
.enter()
.append('path')
.attr('class', 'link')
.attr('d', sankeyLinkHorizontal())
.attr('stroke-width', function(d) { return Math.max(1, d.width); });
link.append('title')
.text(function(d) { return d.source.name + " → " + d.target.name + "\n" + formatted(d.value); });
}
createTheGraphs() {
(this.props.type === "LINE") ? this.createLineGraph() : "";
(this.props.type === "BAR") ? this.createBarChart() : "";
(this.props.type === "PIE" || this.props.type === "DONUT") ? this.createPieChart() : "";
(this.props.type === "SANKEY") ? this.createSankeyGraph() : "";
(this.props.type === "RADIAL") ? this.createRadialChart() : "";
}
componentWillMount() {
this.setState({ loading: true });
}
componentDidMount() {
this.createTheGraphs();
}
componentDidUpdate() {
this.createTheGraphs();
}
render() {
return(
<div className="Graph">
<svg className='Graph_Container' ref={node => this.node = node}></svg>
<h2>{this.props.type} Placeholder</h2>
</div>
);
}
}
export default Graph;
The issue I'm facing right now is in the comments above. I get returned
node.append('rect')
.attr('x', function(d) { console.log(d.x0); return d.x0; }) // undefined
.attr('y', function(d) { console.log(d.y0); return d.y0; }) // undefined
.attr('height', function(d) { console.log(d.y1, d.y0); return d.y1 - d.y0}) // undefined undefined
.attr('width', function(d) { console.log(d.x1, d.x0); return d.x1 - d.x0}) // undefined undefined
.attr("fill", function(d, i) { return color(i); })
.attr('stroke', 'black');
And as such, it's unable to place the nodes in the SVG container. The text gets processed just fine, it's just the x and y coordinates are not getting returned correctly. The console also shows that
console.log(this.props.data);
console.log(this.props.data.links);
console.log(this.props.data.nodes);
Outputs the data as expected, giving me
Object { nodes: Array[4], links: Array[4] }
Array [ Object, Object, Object, Object ]
Array [ Object, Object, Object, Object ]
Or at least, I figured that's what it should expect given that the contents within (in this case, the text) is getting parsed as it should and shows up in the DOM where it needs to. It has something to do with the d.x and the d.y not getting the data they expect. To add to it, I've been following along with https://bl.ocks.org/mbostock/ca9a0bb7ba204d12974bca90acc507c0, slightly rewriting it to suit the React lifecycle methods just as I did with the other graphs.
--- UPDATE
Changing
sankeyGraph(graphData);
To
sankey(graphData);
Gives a different issue. Here it's missing the nodes which it needs to render the paths / lines between them. Even though the sankey var was declared after importing the sankeyGraph, they both have their quirks.
--- UPDATE2
The error in particular looks like this:
Error: missing: Peter modules.js:54276:20
find http://localhost:3000/packages/modules.js:54276:20
computeNodeLinks/< http://localhost:3000/packages/modules.js:54353:62
forEach self-hosted:267:13
computeNodeLinks http://localhost:3000/packages/modules.js:54350:5
sankey http://localhost:3000/packages/modules.js:54292:5
createSankeyGraph http://localhost:3000/app/app.js:554:13
createSankeyGraph self-hosted:941:17
createTheGraphs http://localhost:3000/app/app.js:598:44
createTheGraphs self-hosted:941:17
componentDidMount http://localhost:3000/app/app.js:617:13
mountComponent/</< http://localhost:3000/packages/modules.js:17838:20
measureLifeCyclePerf http://localhost:3000/packages/modules.js:17649:12
mountComponent/< http://localhost:3000/packages/modules.js:17837:11
notifyAll http://localhost:3000/packages/modules.js:10464:9
close http://localhost:3000/packages/modules.js:20865:5
closeAll http://localhost:3000/packages/modules.js:11623:11
perform http://localhost:3000/packages/modules.js:11570:11
batchedMountComponentIntoNode http://localhost:3000/packages/modules.js:22897:3
perform http://localhost:3000/packages/modules.js:11557:13
batchedUpdates http://localhost:3000/packages/modules.js:20563:14
batchedUpdates http://localhost:3000/packages/modules.js:10225:10
_renderNewRootComponent http://localhost:3000/packages/modules.js:23090:5
_renderSubtreeIntoContainer http://localhost:3000/packages/modules.js:23172:21
render http://localhost:3000/packages/modules.js:23193:12
routes.js/< http://localhost:3000/app/app.js:1504:3
maybeReady http://localhost:3000/packages/meteor.js:821:6
loadingCompleted http://localhost:3000/packages/meteor.js:833:5
The graphData object looks like this:
{
nodes: [
{name: "Peter"},
{name: "Test.com"},
{name: "Thing.com"},
{name: "AnotherName"}
], links: [
{source: "Peter", target: "Test.com", value: 50},
{source: "Peter", target: "Thing.com", value: 50},
{source: "Test.com", target: "AnotherName", value: 50},
{source: "Thing.com", target: "AnotherName", value: 50}
]
}
from d3-sankey.
I've made a post regarding the issue on SO, but no responses as of yet. I'm trying out the numeric approach, using numbers as id's instead of names. Again, it returns the correct HTML, but no size attributes are parsed apart from in the text field. That last bit never happened before either.
<svg class="Graph_Container">
<g transform="translate(20,20)">
<g class="links" fill="none" stroke="#000" stroke-opacity="0.2">
<path d="MNaN,NaNCNaN,NaN,NaN,NaN,NaN,NaN" stroke-width="NaN">
<title>Peter → Test.com 50.0 Potential Guests</title>
</path>
</g>
<g class="nodes" font-family="sans-serif" font-size="10">
<g>
<rect x="NaN" y="NaN" height="NaN" width="NaN" fill="rgb(0, 89, 128)" stroke="black"></rect>
<text x="NaN" y="NaN" dy=".35em" text-anchor="end">Peter</text>
<title>Peter 100.0 Potential Guests</title>
</g>
</g>
</g>
</svg>
The data structure using numeric ids looks like this:
{
nodes: [
{id: 0, name: "Peter"},
{id: 1, name: "Test.com"},
{id: 2, name: "Thing.com"},
{id: 3, name: "AnotherName"}
],
links: [
{source: 0, target: 1, value: 50},
{source: 0, target: 2, value: 50},
{source: 1, target: 3, value: 50},
{source: 2, target: 3, value: 50}
]
}
Returning
Unexpected value NaN parsing x attribute. modules.js:53768:9
Unexpected value NaN parsing y attribute. modules.js:53768:9
Unexpected value NaN parsing height attribute. modules.js:53768:9
Unexpected value NaN parsing width attribute. modules.js:53768:9
Unexpected value NaN parsing x attribute. modules.js:53768:9
Unexpected value NaN parsing y attribute.
I couldn't figure out how to use the .nodeId() in the original example. If you can show me how to use it, I'll have another thing to try out. Numeric ids are a no-no so far :(
from d3-sankey.
Okay, so I got the system finally working using the numeric node ids, changing:
var sankey = sankeyGraph()
.nodes(graphData.nodes)
.links(graphData.links)
.nodeWidth(15)
.nodePadding(10)
.extent([1, 1], [parseInt(width) - 1, parseInt(height) - 6]);
To:
var sankey = sankeyGraph()
.nodes(graphData.nodes)
.links(graphData.links)
.nodeWidth(15)
.nodePadding(10)
.size([width, height])
Now on to the .nodeId() stuff, as I don't even want to imagine what converting all the source / target stuff to id numbers would be like. I can't simply put in the array of objects, as it won't find the id fields. I also seemingly can't use a .map() inside the nodes array, which returns an array with all the field values needed for source / target but won't process it properly.
from d3-sankey.
Related Issues (20)
- Support to apply styles to node title HOT 2
- D3 Sankey customization HOT 1
- nodeAlign not aligning the nodes properly HOT 1
- Y coordinates of links control points calculates with error
- Unwanted circle on link path HOT 1
- Distribute or normalize nodes to fill available space
- Documentation image screenshots look strange with github's dark mode
- Uncaught RangeError: Invalid array length computeNodeBreadths
- Reconsider adding maintainers HOT 1
- Is it possible to sort source or target nodes in one column?
- Little to no activity on this plugin HOT 2
- Issues With Zero Values
- Issues with 0 values
- Empty links with a single node does not seem to work
- Feature request: Allow for a node title that's different than the node ID
- How to control position / alignment of node labels? HOT 2
- sankey with mouseover links not working with d3@6 HOT 1
- Different Link Width at Source and Target HOT 3
- sourceLinks `y0` and `y1` calculated the wrong way round HOT 1
- Setting min height of node to avoid overlap issue HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from d3-sankey.