Reputation: 2617
I'm trying to use bezier lines to connect big circles stacked in a column to smaller circles which are appended onto a linear scale. Here is my snippet:
var margins = {top:100, bottom:300, left:100, right:100};
var height = 1300;
var width = 900;
var totalWidth = width+margins.left+margins.right;
var totalHeight = height+margins.top+margins.bottom;
var svg = d3.select('body')
.append('svg')
.attr('width', totalWidth)
.attr('height', totalHeight);
var graphGroup = svg.append('g')
.attr('transform', "translate("+margins.left+","+margins.top+")");
var yScale = d3.scaleLinear()
.range([450,0])
.domain([-4,4]);
graphGroup.append('g')
.call(d3.axisRight(yScale).ticks(5))
.attr("transform", "translate(350,0)");
var circData = [
{'type':'bonds','growth':3.3},
{'type':'bond funds','growth':0},
{'type':'pstock','growth':-.4},
{'type':'pbonds','growth':.9},
{'type':'ploans','growth':0},
{'type':'debt','growth':.2},
{'type':'other','growth':-2.5},
];
var yScale2 = d3.scaleLinear()
.domain([0,6])
.range([420,30]);
graphGroup.selectAll(null)
.data(circData)
.enter()
.append('circle')
.attr('cx',250)
.attr('cy', function(d,i) {return yScale2(i)})
.attr('r', 20)
.on('click', function(d) {return console.log(this)})
.style('fill',"#003366");
var multiLinkData = [
{source: [250,30], target: [350,39.4]},
{source: [250,95], target: [350,225]},
{source: [250,160], target: [350,248]},
{source: [250,225], target: [350,174]},
{source: [250,290], target: [350,225]},
{source: [250,355], target: [350,213]},
{source: [250,420], target: [350,366]},
];
var link = d3.linkHorizontal();
graphGroup.selectAll(null)
.data(circData)
.enter()
.append('circle')
.attr('cx',350)
.attr('cy', function(d,i) {return yScale(d.growth)})
.attr('r', 7)
.on('click', function(d) {return console.log(this)})
.style('fill',"#003366");
d3.select(null)
.selectAll("path")
.data(multiLinkData)
.join("path")
.attr("d", link)
.attr("fill", "none")
.attr("stroke", "#d9d9d9");
<script src="https://d3js.org/d3.v5.min.js"></script>
As we can see, the big circles and smaller circles are appended as desired, however the bezier lines I'm attempting to connect are not drawn. Error reads:
Uncaught TypeError: .selectAll().data().join() is not a function
However this is pretty much exactly how this tutorial lays out the process.
How can I draw the bezier lines as desired? And as a bonus, how can I append them dynamically? (note I hard-coded multiLinkData
by painstakingly clicking and recording the x/y positions in the console log).
Upvotes: 1
Views: 197
Reputation: 102198
You don't have a container for your paths: with d3.select(null).selectAll("path")
you're telling D3 to append the paths to the d3.select(null)
selection's elements, which makes no sense.
It should be:
graphGroup.selectAll("path")
//etc...
Here is your code with that change:
var margins = {top:100, bottom:300, left:100, right:100};
var height = 1300;
var width = 900;
var totalWidth = width+margins.left+margins.right;
var totalHeight = height+margins.top+margins.bottom;
var svg = d3.select('body')
.append('svg')
.attr('width', totalWidth)
.attr('height', totalHeight);
var graphGroup = svg.append('g')
.attr('transform', "translate("+margins.left+","+margins.top+")");
var yScale = d3.scaleLinear()
.range([450,0])
.domain([-4,4]);
graphGroup.append('g')
.call(d3.axisRight(yScale).ticks(5))
.attr("transform", "translate(350,0)");
var circData = [
{'type':'bonds','growth':3.3},
{'type':'bond funds','growth':0},
{'type':'pstock','growth':-.4},
{'type':'pbonds','growth':.9},
{'type':'ploans','growth':0},
{'type':'debt','growth':.2},
{'type':'other','growth':-2.5},
];
var yScale2 = d3.scaleLinear()
.domain([0,6])
.range([420,30]);
graphGroup.selectAll(null)
.data(circData)
.enter()
.append('circle')
.attr('cx',250)
.attr('cy', function(d,i) {return yScale2(i)})
.attr('r', 20)
.on('click', function(d) {return console.log(this)})
.style('fill',"#003366");
var multiLinkData = [
{source: [250,30], target: [350,39.4]},
{source: [250,95], target: [350,225]},
{source: [250,160], target: [350,248]},
{source: [250,225], target: [350,174]},
{source: [250,290], target: [350,225]},
{source: [250,355], target: [350,213]},
{source: [250,420], target: [350,366]},
];
var link = d3.linkHorizontal();
graphGroup.selectAll(null)
.data(circData)
.enter()
.append('circle')
.attr('cx',350)
.attr('cy', function(d,i) {return yScale(d.growth)})
.attr('r', 7)
.on('click', function(d) {return console.log(this)})
.style('fill',"#003366");
graphGroup.selectAll("path")
.data(multiLinkData)
.join("path")
.attr("d", link)
.attr("fill", "none")
.attr("stroke", "#d9d9d9");
<script src="https://d3js.org/d3.v5.min.js"></script>
Upvotes: 1