d3.js legend overlapping chart area












1















I'm pretty new to D3.js (I'm a R programmer).



I'm trying to create a scatter and put a legend in the right bottom. However, it's overlapping with chart area.



I've been trying to take some examples in internet with no lucky.
When I try to move it to the right, the names and/or symbols are not visible.



I want to place the legend outside the chart frame, so it won't overlap.



Any help is appreciated.



Here's what I tried so far:






d3.csv('https://gist.githubusercontent.com/netj/8836201/raw/6f9306ad21398ea43cba4f7d537619d0e07d5ae3/iris.csv', function(data) {
// CSV section
var body = d3.select('body')
var selectData = [{
"text": "sepal.length"
},
{
"text": "sepal.width"
},
{
"text": "petal.length"
},
{
"text": "petal.width"
},
]

// setup fill color
var colors = ['#575757', '#5FB1B9', '#C94257'];

var symbol = d3.svg.symbol()
.type('circle')
.size("160")

var cValue = function(d) {
return d.variety;
},
color = d3.scale.ordinal()
.range(colors);

// Select Y-axis Variable
var span = body.append('span')
.text('Select Y-Axis variable: ')
var yInput = body.append('select')
.attr('id', 'ySelect')
.on('change', yChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})
body.append('br')


// Select X-axis Variable
var span = body.append('span')
.text('Select X-Axis variable: ')
var yInput = body.append('select')
.attr('id', 'xSelect')
.on('change', xChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})
body.append('br')


// Variables
var body = d3.select('body')
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
}
var h = 500 - margin.top - margin.bottom
var w = 500 - margin.left - margin.right
// var formatPercent = d3.format('.2%')
// Scales
// var colorScale = d3.scale.category20()
var xScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([0, w])
var yScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([h, 0])

// SVG
var svg = body.append('svg')
.attr('height', h + margin.top + margin.bottom)
.attr('width', w + margin.left + margin.right)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')

// X-axis
var xAxis = d3.svg.axis()
.scale(xScale)
// .tickFormat(formatPercent)
.ticks(6)
.outerTickSize(0)
.tickSize(0)

.orient('bottom')

// Y-axis
var yAxis = d3.svg.axis()
.scale(yScale)
// .tickFormat(formatPercent)
.ticks(6)
.tickSize(-w)
.outerTickSize(0)
.orient('left')

// Circles
var circles = svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', function(d) {
return xScale(d['sepal.length'])
})
.attr('cy', function(d) {
return yScale(d['sepal.length'])
})
.attr('r', '10')
// .attr('stroke', 'black')
.attr('stroke-width', 0.2)
.attr("fill", function(d) {
return color(cValue(d));
})
.attr('fill-opacity', 0.8)
// .attr('fill', function(d, i) {
// return colorScale(i)
// })
.on('mouseover', function() {
d3.select(this)
.transition()
.duration(300)
.ease('elastic')
.attr('r', 15)
.attr('stroke-width', 1)
.attr('fill-opacity', 1)

})
.on('mouseout', function() {
d3.select(this)
.transition()
.duration(100)
.attr('r', 10)
.attr('stroke-width', 0.5)
})
.append('title') // Tooltip
.text(function(d) {
return d.variety +
'nSepal Length: ' + d['sepal.length'] +
'nSepal Width: ' + d['sepal.width'] +
'nPetal Length: ' + d['petal.length'] +
'nPetal Width: ' + d['petal.width']
})

// X-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'xAxis')
.attr('transform', 'translate(0,' + h + ')')
.call(xAxis)
.append('text') // X-axis Label
.attr('id', 'xAxisLabel')
.attr('y', -25)
.attr('x', w)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

// labels distance from xaxis
svg.selectAll(".axis text")
.attr("dy", 15);

// Y-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'yAxis')
.call(yAxis)
.append('text') // y-axis Label
.attr('id', 'yAxisLabel')
.attr('transform', 'rotate(-90)')
.attr('x', 0)
.attr('y', 5)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

function yChange() {
var value = this.value // get the new y value
yScale // change the yScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
yAxis.scale(yScale) // change the yScale
d3.select('#yAxis') // redraw the yAxis
.transition().duration(500)
.call(yAxis)
d3.select('#yAxisLabel') // change the yAxisLabel
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cy', function(d) {
return yScale(d[value])
})
}

function xChange() {
var value = this.value // get the new x value
xScale // change the xScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
xAxis.scale(xScale) // change the xScale
d3.select('#xAxis') // redraw the xAxis
.transition().duration(500)
.call(xAxis)
d3.select('#xAxisLabel') // change the xAxisLabel
.transition().duration(500)
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cx', function(d) {
return xScale(d[value])
})
}

// create legend
var legend = svg.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) {
return "translate(0," + i * 25 + ")";
});

// draw legend colored rectangles
legend.append("path")
.attr('d', symbol)
.attr("transform", "translate(434, 313)") //much easier approach to position the symbols
// .attr("x", w + 34)
// .attr("y", h - 97)
// .attr("width", 18)
// .attr("height", 18)
.style("fill", color);

// draw legend text
legend.append("text")
.attr("transform", "translate(422, 311)")
// .attr("x", w + 24)
// .attr("y", h - 89)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) {
return d;
})

})

body {
font-size: 16px;
}


/*
circle {
fill: steelblue;
} */

circle:hover {
fill: orange;
}

.axis text {
font-size: 13px;
/* font-weight: bold; */
}

.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
stroke-width: 0.02px;
}


/* .circle {
fill: orange;
} */

label {
position: absolute;
top: 10px;
right: 10px;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>

<body></body>












share|improve this question




















  • 2





    have you played with margin.right?

    – rioV8
    Nov 21 '18 at 23:20











  • That's what I wanted! I feel stupid now. Thank you though

    – patL
    Nov 21 '18 at 23:37













  • why have you hard coded the position of the legend?

    – rioV8
    Nov 22 '18 at 2:55











  • have a second look at your domain calculations

    – rioV8
    Nov 22 '18 at 3:40











  • @rioV8 As I told in the question, I'm learning D3 from a month. I am a R programmer and there're something that I still don't understand. What is the easiest way to calculate domain?

    – patL
    Nov 23 '18 at 23:10
















1















I'm pretty new to D3.js (I'm a R programmer).



I'm trying to create a scatter and put a legend in the right bottom. However, it's overlapping with chart area.



I've been trying to take some examples in internet with no lucky.
When I try to move it to the right, the names and/or symbols are not visible.



I want to place the legend outside the chart frame, so it won't overlap.



Any help is appreciated.



Here's what I tried so far:






d3.csv('https://gist.githubusercontent.com/netj/8836201/raw/6f9306ad21398ea43cba4f7d537619d0e07d5ae3/iris.csv', function(data) {
// CSV section
var body = d3.select('body')
var selectData = [{
"text": "sepal.length"
},
{
"text": "sepal.width"
},
{
"text": "petal.length"
},
{
"text": "petal.width"
},
]

// setup fill color
var colors = ['#575757', '#5FB1B9', '#C94257'];

var symbol = d3.svg.symbol()
.type('circle')
.size("160")

var cValue = function(d) {
return d.variety;
},
color = d3.scale.ordinal()
.range(colors);

// Select Y-axis Variable
var span = body.append('span')
.text('Select Y-Axis variable: ')
var yInput = body.append('select')
.attr('id', 'ySelect')
.on('change', yChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})
body.append('br')


// Select X-axis Variable
var span = body.append('span')
.text('Select X-Axis variable: ')
var yInput = body.append('select')
.attr('id', 'xSelect')
.on('change', xChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})
body.append('br')


// Variables
var body = d3.select('body')
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
}
var h = 500 - margin.top - margin.bottom
var w = 500 - margin.left - margin.right
// var formatPercent = d3.format('.2%')
// Scales
// var colorScale = d3.scale.category20()
var xScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([0, w])
var yScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([h, 0])

// SVG
var svg = body.append('svg')
.attr('height', h + margin.top + margin.bottom)
.attr('width', w + margin.left + margin.right)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')

// X-axis
var xAxis = d3.svg.axis()
.scale(xScale)
// .tickFormat(formatPercent)
.ticks(6)
.outerTickSize(0)
.tickSize(0)

.orient('bottom')

// Y-axis
var yAxis = d3.svg.axis()
.scale(yScale)
// .tickFormat(formatPercent)
.ticks(6)
.tickSize(-w)
.outerTickSize(0)
.orient('left')

// Circles
var circles = svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', function(d) {
return xScale(d['sepal.length'])
})
.attr('cy', function(d) {
return yScale(d['sepal.length'])
})
.attr('r', '10')
// .attr('stroke', 'black')
.attr('stroke-width', 0.2)
.attr("fill", function(d) {
return color(cValue(d));
})
.attr('fill-opacity', 0.8)
// .attr('fill', function(d, i) {
// return colorScale(i)
// })
.on('mouseover', function() {
d3.select(this)
.transition()
.duration(300)
.ease('elastic')
.attr('r', 15)
.attr('stroke-width', 1)
.attr('fill-opacity', 1)

})
.on('mouseout', function() {
d3.select(this)
.transition()
.duration(100)
.attr('r', 10)
.attr('stroke-width', 0.5)
})
.append('title') // Tooltip
.text(function(d) {
return d.variety +
'nSepal Length: ' + d['sepal.length'] +
'nSepal Width: ' + d['sepal.width'] +
'nPetal Length: ' + d['petal.length'] +
'nPetal Width: ' + d['petal.width']
})

// X-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'xAxis')
.attr('transform', 'translate(0,' + h + ')')
.call(xAxis)
.append('text') // X-axis Label
.attr('id', 'xAxisLabel')
.attr('y', -25)
.attr('x', w)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

// labels distance from xaxis
svg.selectAll(".axis text")
.attr("dy", 15);

