Reputation: 693
I'm trying to create arbitrary groups of columns and rows using these attributes in the objects:
var svg = d3.select("#right-section").append("svg").attr("width",600).attr("height",600);
var flatInputMatrix = [1,1,1,0,0,3,3,3,0,0,4,4,4,0,0,5,5,5,0,0,0,2,0,4,4,0,0,0,5,5,0,1,0,2,2];
var m = 5;
var r = 3;
var counter = -1;
var data = flatInputMatrix.map(function(d, i) {
i % m === 0 ? counter++ : null;
return {
column: i % m,
row: counter,
value: d
};
});
var columnsGroups = svg.append("g")
var columns = columnsGroups.selectAll("columns").data(data.column= this.column).enter()
var numbers = svg.selectAll("numbers").data(data).enter().append("text")
.attr("x",function(d,i) { return (i % m)*50 + 10 + r; })
.attr("y",function(d,i) { return Math.floor(i / m) *50+50; })
.style("opacity", 0.5)
.text(function(d) { return d.value; })
.on("mouseover", function(d.columns){d3.select(this).style("opacity", 1) })
The idea is to have a column (later a group of columns) have the opacity = 1 when it is hovered over by the cursor.
Upvotes: 1
Views: 766
Reputation: 102198
Solution #1
Since you want to group by columns, I believe the best approach is nesting your data first (by columns, of course):
var nested = d3.nest()
.key(function(d) {
return d.column
})
.entries(data);
Then, we append different groups, one for each column:
var columns = svg.selectAll("foo")
.data(nested)
.enter()
.append("g")
.attr("transform", function(d) {
return "translate(" + (50 + 50 * d.key) + ",0)";
})
.style("opacity", 0.5);
Finally, we set the mouseover
:
columns.on("mouseover", function() {
d3.select(this).style("opacity", 1);
}).on("mouseout", function() {
d3.select(this).style("opacity", 0.5)
})
Here is the demo:
var svg = d3.select("body").append("svg").attr("width", 600).attr("height", 600);
var flatInputMatrix = [1, 1, 1, 0, 0, 3, 3, 3, 0, 0, 4, 4, 4, 0, 0, 5, 5, 5, 0, 0, 0, 2, 0, 4, 4, 0, 0, 0, 5, 5, 0, 1, 0, 2, 2];
var m = 5;
var r = 3;
var counter = -1;
var data = flatInputMatrix.map(function(d, i) {
i % m === 0 ? counter++ : null;
return {
column: i % m,
row: counter,
value: d
};
});
var nested = d3.nest()
.key(function(d) {
return d.column
})
.entries(data);
var columns = svg.selectAll("foo")
.data(nested)
.enter()
.append("g")
.attr("transform", function(d) {
return "translate(" + (50 + 50 * d.key) + ",0)";
})
.style("opacity", 0.5);
var numbers = columns.selectAll("foo")
.data(function(d) {
return d.values
})
.enter()
.append("text")
.attr("y", function(d) {
return d.row * 50 + 50;
})
.text(function(d) {
return d.value;
});
columns.on("mouseover", function() {
d3.select(this).style("opacity", 1);
}).on("mouseout", function() {
d3.select(this).style("opacity", 0.5)
})
<script src="https://d3js.org/d3.v4.min.js"></script>
Solution#2
However, if you don't want to substantially refactor your code, you can simply use the datum in the mouseover
function:
numbers.on("mouseover", function(d) {
var column = d.column;
numbers.filter(function(d) {
return d.column === column
})
.style("opacity", 1)
}).on("mouseout", function() {
numbers.style("opacity", 0.5)
})
That way, you can keep your code just like it is right now. Here is the demo:
var svg = d3.select("body").append("svg").attr("width", 600).attr("height", 600);
var flatInputMatrix = [1, 1, 1, 0, 0, 3, 3, 3, 0, 0, 4, 4, 4, 0, 0, 5, 5, 5, 0, 0, 0, 2, 0, 4, 4, 0, 0, 0, 5, 5, 0, 1, 0, 2, 2];
var m = 5;
var r = 3;
var counter = -1;
var data = flatInputMatrix.map(function(d, i) {
i % m === 0 ? counter++ : null;
return {
column: i % m,
row: counter,
value: d
};
});
var numbers = svg.selectAll("numbers")
.data(data)
.enter()
.append("text")
.attr("x", function(d, i) {
return (i % m) * 50 + 10 + r;
})
.attr("y", function(d, i) {
return Math.floor(i / m) * 50 + 50;
})
.style("opacity", 0.5)
.text(function(d) {
return d.value;
});
numbers.on("mouseover", function(d) {
var column = d.column;
numbers.filter(function(d) {
return d.column === column
})
.style("opacity", 1)
}).on("mouseout", function() {
numbers.style("opacity", 0.5)
})
<script src="https://d3js.org/d3.v4.min.js"></script>
Upvotes: 1