I am trying to create an animation where the elements of a grid appear in left-to-right, top-to-bottom order. So the order would be: A_(1,1)
, A_(1,2)
,...A_(1,d)
...A_(n,d)
.
My current code displays all elements in one column of the grid, followed by a delay, then all the elements in the second column, delay, and so on. I am sure this is because the index element in line 56, which controls the time delay for each element, resets with each row. I'd like to know if there is a way to get around this, such as having a variable that keeps track of the column number of d.
var data = [[0,1],[2,3]];
function myMatrix2(data) {
var margin = {top: 50, right: 100, bottom: 50, left: 100},
width = 250,
height = 250;
const svg = d3
.select('.grid2')
.append('svg')
.attr("width", width margin.left margin.right)
.attr("height", height margin.top margin.bottom)
.append("g")
.attr("transform", "translate(" margin.left "," margin.top ")");
numrows = data.length;
numcols = data[0].length;
rw=width/numrows;
hw=height/numcols;
var x = d3.scaleOrdinal()
.domain(d3.range(numcols))
.range(d3.range(0,width,width/numcols));
var y = d3.scaleOrdinal()
.domain(d3.range(numrows))
.range(d3.range(0,height,height/numrows));
var row = svg.selectAll(".row")
.data(data)
.enter().append("g")
.attr("class", "row")
.attr("transform", function(d, i) {return "translate(0," y(i) ")"; });
var cell = row.selectAll(".cell")
.data(function(d) { return d; })
.enter().append("g")
.attr("class", "cell")
.attr("transform", function(d, i) { return "translate(" x(i) ", 0)"; });
cell.append('rect')
.attr("width", rw)
.attr("height", hw)
.style("stroke", "black")
.style("stroke-width", "2px")
.style("fill", 'white')
cell.append("text") //Add matrix elements
.attr("dy", ".32em")
.attr("x", rw/2 )
.attr("y", hw/2 )
.attr("text-anchor", "middle")
.style("font-size","14px")
.transition() //Delay starts here
.delay(function(d,i) {console.log("D: " d " I: " i); return i*3000;})
.text(function(d) { return d; })
return;
};
CodePudding user response:
There are several ways to do this. One of my favourites idiomatic D3 ways is to set the index of the parent rows using a local variable...
local.set(this, i);
...and then retrieving that local for setting the delay:
.delay(function(d, i) {
const p = local.get(this);
return i * 1000 p * (1000 / numrows);
})
Here's your code with a 3x3 matrix:
var data = [
[0, 1, 4],
[2, 3, 6],
[7, 8, 9]
];
const local = d3.local();
myMatrix2(data);
function myMatrix2(data) {
var margin = {
top: 4,
right: 10,
bottom: 4,
left: 10
},
width = 150,
height = 150;
const svg = d3
.select('body')
.append('svg')
.attr("width", width margin.left margin.right)
.attr("height", height margin.top margin.bottom)
.append("g")
.attr("transform", "translate(" margin.left "," margin.top ")");
numrows = data.length;
numcols = data[0].length;
rw = width / numrows;
hw = height / numcols;
var x = d3.scaleOrdinal()
.domain(d3.range(numcols))
.range(d3.range(0, width, width / numcols));
var y = d3.scaleOrdinal()
.domain(d3.range(numrows))
.range(d3.range(0, height, height / numrows));
var row = svg.selectAll(".row")
.data(data)
.enter().append("g")
.attr("class", "row")
.attr("transform", function(d, i) {
local.set(this, i);
return "translate(0," y(i) ")";
});
var cell = row.selectAll(".cell")
.data(function(d) {
return d;
})
.enter().append("g")
.attr("class", "cell")
.attr("transform", function(d, i) {
return "translate(" x(i) ", 0)";
});
cell.append('rect')
.attr("width", rw)
.attr("height", hw)
.style("stroke", "black")
.style("stroke-width", "2px")
.style("fill", 'white')
cell.append("text") //Add matrix elements
.attr("dy", ".32em")
.attr("x", rw / 2)
.attr("y", hw / 2)
.attr("text-anchor", "middle")
.style("font-size", "14px")
.transition() //Delay starts here
.delay(function(d, i) {
const p = local.get(this);
return i * 1000 p * (1000 / numrows);
})
.text(function(d) {
return d;
})
return;
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>