// Y-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'yAxis')
.call(yAxis)
.append('text') // y-axis Label
.attr('id', 'yAxisLabel')
.attr('transform', 'rotate(-90)')
.attr('x', 0)
.attr('y', 5)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

function yChange() {
var value = this.value // get the new y value
yScale // change the yScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
yAxis.scale(yScale) // change the yScale
d3.select('#yAxis') // redraw the yAxis
.transition().duration(500)
.call(yAxis)
d3.select('#yAxisLabel') // change the yAxisLabel
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cy', function(d) {
return yScale(d[value])
})
}

function xChange() {
var value = this.value // get the new x value
xScale // change the xScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
xAxis.scale(xScale) // change the xScale
d3.select('#xAxis') // redraw the xAxis
.transition().duration(500)
.call(xAxis)
d3.select('#xAxisLabel') // change the xAxisLabel
.transition().duration(500)
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cx', function(d) {
return xScale(d[value])
})
}

// create legend
var legend = svg.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) {
return "translate(0," + i * 25 + ")";
});

// draw legend colored rectangles
legend.append("path")
.attr('d', symbol)
.attr("transform", "translate(434, 313)") //much easier approach to position the symbols
// .attr("x", w + 34)
// .attr("y", h - 97)
// .attr("width", 18)
// .attr("height", 18)
.style("fill", color);

// draw legend text
legend.append("text")
.attr("transform", "translate(422, 311)")
// .attr("x", w + 24)
// .attr("y", h - 89)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) {
return d;
})

})

body {
font-size: 16px;
}


/*
circle {
fill: steelblue;
} */

circle:hover {
fill: orange;
}

.axis text {
font-size: 13px;
/* font-weight: bold; */
}

.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
stroke-width: 0.02px;
}


/* .circle {
fill: orange;
} */

label {
position: absolute;
top: 10px;
right: 10px;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>

<body></body>












share|improve this question




















  • 2





    have you played with margin.right?

    – rioV8
    Nov 21 '18 at 23:20











  • That's what I wanted! I feel stupid now. Thank you though

    – patL
    Nov 21 '18 at 23:37













  • why have you hard coded the position of the legend?

    – rioV8
    Nov 22 '18 at 2:55











  • have a second look at your domain calculations

    – rioV8
    Nov 22 '18 at 3:40











  • @rioV8 As I told in the question, I'm learning D3 from a month. I am a R programmer and there're something that I still don't understand. What is the easiest way to calculate domain?

    – patL
    Nov 23 '18 at 23:10














1












1








1








I'm pretty new to D3.js (I'm a R programmer).



I'm trying to create a scatter and put a legend in the right bottom. However, it's overlapping with chart area.



I've been trying to take some examples in internet with no lucky.
When I try to move it to the right, the names and/or symbols are not visible.



I want to place the legend outside the chart frame, so it won't overlap.



Any help is appreciated.



Here's what I tried so far:






d3.csv('https://gist.githubusercontent.com/netj/8836201/raw/6f9306ad21398ea43cba4f7d537619d0e07d5ae3/iris.csv', function(data) {
// CSV section
var body = d3.select('body')
var selectData = [{
"text": "sepal.length"
},
{
"text": "sepal.width"
},
{
"text": "petal.length"
},
{
"text": "petal.width"
},
]

// setup fill color
var colors = ['#575757', '#5FB1B9', '#C94257'];

var symbol = d3.svg.symbol()
.type('circle')
.size("160")

var cValue = function(d) {
return d.variety;
},
color = d3.scale.ordinal()
.range(colors);

// Select Y-axis Variable
var span = body.append('span')
.text('Select Y-Axis variable: ')
var yInput = body.append('select')
.attr('id', 'ySelect')
.on('change', yChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})
body.append('br')


// Select X-axis Variable
var span = body.append('span')
.text('Select X-Axis variable: ')
var yInput = body.append('select')
.attr('id', 'xSelect')
.on('change', xChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})
body.append('br')


// Variables
var body = d3.select('body')
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
}
var h = 500 - margin.top - margin.bottom
var w = 500 - margin.left - margin.right
// var formatPercent = d3.format('.2%')
// Scales
// var colorScale = d3.scale.category20()
var xScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([0, w])
var yScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([h, 0])

// SVG
var svg = body.append('svg')
.attr('height', h + margin.top + margin.bottom)
.attr('width', w + margin.left + margin.right)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')

// X-axis
var xAxis = d3.svg.axis()
.scale(xScale)
// .tickFormat(formatPercent)
.ticks(6)
.outerTickSize(0)
.tickSize(0)

.orient('bottom')

// Y-axis
var yAxis = d3.svg.axis()
.scale(yScale)
// .tickFormat(formatPercent)
.ticks(6)
.tickSize(-w)
.outerTickSize(0)
.orient('left')

// Circles
var circles = svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', function(d) {
return xScale(d['sepal.length'])
})
.attr('cy', function(d) {
return yScale(d['sepal.length'])
})
.attr('r', '10')
// .attr('stroke', 'black')
.attr('stroke-width', 0.2)
.attr("fill", function(d) {
return color(cValue(d));
})
.attr('fill-opacity', 0.8)
// .attr('fill', function(d, i) {
// return colorScale(i)
// })
.on('mouseover', function() {
d3.select(this)
.transition()
.duration(300)
.ease('elastic')
.attr('r', 15)
.attr('stroke-width', 1)
.attr('fill-opacity', 1)

})
.on('mouseout', function() {
d3.select(this)
.transition()
.duration(100)
.attr('r', 10)
.attr('stroke-width', 0.5)
})
.append('title') // Tooltip
.text(function(d) {
return d.variety +
'nSepal Length: ' + d['sepal.length'] +
'nSepal Width: ' + d['sepal.width'] +
'nPetal Length: ' + d['petal.length'] +
'nPetal Width: ' + d['petal.width']
})

// X-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'xAxis')
.attr('transform', 'translate(0,' + h + ')')
.call(xAxis)
.append('text') // X-axis Label
.attr('id', 'xAxisLabel')
.attr('y', -25)
.attr('x', w)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

// labels distance from xaxis
svg.selectAll(".axis text")
.attr("dy", 15);

// Y-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'yAxis')
.call(yAxis)
.append('text') // y-axis Label
.attr('id', 'yAxisLabel')
.attr('transform', 'rotate(-90)')
.attr('x', 0)
.attr('y', 5)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

function yChange() {
var value = this.value // get the new y value
yScale // change the yScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
yAxis.scale(yScale) // change the yScale
d3.select('#yAxis') // redraw the yAxis
.transition().duration(500)
.call(yAxis)
d3.select('#yAxisLabel') // change the yAxisLabel
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cy', function(d) {
return yScale(d[value])
})
}

function xChange() {
var value = this.value // get the new x value
xScale // change the xScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
xAxis.scale(xScale) // change the xScale
d3.select('#xAxis') // redraw the xAxis
.transition().duration(500)
.call(xAxis)
d3.select('#xAxisLabel') // change the xAxisLabel
.transition().duration(500)
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cx', function(d) {
return xScale(d[value])
})
}

// create legend
var legend = svg.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) {
return "translate(0," + i * 25 + ")";
});

// draw legend colored rectangles
legend.append("path")
.attr('d', symbol)
.attr("transform", "translate(434, 313)") //much easier approach to position the symbols
// .attr("x", w + 34)
// .attr("y", h - 97)
// .attr("width", 18)
// .attr("height", 18)
.style("fill", color);

// draw legend text
legend.append("text")
.attr("transform", "translate(422, 311)")
// .attr("x", w + 24)
// .attr("y", h - 89)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) {
return d;
})

})

body {
font-size: 16px;
}


/*
circle {
fill: steelblue;
} */

circle:hover {
fill: orange;
}

.axis text {
font-size: 13px;
/* font-weight: bold; */
}

.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
stroke-width: 0.02px;
}


/* .circle {
fill: orange;
} */

label {
position: absolute;
top: 10px;
right: 10px;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>

<body></body>












share|improve this question
















I'm pretty new to D3.js (I'm a R programmer).



I'm trying to create a scatter and put a legend in the right bottom. However, it's overlapping with chart area.



I've been trying to take some examples in internet with no lucky.
When I try to move it to the right, the names and/or symbols are not visible.



I want to place the legend outside the chart frame, so it won't overlap.



Any help is appreciated.



Here's what I tried so far:






d3.csv('https://gist.githubusercontent.com/netj/8836201/raw/6f9306ad21398ea43cba4f7d537619d0e07d5ae3/iris.csv', function(data) {
// CSV section
var body = d3.select('body')
var selectData = [{
"text": "sepal.length"
},
{
"text": "sepal.width"
},
{
"text": "petal.length"
},
{
"text": "petal.width"
},
]

// setup fill color
var colors = ['#575757', '#5FB1B9', '#C94257'];

var symbol = d3.svg.symbol()
.type('circle')
.size("160")

var cValue = function(d) {
return d.variety;
},
color = d3.scale.ordinal()
.range(colors);

// Select Y-axis Variable
var span = body.append('span')
.text('Select Y-Axis variable: ')
var yInput = body.append('select')
.attr('id', 'ySelect')
.on('change', yChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})
body.append('br')


// Select X-axis Variable
var span = body.append('span')
.text('Select X-Axis variable: ')
var yInput = body.append('select')
.attr('id', 'xSelect')
.on('change', xChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})
body.append('br')


// Variables
var body = d3.select('body')
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
}
var h = 500 - margin.top - margin.bottom
var w = 500 - margin.left - margin.right
// var formatPercent = d3.format('.2%')
// Scales
// var colorScale = d3.scale.category20()
var xScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([0, w])
var yScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([h, 0])

// SVG
var svg = body.append('svg')
.attr('height', h + margin.top + margin.bottom)
.attr('width', w + margin.left + margin.right)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')

// X-axis
var xAxis = d3.svg.axis()
.scale(xScale)
// .tickFormat(formatPercent)
.ticks(6)
.outerTickSize(0)
.tickSize(0)

.orient('bottom')

// Y-axis
var yAxis = d3.svg.axis()
.scale(yScale)
// .tickFormat(formatPercent)
.ticks(6)
.tickSize(-w)
.outerTickSize(0)
.orient('left')

// Circles
var circles = svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', function(d) {
return xScale(d['sepal.length'])
})
.attr('cy', function(d) {
return yScale(d['sepal.length'])
})
.attr('r', '10')
// .attr('stroke', 'black')
.attr('stroke-width', 0.2)
.attr("fill", function(d) {
return color(cValue(d));
})
.attr('fill-opacity', 0.8)
// .attr('fill', function(d, i) {
// return colorScale(i)
// })
.on('mouseover', function() {
d3.select(this)
.transition()
.duration(300)
.ease('elastic')
.attr('r', 15)
.attr('stroke-width', 1)
.attr('fill-opacity', 1)

})
.on('mouseout', function() {
d3.select(this)
.transition()
.duration(100)
.attr('r', 10)
.attr('stroke-width', 0.5)
})
.append('title') // Tooltip
.text(function(d) {
return d.variety +
'nSepal Length: ' + d['sepal.length'] +
'nSepal Width: ' + d['sepal.width'] +
'nPetal Length: ' + d['petal.length'] +
'nPetal Width: ' + d['petal.width']
})

// X-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'xAxis')
.attr('transform', 'translate(0,' + h + ')')
.call(xAxis)
.append('text') // X-axis Label
.attr('id', 'xAxisLabel')
.attr('y', -25)
.attr('x', w)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

// labels distance from xaxis
svg.selectAll(".axis text")
.attr("dy", 15);

// Y-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'yAxis')
.call(yAxis)
.append('text') // y-axis Label
.attr('id', 'yAxisLabel')
.attr('transform', 'rotate(-90)')
.attr('x', 0)
.attr('y', 5)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

function yChange() {
var value = this.value // get the new y value
yScale // change the yScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
yAxis.scale(yScale) // change the yScale
d3.select('#yAxis') // redraw the yAxis
.transition().duration(500)
.call(yAxis)
d3.select('#yAxisLabel') // change the yAxisLabel
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cy', function(d) {
return yScale(d[value])
})
}

function xChange() {
var value = this.value // get the new x value
xScale // change the xScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
xAxis.scale(xScale) // change the xScale
d3.select('#xAxis') // redraw the xAxis
.transition().duration(500)
.call(xAxis)
d3.select('#xAxisLabel') // change the xAxisLabel
.transition().duration(500)
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cx', function(d) {
return xScale(d[value])
})
}

// create legend
var legend = svg.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) {
return "translate(0," + i * 25 + ")";
});

// draw legend colored rectangles
legend.append("path")
.attr('d', symbol)
.attr("transform", "translate(434, 313)") //much easier approach to position the symbols
// .attr("x", w + 34)
// .attr("y", h - 97)
// .attr("width", 18)
// .attr("height", 18)
.style("fill", color);

// draw legend text
legend.append("text")
.attr("transform", "translate(422, 311)")
// .attr("x", w + 24)
// .attr("y", h - 89)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) {
return d;
})

})

body {
font-size: 16px;
}


/*
circle {
fill: steelblue;
} */

circle:hover {
fill: orange;
}

.axis text {
font-size: 13px;
/* font-weight: bold; */
}

.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
stroke-width: 0.02px;
}


/* .circle {
fill: orange;
} */

label {
position: absolute;
top: 10px;
right: 10px;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>

<body></body>








d3.csv('https://gist.githubusercontent.com/netj/8836201/raw/6f9306ad21398ea43cba4f7d537619d0e07d5ae3/iris.csv', function(data) {
// CSV section
var body = d3.select('body')
var selectData = [{
"text": "sepal.length"
},
{
"text": "sepal.width"
},
{
"text": "petal.length"
},
{
"text": "petal.width"
},
]

// setup fill color
var colors = ['#575757', '#5FB1B9', '#C94257'];

var symbol = d3.svg.symbol()
.type('circle')
.size("160")

var cValue = function(d) {
return d.variety;
},
color = d3.scale.ordinal()
.range(colors);

// Select Y-axis Variable
var span = body.append('span')
.text('Select Y-Axis variable: ')
var yInput = body.append('select')
.attr('id', 'ySelect')
.on('change', yChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})
body.append('br')


// Select X-axis Variable
var span = body.append('span')
.text('Select X-Axis variable: ')
var yInput = body.append('select')
.attr('id', 'xSelect')
.on('change', xChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})
body.append('br')


// Variables
var body = d3.select('body')
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
}
var h = 500 - margin.top - margin.bottom
var w = 500 - margin.left - margin.right
// var formatPercent = d3.format('.2%')
// Scales
// var colorScale = d3.scale.category20()
var xScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([0, w])
var yScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([h, 0])

// SVG
var svg = body.append('svg')
.attr('height', h + margin.top + margin.bottom)
.attr('width', w + margin.left + margin.right)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')

// X-axis
var xAxis = d3.svg.axis()
.scale(xScale)
// .tickFormat(formatPercent)
.ticks(6)
.outerTickSize(0)
.tickSize(0)

.orient('bottom')

// Y-axis
var yAxis = d3.svg.axis()
.scale(yScale)
// .tickFormat(formatPercent)
.ticks(6)
.tickSize(-w)
.outerTickSize(0)
.orient('left')

// Circles
var circles = svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', function(d) {
return xScale(d['sepal.length'])
})
.attr('cy', function(d) {
return yScale(d['sepal.length'])
})
.attr('r', '10')
// .attr('stroke', 'black')
.attr('stroke-width', 0.2)
.attr("fill", function(d) {
return color(cValue(d));
})
.attr('fill-opacity', 0.8)
// .attr('fill', function(d, i) {
// return colorScale(i)
// })
.on('mouseover', function() {
d3.select(this)
.transition()
.duration(300)
.ease('elastic')
.attr('r', 15)
.attr('stroke-width', 1)
.attr('fill-opacity', 1)

})
.on('mouseout', function() {
d3.select(this)
.transition()
.duration(100)
.attr('r', 10)
.attr('stroke-width', 0.5)
})
.append('title') // Tooltip
.text(function(d) {
return d.variety +
'nSepal Length: ' + d['sepal.length'] +
'nSepal Width: ' + d['sepal.width'] +
'nPetal Length: ' + d['petal.length'] +
'nPetal Width: ' + d['petal.width']
})

// X-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'xAxis')
.attr('transform', 'translate(0,' + h + ')')
.call(xAxis)
.append('text') // X-axis Label
.attr('id', 'xAxisLabel')
.attr('y', -25)
.attr('x', w)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

// labels distance from xaxis
svg.selectAll(".axis text")
.attr("dy", 15);

// Y-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'yAxis')
.call(yAxis)
.append('text') // y-axis Label
.attr('id', 'yAxisLabel')
.attr('transform', 'rotate(-90)')
.attr('x', 0)
.attr('y', 5)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

function yChange() {
var value = this.value // get the new y value
yScale // change the yScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
yAxis.scale(yScale) // change the yScale
d3.select('#yAxis') // redraw the yAxis
.transition().duration(500)
.call(yAxis)
d3.select('#yAxisLabel') // change the yAxisLabel
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cy', function(d) {
return yScale(d[value])
})
}

function xChange() {
var value = this.value // get the new x value
xScale // change the xScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
xAxis.scale(xScale) // change the xScale
d3.select('#xAxis') // redraw the xAxis
.transition().duration(500)
.call(xAxis)
d3.select('#xAxisLabel') // change the xAxisLabel
.transition().duration(500)
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cx', function(d) {
return xScale(d[value])
})
}

// create legend
var legend = svg.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) {
return "translate(0," + i * 25 + ")";
});

// draw legend colored rectangles
legend.append("path")
.attr('d', symbol)
.attr("transform", "translate(434, 313)") //much easier approach to position the symbols
// .attr("x", w + 34)
// .attr("y", h - 97)
// .attr("width", 18)
// .attr("height", 18)
.style("fill", color);

// draw legend text
legend.append("text")
.attr("transform", "translate(422, 311)")
// .attr("x", w + 24)
// .attr("y", h - 89)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) {
return d;
})

})

body {
font-size: 16px;
}


/*
circle {
fill: steelblue;
} */

circle:hover {
fill: orange;
}

.axis text {
font-size: 13px;
/* font-weight: bold; */
}

.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
stroke-width: 0.02px;
}


/* .circle {
fill: orange;
} */

label {
position: absolute;
top: 10px;
right: 10px;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>

<body></body>





d3.csv('https://gist.githubusercontent.com/netj/8836201/raw/6f9306ad21398ea43cba4f7d537619d0e07d5ae3/iris.csv', function(data) {
// CSV section
var body = d3.select('body')
var selectData = [{
"text": "sepal.length"
},
{
"text": "sepal.width"
},
{
"text": "petal.length"
},
{
"text": "petal.width"
},
]

// setup fill color
var colors = ['#575757', '#5FB1B9', '#C94257'];

var symbol = d3.svg.symbol()
.type('circle')
.size("160")

var cValue = function(d) {
return d.variety;
},
color = d3.scale.ordinal()
.range(colors);

// Select Y-axis Variable
var span = body.append('span')
.text('Select Y-Axis variable: ')
var yInput = body.append('select')
.attr('id', 'ySelect')
.on('change', yChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})
body.append('br')


// Select X-axis Variable
var span = body.append('span')
.text('Select X-Axis variable: ')
var yInput = body.append('select')
.attr('id', 'xSelect')
.on('change', xChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})
body.append('br')


// Variables
var body = d3.select('body')
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
}
var h = 500 - margin.top - margin.bottom
var w = 500 - margin.left - margin.right
// var formatPercent = d3.format('.2%')
// Scales
// var colorScale = d3.scale.category20()
var xScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([0, w])
var yScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([h, 0])

// SVG
var svg = body.append('svg')
.attr('height', h + margin.top + margin.bottom)
.attr('width', w + margin.left + margin.right)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')

// X-axis
var xAxis = d3.svg.axis()
.scale(xScale)
// .tickFormat(formatPercent)
.ticks(6)
.outerTickSize(0)
.tickSize(0)

.orient('bottom')

// Y-axis
var yAxis = d3.svg.axis()
.scale(yScale)
// .tickFormat(formatPercent)
.ticks(6)
.tickSize(-w)
.outerTickSize(0)
.orient('left')

// Circles
var circles = svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', function(d) {
return xScale(d['sepal.length'])
})
.attr('cy', function(d) {
return yScale(d['sepal.length'])
})
.attr('r', '10')
// .attr('stroke', 'black')
.attr('stroke-width', 0.2)
.attr("fill", function(d) {
return color(cValue(d));
})
.attr('fill-opacity', 0.8)
// .attr('fill', function(d, i) {
// return colorScale(i)
// })
.on('mouseover', function() {
d3.select(this)
.transition()
.duration(300)
.ease('elastic')
.attr('r', 15)
.attr('stroke-width', 1)
.attr('fill-opacity', 1)

})
.on('mouseout', function() {
d3.select(this)
.transition()
.duration(100)
.attr('r', 10)
.attr('stroke-width', 0.5)
})
.append('title') // Tooltip
.text(function(d) {
return d.variety +
'nSepal Length: ' + d['sepal.length'] +
'nSepal Width: ' + d['sepal.width'] +
'nPetal Length: ' + d['petal.length'] +
'nPetal Width: ' + d['petal.width']
})

// X-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'xAxis')
.attr('transform', 'translate(0,' + h + ')')
.call(xAxis)
.append('text') // X-axis Label
.attr('id', 'xAxisLabel')
.attr('y', -25)
.attr('x', w)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

// labels distance from xaxis
svg.selectAll(".axis text")
.attr("dy", 15);

// Y-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'yAxis')
.call(yAxis)
.append('text') // y-axis Label
.attr('id', 'yAxisLabel')
.attr('transform', 'rotate(-90)')
.attr('x', 0)
.attr('y', 5)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

function yChange() {
var value = this.value // get the new y value
yScale // change the yScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
yAxis.scale(yScale) // change the yScale
d3.select('#yAxis') // redraw the yAxis
.transition().duration(500)
.call(yAxis)
d3.select('#yAxisLabel') // change the yAxisLabel
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cy', function(d) {
return yScale(d[value])
})
}

function xChange() {
var value = this.value // get the new x value
xScale // change the xScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
xAxis.scale(xScale) // change the xScale
d3.select('#xAxis') // redraw the xAxis
.transition().duration(500)
.call(xAxis)
d3.select('#xAxisLabel') // change the xAxisLabel
.transition().duration(500)
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cx', function(d) {
return xScale(d[value])
})
}

// create legend
var legend = svg.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) {
return "translate(0," + i * 25 + ")";
});

// draw legend colored rectangles
legend.append("path")
.attr('d', symbol)
.attr("transform", "translate(434, 313)") //much easier approach to position the symbols
// .attr("x", w + 34)
// .attr("y", h - 97)
// .attr("width", 18)
// .attr("height", 18)
.style("fill", color);

// draw legend text
legend.append("text")
.attr("transform", "translate(422, 311)")
// .attr("x", w + 24)
// .attr("y", h - 89)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) {
return d;
})

})

body {
font-size: 16px;
}


/*
circle {
fill: steelblue;
} */

circle:hover {
fill: orange;
}

.axis text {
font-size: 13px;
/* font-weight: bold; */
}

.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
stroke-width: 0.02px;
}


/* .circle {
fill: orange;
} */

label {
position: absolute;
top: 10px;
right: 10px;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>

<body></body>






javascript d3.js legend scatter-plot






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 22 '18 at 10:04









ksav

4,63221329




4,63221329










asked Nov 21 '18 at 22:50









patLpatL

9961624




9961624








  • 2





    have you played with margin.right?

    – rioV8
    Nov 21 '18 at 23:20











  • That's what I wanted! I feel stupid now. Thank you though

    – patL
    Nov 21 '18 at 23:37













  • why have you hard coded the position of the legend?

    – rioV8
    Nov 22 '18 at 2:55











  • have a second look at your domain calculations

    – rioV8
    Nov 22 '18 at 3:40











  • @rioV8 As I told in the question, I'm learning D3 from a month. I am a R programmer and there're something that I still don't understand. What is the easiest way to calculate domain?

    – patL
    Nov 23 '18 at 23:10














  • 2





    have you played with margin.right?

    – rioV8
    Nov 21 '18 at 23:20











  • That's what I wanted! I feel stupid now. Thank you though

    – patL
    Nov 21 '18 at 23:37













  • why have you hard coded the position of the legend?

    – rioV8
    Nov 22 '18 at 2:55











  • have a second look at your domain calculations

    – rioV8
    Nov 22 '18 at 3:40











  • @rioV8 As I told in the question, I'm learning D3 from a month. I am a R programmer and there're something that I still don't understand. What is the easiest way to calculate domain?

    – patL
    Nov 23 '18 at 23:10








2




2





have you played with margin.right?

– rioV8
Nov 21 '18 at 23:20





have you played with margin.right?

– rioV8
Nov 21 '18 at 23:20













That's what I wanted! I feel stupid now. Thank you though

– patL
Nov 21 '18 at 23:37







That's what I wanted! I feel stupid now. Thank you though

– patL
Nov 21 '18 at 23:37















why have you hard coded the position of the legend?

– rioV8
Nov 22 '18 at 2:55





why have you hard coded the position of the legend?

– rioV8
Nov 22 '18 at 2:55













have a second look at your domain calculations

– rioV8
Nov 22 '18 at 3:40





have a second look at your domain calculations

– rioV8
Nov 22 '18 at 3:40













@rioV8 As I told in the question, I'm learning D3 from a month. I am a R programmer and there're something that I still don't understand. What is the easiest way to calculate domain?

– patL
Nov 23 '18 at 23:10





@rioV8 As I told in the question, I'm learning D3 from a month. I am a R programmer and there're something that I still don't understand. What is the easiest way to calculate domain?

– patL
Nov 23 '18 at 23:10












1 Answer
1






active

oldest

votes


















1














Why not just render your legend as HTML and use CSS to help with layout?






d3.csv('https://gist.githubusercontent.com/netj/8836201/raw/6f9306ad21398ea43cba4f7d537619d0e07d5ae3/iris.csv', function(data) {
// CSV section
var body = d3.select('body')
var selectData = [{
"text": "sepal.length"
},
{
"text": "sepal.width"
},
{
"text": "petal.length"
},
{
"text": "petal.width"
},
]

// setup fill color
var colors = ['#575757', '#5FB1B9', '#C94257'];

var symbol = d3.svg.symbol()
.type('circle')
.size("160")

var cValue = function(d) {
return d.variety;
},
color = d3.scale.ordinal()
.range(colors);

var controls = body.append('div').attr('class', 'controls')


// Select Y-axis Variable
var yControls = controls.append('div')
var span = yControls.append('span')
.text('Select Y-Axis variable: ')
var yInput = yControls.append('select')
.attr('id', 'ySelect')
.on('change', yChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})



// Select X-axis Variable
var xControls = controls.append('div')
var span = xControls.append('span')
.text('Select X-Axis variable: ')
var yInput = xControls.append('select')
.attr('id', 'xSelect')
.on('change', xChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})


// Variables
var body = d3.select('body')
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
}
var h = 500 - margin.top - margin.bottom
var w = 500 - margin.left - margin.right

var xScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([0, w])
var yScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([h, 0])

// SVG
var svgContainer = body.append('div').attr('class', 'svg-container')

var svg = svgContainer.append('svg')
.attr('height', h + margin.top + margin.bottom)
.attr('width', w + margin.left + margin.right)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')

// X-axis
var xAxis = d3.svg.axis()
.scale(xScale)
// .tickFormat(formatPercent)
.ticks(6)
.outerTickSize(0)
.tickSize(0)

.orient('bottom')

// Y-axis
var yAxis = d3.svg.axis()
.scale(yScale)
// .tickFormat(formatPercent)
.ticks(6)
.tickSize(-w)
.outerTickSize(0)
.orient('left')

// Circles
var circles = svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', function(d) {
return xScale(d['sepal.length'])
})
.attr('cy', function(d) {
return yScale(d['sepal.length'])
})
.attr('r', '10')
// .attr('stroke', 'black')
.attr('stroke-width', 0.2)
.attr("fill", function(d) {
return color(cValue(d));
})
.attr('fill-opacity', 0.8)
// .attr('fill', function(d, i) {
// return colorScale(i)
// })
.on('mouseover', function() {
d3.select(this)
.transition()
.duration(300)
.ease('elastic')
.attr('r', 15)
.attr('stroke-width', 1)
.attr('fill-opacity', 1)

})
.on('mouseout', function() {
d3.select(this)
.transition()
.duration(100)
.attr('r', 10)
.attr('stroke-width', 0.5)
})
.append('title') // Tooltip
.text(function(d) {
return d.variety +
'nSepal Length: ' + d['sepal.length'] +
'nSepal Width: ' + d['sepal.width'] +
'nPetal Length: ' + d['petal.length'] +
'nPetal Width: ' + d['petal.width']
})

// X-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'xAxis')
.attr('transform', 'translate(0,' + h + ')')
.call(xAxis)
.append('text') // X-axis Label
.attr('id', 'xAxisLabel')
.attr('y', -25)
.attr('x', w)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

// labels distance from xaxis
svg.selectAll(".axis text")
.attr("dy", 15);

// Y-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'yAxis')
.call(yAxis)
.append('text') // y-axis Label
.attr('id', 'yAxisLabel')
.attr('transform', 'rotate(-90)')
.attr('x', 0)
.attr('y', 5)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

function yChange() {
var value = this.value // get the new y value
yScale // change the yScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
yAxis.scale(yScale) // change the yScale
d3.select('#yAxis') // redraw the yAxis
.transition().duration(500)
.call(yAxis)
d3.select('#yAxisLabel') // change the yAxisLabel
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cy', function(d) {
return yScale(d[value])
})
}

function xChange() {
var value = this.value // get the new x value
xScale // change the xScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
xAxis.scale(xScale) // change the xScale
d3.select('#xAxis') // redraw the xAxis
.transition().duration(500)
.call(xAxis)
d3.select('#xAxisLabel') // change the xAxisLabel
.transition().duration(500)
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cx', function(d) {
return xScale(d[value])
})
}

// create legend
var legendContainer = body.append('div')
.attr('class', 'legend-container')

var legend = legendContainer.selectAll(".legend")
.data(color.domain())
.enter().append("div")
.attr("class", "legend")

// draw legend colored rectangles
legend.append("span")
.attr("class", "legend-color")
.style("background-color", color);

// draw legend text
legend.append("span")
.text(function(d) {
return d;
})

})

body {
font-size: 16px;
display: flex;
flex-wrap: wrap;
}

.controls {
flex: 1 1 100%;
}

.legend-container {
align-items: center;
flex: 0 1 auto;
align-self: center;
margin: 0 auto;
}

circle:hover {
fill: orange;
}

.axis text {
font-size: 13px;
}

.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
stroke-width: 0.02px;
}

label {
position: absolute;
top: 10px;
right: 10px;
}

.legend {
margin-bottom: 0.5em;
}

.legend-color {
width: 20px;
height: 20px;
display: inline-block;
border-radius: 50%;
vertical-align: middle;
margin-right: 1em;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>

<body></body>





With this approach you end up with a structure like this:



body
.controls
.svg-container
svg
.legend-container


which can make responsive layouts especially easy with CSS.






share|improve this answer


























  • This is a nice approach! I didn't know that you could append a div like that. Thank you!

    – patL
    Nov 23 '18 at 23:30











  • In your code you are appending regular html <select> tags as controls. So It makes sense that you could be able to do something similar for the legend.

    – ksav
    Nov 24 '18 at 11:04













  • Thank you @ksav. I'm still learning D3 and html... It helped me a lot! ;) No I have to figure out a way to use .on and "click" to hide and show my data.

    – patL
    Nov 24 '18 at 22:45











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53421526%2fd3-js-legend-overlapping-chart-area%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














Why not just render your legend as HTML and use CSS to help with layout?






d3.csv('https://gist.githubusercontent.com/netj/8836201/raw/6f9306ad21398ea43cba4f7d537619d0e07d5ae3/iris.csv', function(data) {
// CSV section
var body = d3.select('body')
var selectData = [{
"text": "sepal.length"
},
{
"text": "sepal.width"
},
{
"text": "petal.length"
},
{
"text": "petal.width"
},
]

// setup fill color
var colors = ['#575757', '#5FB1B9', '#C94257'];

var symbol = d3.svg.symbol()
.type('circle')
.size("160")

var cValue = function(d) {
return d.variety;
},
color = d3.scale.ordinal()
.range(colors);

var controls = body.append('div').attr('class', 'controls')


// Select Y-axis Variable
var yControls = controls.append('div')
var span = yControls.append('span')
.text('Select Y-Axis variable: ')
var yInput = yControls.append('select')
.attr('id', 'ySelect')
.on('change', yChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})



// Select X-axis Variable
var xControls = controls.append('div')
var span = xControls.append('span')
.text('Select X-Axis variable: ')
var yInput = xControls.append('select')
.attr('id', 'xSelect')
.on('change', xChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})


// Variables
var body = d3.select('body')
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
}
var h = 500 - margin.top - margin.bottom
var w = 500 - margin.left - margin.right

var xScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([0, w])
var yScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([h, 0])

// SVG
var svgContainer = body.append('div').attr('class', 'svg-container')

var svg = svgContainer.append('svg')
.attr('height', h + margin.top + margin.bottom)
.attr('width', w + margin.left + margin.right)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')

// X-axis
var xAxis = d3.svg.axis()
.scale(xScale)
// .tickFormat(formatPercent)
.ticks(6)
.outerTickSize(0)
.tickSize(0)

.orient('bottom')

// Y-axis
var yAxis = d3.svg.axis()
.scale(yScale)
// .tickFormat(formatPercent)
.ticks(6)
.tickSize(-w)
.outerTickSize(0)
.orient('left')

// Circles
var circles = svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', function(d) {
return xScale(d['sepal.length'])
})
.attr('cy', function(d) {
return yScale(d['sepal.length'])
})
.attr('r', '10')
// .attr('stroke', 'black')
.attr('stroke-width', 0.2)
.attr("fill", function(d) {
return color(cValue(d));
})
.attr('fill-opacity', 0.8)
// .attr('fill', function(d, i) {
// return colorScale(i)
// })
.on('mouseover', function() {
d3.select(this)
.transition()
.duration(300)
.ease('elastic')
.attr('r', 15)
.attr('stroke-width', 1)
.attr('fill-opacity', 1)

})
.on('mouseout', function() {
d3.select(this)
.transition()
.duration(100)
.attr('r', 10)
.attr('stroke-width', 0.5)
})
.append('title') // Tooltip
.text(function(d) {
return d.variety +
'nSepal Length: ' + d['sepal.length'] +
'nSepal Width: ' + d['sepal.width'] +
'nPetal Length: ' + d['petal.length'] +
'nPetal Width: ' + d['petal.width']
})

// X-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'xAxis')
.attr('transform', 'translate(0,' + h + ')')
.call(xAxis)
.append('text') // X-axis Label
.attr('id', 'xAxisLabel')
.attr('y', -25)
.attr('x', w)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

// labels distance from xaxis
svg.selectAll(".axis text")
.attr("dy", 15);

// Y-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'yAxis')
.call(yAxis)
.append('text') // y-axis Label
.attr('id', 'yAxisLabel')
.attr('transform', 'rotate(-90)')
.attr('x', 0)
.attr('y', 5)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

function yChange() {
var value = this.value // get the new y value
yScale // change the yScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
yAxis.scale(yScale) // change the yScale
d3.select('#yAxis') // redraw the yAxis
.transition().duration(500)
.call(yAxis)
d3.select('#yAxisLabel') // change the yAxisLabel
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cy', function(d) {
return yScale(d[value])
})
}

function xChange() {
var value = this.value // get the new x value
xScale // change the xScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
xAxis.scale(xScale) // change the xScale
d3.select('#xAxis') // redraw the xAxis
.transition().duration(500)
.call(xAxis)
d3.select('#xAxisLabel') // change the xAxisLabel
.transition().duration(500)
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cx', function(d) {
return xScale(d[value])
})
}

// create legend
var legendContainer = body.append('div')
.attr('class', 'legend-container')

var legend = legendContainer.selectAll(".legend")
.data(color.domain())
.enter().append("div")
.attr("class", "legend")

// draw legend colored rectangles
legend.append("span")
.attr("class", "legend-color")
.style("background-color", color);

// draw legend text
legend.append("span")
.text(function(d) {
return d;
})

})

body {
font-size: 16px;
display: flex;
flex-wrap: wrap;
}

.controls {
flex: 1 1 100%;
}

.legend-container {
align-items: center;
flex: 0 1 auto;
align-self: center;
margin: 0 auto;
}

circle:hover {
fill: orange;
}

.axis text {
font-size: 13px;
}

.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
stroke-width: 0.02px;
}

label {
position: absolute;
top: 10px;
right: 10px;
}

.legend {
margin-bottom: 0.5em;
}

.legend-color {
width: 20px;
height: 20px;
display: inline-block;
border-radius: 50%;
vertical-align: middle;
margin-right: 1em;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>

<body></body>





With this approach you end up with a structure like this:



body
.controls
.svg-container
svg
.legend-container


which can make responsive layouts especially easy with CSS.






share|improve this answer


























  • This is a nice approach! I didn't know that you could append a div like that. Thank you!

    – patL
    Nov 23 '18 at 23:30











  • In your code you are appending regular html <select> tags as controls. So It makes sense that you could be able to do something similar for the legend.

    – ksav
    Nov 24 '18 at 11:04













  • Thank you @ksav. I'm still learning D3 and html... It helped me a lot! ;) No I have to figure out a way to use .on and "click" to hide and show my data.

    – patL
    Nov 24 '18 at 22:45
















1














Why not just render your legend as HTML and use CSS to help with layout?






d3.csv('https://gist.githubusercontent.com/netj/8836201/raw/6f9306ad21398ea43cba4f7d537619d0e07d5ae3/iris.csv', function(data) {
// CSV section
var body = d3.select('body')
var selectData = [{
"text": "sepal.length"
},
{
"text": "sepal.width"
},
{
"text": "petal.length"
},
{
"text": "petal.width"
},
]

// setup fill color
var colors = ['#575757', '#5FB1B9', '#C94257'];

var symbol = d3.svg.symbol()
.type('circle')
.size("160")

var cValue = function(d) {
return d.variety;
},
color = d3.scale.ordinal()
.range(colors);

var controls = body.append('div').attr('class', 'controls')


// Select Y-axis Variable
var yControls = controls.append('div')
var span = yControls.append('span')
.text('Select Y-Axis variable: ')
var yInput = yControls.append('select')
.attr('id', 'ySelect')
.on('change', yChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})



// Select X-axis Variable
var xControls = controls.append('div')
var span = xControls.append('span')
.text('Select X-Axis variable: ')
var yInput = xControls.append('select')
.attr('id', 'xSelect')
.on('change', xChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})


// Variables
var body = d3.select('body')
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
}
var h = 500 - margin.top - margin.bottom
var w = 500 - margin.left - margin.right

var xScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([0, w])
var yScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([h, 0])

// SVG
var svgContainer = body.append('div').attr('class', 'svg-container')

var svg = svgContainer.append('svg')
.attr('height', h + margin.top + margin.bottom)
.attr('width', w + margin.left + margin.right)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')

// X-axis
var xAxis = d3.svg.axis()
.scale(xScale)
// .tickFormat(formatPercent)
.ticks(6)
.outerTickSize(0)
.tickSize(0)

.orient('bottom')

// Y-axis
var yAxis = d3.svg.axis()
.scale(yScale)
// .tickFormat(formatPercent)
.ticks(6)
.tickSize(-w)
.outerTickSize(0)
.orient('left')

// Circles
var circles = svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', function(d) {
return xScale(d['sepal.length'])
})
.attr('cy', function(d) {
return yScale(d['sepal.length'])
})
.attr('r', '10')
// .attr('stroke', 'black')
.attr('stroke-width', 0.2)
.attr("fill", function(d) {
return color(cValue(d));
})
.attr('fill-opacity', 0.8)
// .attr('fill', function(d, i) {
// return colorScale(i)
// })
.on('mouseover', function() {
d3.select(this)
.transition()
.duration(300)
.ease('elastic')
.attr('r', 15)
.attr('stroke-width', 1)
.attr('fill-opacity', 1)

})
.on('mouseout', function() {
d3.select(this)
.transition()
.duration(100)
.attr('r', 10)
.attr('stroke-width', 0.5)
})
.append('title') // Tooltip
.text(function(d) {
return d.variety +
'nSepal Length: ' + d['sepal.length'] +
'nSepal Width: ' + d['sepal.width'] +
'nPetal Length: ' + d['petal.length'] +
'nPetal Width: ' + d['petal.width']
})

// X-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'xAxis')
.attr('transform', 'translate(0,' + h + ')')
.call(xAxis)
.append('text') // X-axis Label
.attr('id', 'xAxisLabel')
.attr('y', -25)
.attr('x', w)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

// labels distance from xaxis
svg.selectAll(".axis text")
.attr("dy", 15);

// Y-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'yAxis')
.call(yAxis)
.append('text') // y-axis Label
.attr('id', 'yAxisLabel')
.attr('transform', 'rotate(-90)')
.attr('x', 0)
.attr('y', 5)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

function yChange() {
var value = this.value // get the new y value
yScale // change the yScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
yAxis.scale(yScale) // change the yScale
d3.select('#yAxis') // redraw the yAxis
.transition().duration(500)
.call(yAxis)
d3.select('#yAxisLabel') // change the yAxisLabel
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cy', function(d) {
return yScale(d[value])
})
}

function xChange() {
var value = this.value // get the new x value
xScale // change the xScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
xAxis.scale(xScale) // change the xScale
d3.select('#xAxis') // redraw the xAxis
.transition().duration(500)
.call(xAxis)
d3.select('#xAxisLabel') // change the xAxisLabel
.transition().duration(500)
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cx', function(d) {
return xScale(d[value])
})
}

// create legend
var legendContainer = body.append('div')
.attr('class', 'legend-container')

var legend = legendContainer.selectAll(".legend")
.data(color.domain())
.enter().append("div")
.attr("class", "legend")

// draw legend colored rectangles
legend.append("span")
.attr("class", "legend-color")
.style("background-color", color);

// draw legend text
legend.append("span")
.text(function(d) {
return d;
})

})

body {
font-size: 16px;
display: flex;
flex-wrap: wrap;
}

.controls {
flex: 1 1 100%;
}

.legend-container {
align-items: center;
flex: 0 1 auto;
align-self: center;
margin: 0 auto;
}

circle:hover {
fill: orange;
}

.axis text {
font-size: 13px;
}

.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
stroke-width: 0.02px;
}

label {
position: absolute;
top: 10px;
right: 10px;
}

.legend {
margin-bottom: 0.5em;
}

.legend-color {
width: 20px;
height: 20px;
display: inline-block;
border-radius: 50%;
vertical-align: middle;
margin-right: 1em;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>

<body></body>





With this approach you end up with a structure like this:



body
.controls
.svg-container
svg
.legend-container


which can make responsive layouts especially easy with CSS.






share|improve this answer


























  • This is a nice approach! I didn't know that you could append a div like that. Thank you!

    – patL
    Nov 23 '18 at 23:30











  • In your code you are appending regular html <select> tags as controls. So It makes sense that you could be able to do something similar for the legend.

    – ksav
    Nov 24 '18 at 11:04













  • Thank you @ksav. I'm still learning D3 and html... It helped me a lot! ;) No I have to figure out a way to use .on and "click" to hide and show my data.

    – patL
    Nov 24 '18 at 22:45














1












1








1







Why not just render your legend as HTML and use CSS to help with layout?






d3.csv('https://gist.githubusercontent.com/netj/8836201/raw/6f9306ad21398ea43cba4f7d537619d0e07d5ae3/iris.csv', function(data) {
// CSV section
var body = d3.select('body')
var selectData = [{
"text": "sepal.length"
},
{
"text": "sepal.width"
},
{
"text": "petal.length"
},
{
"text": "petal.width"
},
]

// setup fill color
var colors = ['#575757', '#5FB1B9', '#C94257'];

var symbol = d3.svg.symbol()
.type('circle')
.size("160")

var cValue = function(d) {
return d.variety;
},
color = d3.scale.ordinal()
.range(colors);

var controls = body.append('div').attr('class', 'controls')


// Select Y-axis Variable
var yControls = controls.append('div')
var span = yControls.append('span')
.text('Select Y-Axis variable: ')
var yInput = yControls.append('select')
.attr('id', 'ySelect')
.on('change', yChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})



// Select X-axis Variable
var xControls = controls.append('div')
var span = xControls.append('span')
.text('Select X-Axis variable: ')
var yInput = xControls.append('select')
.attr('id', 'xSelect')
.on('change', xChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})


// Variables
var body = d3.select('body')
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
}
var h = 500 - margin.top - margin.bottom
var w = 500 - margin.left - margin.right

var xScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([0, w])
var yScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([h, 0])

// SVG
var svgContainer = body.append('div').attr('class', 'svg-container')

var svg = svgContainer.append('svg')
.attr('height', h + margin.top + margin.bottom)
.attr('width', w + margin.left + margin.right)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')

// X-axis
var xAxis = d3.svg.axis()
.scale(xScale)
// .tickFormat(formatPercent)
.ticks(6)
.outerTickSize(0)
.tickSize(0)

.orient('bottom')

// Y-axis
var yAxis = d3.svg.axis()
.scale(yScale)
// .tickFormat(formatPercent)
.ticks(6)
.tickSize(-w)
.outerTickSize(0)
.orient('left')

// Circles
var circles = svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', function(d) {
return xScale(d['sepal.length'])
})
.attr('cy', function(d) {
return yScale(d['sepal.length'])
})
.attr('r', '10')
// .attr('stroke', 'black')
.attr('stroke-width', 0.2)
.attr("fill", function(d) {
return color(cValue(d));
})
.attr('fill-opacity', 0.8)
// .attr('fill', function(d, i) {
// return colorScale(i)
// })
.on('mouseover', function() {
d3.select(this)
.transition()
.duration(300)
.ease('elastic')
.attr('r', 15)
.attr('stroke-width', 1)
.attr('fill-opacity', 1)

})
.on('mouseout', function() {
d3.select(this)
.transition()
.duration(100)
.attr('r', 10)
.attr('stroke-width', 0.5)
})
.append('title') // Tooltip
.text(function(d) {
return d.variety +
'nSepal Length: ' + d['sepal.length'] +
'nSepal Width: ' + d['sepal.width'] +
'nPetal Length: ' + d['petal.length'] +
'nPetal Width: ' + d['petal.width']
})

// X-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'xAxis')
.attr('transform', 'translate(0,' + h + ')')
.call(xAxis)
.append('text') // X-axis Label
.attr('id', 'xAxisLabel')
.attr('y', -25)
.attr('x', w)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

// labels distance from xaxis
svg.selectAll(".axis text")
.attr("dy", 15);

// Y-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'yAxis')
.call(yAxis)
.append('text') // y-axis Label
.attr('id', 'yAxisLabel')
.attr('transform', 'rotate(-90)')
.attr('x', 0)
.attr('y', 5)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

function yChange() {
var value = this.value // get the new y value
yScale // change the yScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
yAxis.scale(yScale) // change the yScale
d3.select('#yAxis') // redraw the yAxis
.transition().duration(500)
.call(yAxis)
d3.select('#yAxisLabel') // change the yAxisLabel
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cy', function(d) {
return yScale(d[value])
})
}

function xChange() {
var value = this.value // get the new x value
xScale // change the xScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
xAxis.scale(xScale) // change the xScale
d3.select('#xAxis') // redraw the xAxis
.transition().duration(500)
.call(xAxis)
d3.select('#xAxisLabel') // change the xAxisLabel
.transition().duration(500)
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cx', function(d) {
return xScale(d[value])
})
}

// create legend
var legendContainer = body.append('div')
.attr('class', 'legend-container')

var legend = legendContainer.selectAll(".legend")
.data(color.domain())
.enter().append("div")
.attr("class", "legend")

// draw legend colored rectangles
legend.append("span")
.attr("class", "legend-color")
.style("background-color", color);

// draw legend text
legend.append("span")
.text(function(d) {
return d;
})

})

body {
font-size: 16px;
display: flex;
flex-wrap: wrap;
}

.controls {
flex: 1 1 100%;
}

.legend-container {
align-items: center;
flex: 0 1 auto;
align-self: center;
margin: 0 auto;
}

circle:hover {
fill: orange;
}

.axis text {
font-size: 13px;
}

.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
stroke-width: 0.02px;
}

label {
position: absolute;
top: 10px;
right: 10px;
}

.legend {
margin-bottom: 0.5em;
}

.legend-color {
width: 20px;
height: 20px;
display: inline-block;
border-radius: 50%;
vertical-align: middle;
margin-right: 1em;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>

<body></body>





With this approach you end up with a structure like this:



body
.controls
.svg-container
svg
.legend-container


which can make responsive layouts especially easy with CSS.






share|improve this answer















Why not just render your legend as HTML and use CSS to help with layout?






d3.csv('https://gist.githubusercontent.com/netj/8836201/raw/6f9306ad21398ea43cba4f7d537619d0e07d5ae3/iris.csv', function(data) {
// CSV section
var body = d3.select('body')
var selectData = [{
"text": "sepal.length"
},
{
"text": "sepal.width"
},
{
"text": "petal.length"
},
{
"text": "petal.width"
},
]

// setup fill color
var colors = ['#575757', '#5FB1B9', '#C94257'];

var symbol = d3.svg.symbol()
.type('circle')
.size("160")

var cValue = function(d) {
return d.variety;
},
color = d3.scale.ordinal()
.range(colors);

var controls = body.append('div').attr('class', 'controls')


// Select Y-axis Variable
var yControls = controls.append('div')
var span = yControls.append('span')
.text('Select Y-Axis variable: ')
var yInput = yControls.append('select')
.attr('id', 'ySelect')
.on('change', yChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})



// Select X-axis Variable
var xControls = controls.append('div')
var span = xControls.append('span')
.text('Select X-Axis variable: ')
var yInput = xControls.append('select')
.attr('id', 'xSelect')
.on('change', xChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})


// Variables
var body = d3.select('body')
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
}
var h = 500 - margin.top - margin.bottom
var w = 500 - margin.left - margin.right

var xScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([0, w])
var yScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([h, 0])

// SVG
var svgContainer = body.append('div').attr('class', 'svg-container')

var svg = svgContainer.append('svg')
.attr('height', h + margin.top + margin.bottom)
.attr('width', w + margin.left + margin.right)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')

// X-axis
var xAxis = d3.svg.axis()
.scale(xScale)
// .tickFormat(formatPercent)
.ticks(6)
.outerTickSize(0)
.tickSize(0)

.orient('bottom')

// Y-axis
var yAxis = d3.svg.axis()
.scale(yScale)
// .tickFormat(formatPercent)
.ticks(6)
.tickSize(-w)
.outerTickSize(0)
.orient('left')

// Circles
var circles = svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', function(d) {
return xScale(d['sepal.length'])
})
.attr('cy', function(d) {
return yScale(d['sepal.length'])
})
.attr('r', '10')
// .attr('stroke', 'black')
.attr('stroke-width', 0.2)
.attr("fill", function(d) {
return color(cValue(d));
})
.attr('fill-opacity', 0.8)
// .attr('fill', function(d, i) {
// return colorScale(i)
// })
.on('mouseover', function() {
d3.select(this)
.transition()
.duration(300)
.ease('elastic')
.attr('r', 15)
.attr('stroke-width', 1)
.attr('fill-opacity', 1)

})
.on('mouseout', function() {
d3.select(this)
.transition()
.duration(100)
.attr('r', 10)
.attr('stroke-width', 0.5)
})
.append('title') // Tooltip
.text(function(d) {
return d.variety +
'nSepal Length: ' + d['sepal.length'] +
'nSepal Width: ' + d['sepal.width'] +
'nPetal Length: ' + d['petal.length'] +
'nPetal Width: ' + d['petal.width']
})

// X-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'xAxis')
.attr('transform', 'translate(0,' + h + ')')
.call(xAxis)
.append('text') // X-axis Label
.attr('id', 'xAxisLabel')
.attr('y', -25)
.attr('x', w)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

// labels distance from xaxis
svg.selectAll(".axis text")
.attr("dy", 15);

// Y-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'yAxis')
.call(yAxis)
.append('text') // y-axis Label
.attr('id', 'yAxisLabel')
.attr('transform', 'rotate(-90)')
.attr('x', 0)
.attr('y', 5)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

function yChange() {
var value = this.value // get the new y value
yScale // change the yScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
yAxis.scale(yScale) // change the yScale
d3.select('#yAxis') // redraw the yAxis
.transition().duration(500)
.call(yAxis)
d3.select('#yAxisLabel') // change the yAxisLabel
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cy', function(d) {
return yScale(d[value])
})
}

function xChange() {
var value = this.value // get the new x value
xScale // change the xScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
xAxis.scale(xScale) // change the xScale
d3.select('#xAxis') // redraw the xAxis
.transition().duration(500)
.call(xAxis)
d3.select('#xAxisLabel') // change the xAxisLabel
.transition().duration(500)
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cx', function(d) {
return xScale(d[value])
})
}

// create legend
var legendContainer = body.append('div')
.attr('class', 'legend-container')

var legend = legendContainer.selectAll(".legend")
.data(color.domain())
.enter().append("div")
.attr("class", "legend")

// draw legend colored rectangles
legend.append("span")
.attr("class", "legend-color")
.style("background-color", color);

// draw legend text
legend.append("span")
.text(function(d) {
return d;
})

})

body {
font-size: 16px;
display: flex;
flex-wrap: wrap;
}

.controls {
flex: 1 1 100%;
}

.legend-container {
align-items: center;
flex: 0 1 auto;
align-self: center;
margin: 0 auto;
}

circle:hover {
fill: orange;
}

.axis text {
font-size: 13px;
}

.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
stroke-width: 0.02px;
}

label {
position: absolute;
top: 10px;
right: 10px;
}

.legend {
margin-bottom: 0.5em;
}

.legend-color {
width: 20px;
height: 20px;
display: inline-block;
border-radius: 50%;
vertical-align: middle;
margin-right: 1em;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>

<body></body>





With this approach you end up with a structure like this:



body
.controls
.svg-container
svg
.legend-container


which can make responsive layouts especially easy with CSS.






d3.csv('https://gist.githubusercontent.com/netj/8836201/raw/6f9306ad21398ea43cba4f7d537619d0e07d5ae3/iris.csv', function(data) {
// CSV section
var body = d3.select('body')
var selectData = [{
"text": "sepal.length"
},
{
"text": "sepal.width"
},
{
"text": "petal.length"
},
{
"text": "petal.width"
},
]

// setup fill color
var colors = ['#575757', '#5FB1B9', '#C94257'];

var symbol = d3.svg.symbol()
.type('circle')
.size("160")

var cValue = function(d) {
return d.variety;
},
color = d3.scale.ordinal()
.range(colors);

var controls = body.append('div').attr('class', 'controls')


// Select Y-axis Variable
var yControls = controls.append('div')
var span = yControls.append('span')
.text('Select Y-Axis variable: ')
var yInput = yControls.append('select')
.attr('id', 'ySelect')
.on('change', yChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})



// Select X-axis Variable
var xControls = controls.append('div')
var span = xControls.append('span')
.text('Select X-Axis variable: ')
var yInput = xControls.append('select')
.attr('id', 'xSelect')
.on('change', xChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})


// Variables
var body = d3.select('body')
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
}
var h = 500 - margin.top - margin.bottom
var w = 500 - margin.left - margin.right

var xScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([0, w])
var yScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([h, 0])

// SVG
var svgContainer = body.append('div').attr('class', 'svg-container')

var svg = svgContainer.append('svg')
.attr('height', h + margin.top + margin.bottom)
.attr('width', w + margin.left + margin.right)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')

// X-axis
var xAxis = d3.svg.axis()
.scale(xScale)
// .tickFormat(formatPercent)
.ticks(6)
.outerTickSize(0)
.tickSize(0)

.orient('bottom')

// Y-axis
var yAxis = d3.svg.axis()
.scale(yScale)
// .tickFormat(formatPercent)
.ticks(6)
.tickSize(-w)
.outerTickSize(0)
.orient('left')

// Circles
var circles = svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', function(d) {
return xScale(d['sepal.length'])
})
.attr('cy', function(d) {
return yScale(d['sepal.length'])
})
.attr('r', '10')
// .attr('stroke', 'black')
.attr('stroke-width', 0.2)
.attr("fill", function(d) {
return color(cValue(d));
})
.attr('fill-opacity', 0.8)
// .attr('fill', function(d, i) {
// return colorScale(i)
// })
.on('mouseover', function() {
d3.select(this)
.transition()
.duration(300)
.ease('elastic')
.attr('r', 15)
.attr('stroke-width', 1)
.attr('fill-opacity', 1)

})
.on('mouseout', function() {
d3.select(this)
.transition()
.duration(100)
.attr('r', 10)
.attr('stroke-width', 0.5)
})
.append('title') // Tooltip
.text(function(d) {
return d.variety +
'nSepal Length: ' + d['sepal.length'] +
'nSepal Width: ' + d['sepal.width'] +
'nPetal Length: ' + d['petal.length'] +
'nPetal Width: ' + d['petal.width']
})

// X-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'xAxis')
.attr('transform', 'translate(0,' + h + ')')
.call(xAxis)
.append('text') // X-axis Label
.attr('id', 'xAxisLabel')
.attr('y', -25)
.attr('x', w)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

// labels distance from xaxis
svg.selectAll(".axis text")
.attr("dy", 15);

// Y-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'yAxis')
.call(yAxis)
.append('text') // y-axis Label
.attr('id', 'yAxisLabel')
.attr('transform', 'rotate(-90)')
.attr('x', 0)
.attr('y', 5)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

function yChange() {
var value = this.value // get the new y value
yScale // change the yScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
yAxis.scale(yScale) // change the yScale
d3.select('#yAxis') // redraw the yAxis
.transition().duration(500)
.call(yAxis)
d3.select('#yAxisLabel') // change the yAxisLabel
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cy', function(d) {
return yScale(d[value])
})
}

function xChange() {
var value = this.value // get the new x value
xScale // change the xScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
xAxis.scale(xScale) // change the xScale
d3.select('#xAxis') // redraw the xAxis
.transition().duration(500)
.call(xAxis)
d3.select('#xAxisLabel') // change the xAxisLabel
.transition().duration(500)
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cx', function(d) {
return xScale(d[value])
})
}

// create legend
var legendContainer = body.append('div')
.attr('class', 'legend-container')

var legend = legendContainer.selectAll(".legend")
.data(color.domain())
.enter().append("div")
.attr("class", "legend")

// draw legend colored rectangles
legend.append("span")
.attr("class", "legend-color")
.style("background-color", color);

// draw legend text
legend.append("span")
.text(function(d) {
return d;
})

})

body {
font-size: 16px;
display: flex;
flex-wrap: wrap;
}

.controls {
flex: 1 1 100%;
}

.legend-container {
align-items: center;
flex: 0 1 auto;
align-self: center;
margin: 0 auto;
}

circle:hover {
fill: orange;
}

.axis text {
font-size: 13px;
}

.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
stroke-width: 0.02px;
}

label {
position: absolute;
top: 10px;
right: 10px;
}

.legend {
margin-bottom: 0.5em;
}

.legend-color {
width: 20px;
height: 20px;
display: inline-block;
border-radius: 50%;
vertical-align: middle;
margin-right: 1em;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>

<body></body>





d3.csv('https://gist.githubusercontent.com/netj/8836201/raw/6f9306ad21398ea43cba4f7d537619d0e07d5ae3/iris.csv', function(data) {
// CSV section
var body = d3.select('body')
var selectData = [{
"text": "sepal.length"
},
{
"text": "sepal.width"
},
{
"text": "petal.length"
},
{
"text": "petal.width"
},
]

// setup fill color
var colors = ['#575757', '#5FB1B9', '#C94257'];

var symbol = d3.svg.symbol()
.type('circle')
.size("160")

var cValue = function(d) {
return d.variety;
},
color = d3.scale.ordinal()
.range(colors);

var controls = body.append('div').attr('class', 'controls')


// Select Y-axis Variable
var yControls = controls.append('div')
var span = yControls.append('span')
.text('Select Y-Axis variable: ')
var yInput = yControls.append('select')
.attr('id', 'ySelect')
.on('change', yChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})



// Select X-axis Variable
var xControls = controls.append('div')
var span = xControls.append('span')
.text('Select X-Axis variable: ')
var yInput = xControls.append('select')
.attr('id', 'xSelect')
.on('change', xChange)
.selectAll('option')
.data(selectData)
.enter()
.append('option')
.attr('value', function(d) {
return d.text
})
.text(function(d) {
return d.text;
})


// Variables
var body = d3.select('body')
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
}
var h = 500 - margin.top - margin.bottom
var w = 500 - margin.left - margin.right

var xScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([0, w])
var yScale = d3.scale.linear()
.domain([
d3.min([0, d3.min(data, function(d) {
return d['sepal.length']
})]),
d3.max([0, d3.max(data, function(d) {
return d['sepal.length']
})])
])
.range([h, 0])

// SVG
var svgContainer = body.append('div').attr('class', 'svg-container')

var svg = svgContainer.append('svg')
.attr('height', h + margin.top + margin.bottom)
.attr('width', w + margin.left + margin.right)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')

// X-axis
var xAxis = d3.svg.axis()
.scale(xScale)
// .tickFormat(formatPercent)
.ticks(6)
.outerTickSize(0)
.tickSize(0)

.orient('bottom')

// Y-axis
var yAxis = d3.svg.axis()
.scale(yScale)
// .tickFormat(formatPercent)
.ticks(6)
.tickSize(-w)
.outerTickSize(0)
.orient('left')

// Circles
var circles = svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', function(d) {
return xScale(d['sepal.length'])
})
.attr('cy', function(d) {
return yScale(d['sepal.length'])
})
.attr('r', '10')
// .attr('stroke', 'black')
.attr('stroke-width', 0.2)
.attr("fill", function(d) {
return color(cValue(d));
})
.attr('fill-opacity', 0.8)
// .attr('fill', function(d, i) {
// return colorScale(i)
// })
.on('mouseover', function() {
d3.select(this)
.transition()
.duration(300)
.ease('elastic')
.attr('r', 15)
.attr('stroke-width', 1)
.attr('fill-opacity', 1)

})
.on('mouseout', function() {
d3.select(this)
.transition()
.duration(100)
.attr('r', 10)
.attr('stroke-width', 0.5)
})
.append('title') // Tooltip
.text(function(d) {
return d.variety +
'nSepal Length: ' + d['sepal.length'] +
'nSepal Width: ' + d['sepal.width'] +
'nPetal Length: ' + d['petal.length'] +
'nPetal Width: ' + d['petal.width']
})

// X-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'xAxis')
.attr('transform', 'translate(0,' + h + ')')
.call(xAxis)
.append('text') // X-axis Label
.attr('id', 'xAxisLabel')
.attr('y', -25)
.attr('x', w)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

// labels distance from xaxis
svg.selectAll(".axis text")
.attr("dy", 15);

// Y-axis
svg.append('g')
.attr('class', 'axis')
.attr('id', 'yAxis')
.call(yAxis)
.append('text') // y-axis Label
.attr('id', 'yAxisLabel')
.attr('transform', 'rotate(-90)')
.attr('x', 0)
.attr('y', 5)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Sepal Length')

function yChange() {
var value = this.value // get the new y value
yScale // change the yScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
yAxis.scale(yScale) // change the yScale
d3.select('#yAxis') // redraw the yAxis
.transition().duration(500)
.call(yAxis)
d3.select('#yAxisLabel') // change the yAxisLabel
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cy', function(d) {
return yScale(d[value])
})
}

function xChange() {
var value = this.value // get the new x value
xScale // change the xScale
.domain([
d3.min([0, d3.min(data, function(d) {
return d[value]
})]),
d3.max([0, d3.max(data, function(d) {
return d[value]
})])
])
xAxis.scale(xScale) // change the xScale
d3.select('#xAxis') // redraw the xAxis
.transition().duration(500)
.call(xAxis)
d3.select('#xAxisLabel') // change the xAxisLabel
.transition().duration(500)
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(500)
.delay(function(d, i) {
return i * 10
})
.attr('cx', function(d) {
return xScale(d[value])
})
}

// create legend
var legendContainer = body.append('div')
.attr('class', 'legend-container')

var legend = legendContainer.selectAll(".legend")
.data(color.domain())
.enter().append("div")
.attr("class", "legend")

// draw legend colored rectangles
legend.append("span")
.attr("class", "legend-color")
.style("background-color", color);

// draw legend text
legend.append("span")
.text(function(d) {
return d;
})

})

body {
font-size: 16px;
display: flex;
flex-wrap: wrap;
}

.controls {
flex: 1 1 100%;
}

.legend-container {
align-items: center;
flex: 0 1 auto;
align-self: center;
margin: 0 auto;
}

circle:hover {
fill: orange;
}

.axis text {
font-size: 13px;
}

.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
stroke-width: 0.02px;
}

label {
position: absolute;
top: 10px;
right: 10px;
}

.legend {
margin-bottom: 0.5em;
}

.legend-color {
width: 20px;
height: 20px;
display: inline-block;
border-radius: 50%;
vertical-align: middle;
margin-right: 1em;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>

<body></body>






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 24 '18 at 14:27

























answered Nov 22 '18 at 10:38









ksavksav

4,63221329




4,63221329













  • This is a nice approach! I didn't know that you could append a div like that. Thank you!

    – patL
    Nov 23 '18 at 23:30











  • In your code you are appending regular html <select> tags as controls. So It makes sense that you could be able to do something similar for the legend.

    – ksav
    Nov 24 '18 at 11:04













  • Thank you @ksav. I'm still learning D3 and html... It helped me a lot! ;) No I have to figure out a way to use .on and "click" to hide and show my data.

    – patL
    Nov 24 '18 at 22:45



















  • This is a nice approach! I didn't know that you could append a div like that. Thank you!

    – patL
    Nov 23 '18 at 23:30











  • In your code you are appending regular html <select> tags as controls. So It makes sense that you could be able to do something similar for the legend.

    – ksav
    Nov 24 '18 at 11:04













  • Thank you @ksav. I'm still learning D3 and html... It helped me a lot! ;) No I have to figure out a way to use .on and "click" to hide and show my data.

    – patL
    Nov 24 '18 at 22:45

















This is a nice approach! I didn't know that you could append a div like that. Thank you!

– patL
Nov 23 '18 at 23:30





This is a nice approach! I didn't know that you could append a div like that. Thank you!

– patL
Nov 23 '18 at 23:30













In your code you are appending regular html <select> tags as controls. So It makes sense that you could be able to do something similar for the legend.

– ksav
Nov 24 '18 at 11:04







In your code you are appending regular html <select> tags as controls. So It makes sense that you could be able to do something similar for the legend.

– ksav
Nov 24 '18 at 11:04















Thank you @ksav. I'm still learning D3 and html... It helped me a lot! ;) No I have to figure out a way to use .on and "click" to hide and show my data.

– patL
Nov 24 '18 at 22:45





Thank you @ksav. I'm still learning D3 and html... It helped me a lot! ;) No I have to figure out a way to use .on and "click" to hide and show my data.

– patL
Nov 24 '18 at 22:45


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53421526%2fd3-js-legend-overlapping-chart-area%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Wiesbaden

Marschland

Dieringhausen