Javascript 为什么有些细胞不能完全移动
我已经设置了这个JSFIDLE: } 在moveCell函数中,我选择一个随机单元,请求其当前的x和y坐标,然后加上或减去其宽度或高度,将其移动到相邻单元Javascript 为什么有些细胞不能完全移动,javascript,d3.js,Javascript,D3.js,我已经设置了这个JSFIDLE: } 在moveCell函数中,我选择一个随机单元,请求其当前的x和y坐标,然后加上或减去其宽度或高度,将其移动到相邻单元 我想知道的是:如果你观察细胞移动,一些细胞只会部分移动到下一个细胞。有一位女士能告诉我,为什么会这样吗?在这种情况下,首先要做的是放置。每个(“中断”,function(){console.log(“中断”)})在您的转换上。然后您将看到问题。 如果您将转换命名为selection.transition(“name”),则应该修复它,但这并不
我想知道的是:如果你观察细胞移动,一些细胞只会部分移动到下一个细胞。有一位女士能告诉我,为什么会这样吗?在这种情况下,首先要做的是放置
。每个(“中断”,function(){console.log(“中断”)})代码>在您的转换上。然后您将看到问题。
如果您将转换命名为selection.transition(“name”)
,则应该修复它,但这并不能修复它。
这意味着您必须按照@jcunod的建议进行操作,并排除正在移动的对象。一种惯用的方法是这样做
if (direction === 'x') {
selectedCell.transition("x").duration(1500)
.attr('x', newX)
.each("start", function () { lock.call(this, "lockedX") })
.each("end", function () { unlock.call(this, "lockedX") });
} else {
selectedCell.transition("y").duration(1500)
.attr('y', newY)
.each("start", function () { lock.call(this, "lockedX") })
.each("end", function () { unlock.call(this, "lockedX") });
}
function lock(lockClass) {
var c = { cell: false }; c[lockClass] = true;
d3.select(this).classed(c)
};
function unlock(lockClass) {
var c = { cell: this.classList.length == 1 }; c[lockClass] = false;
d3.select(this).classed(c);
};
是用来证明这个概念的小提琴
纯粹且惯用的d3版本
为了完整起见,这里是d3的方法。
我试着使它尽可能地道。要点是
纯数据驱动
数据被更新,viz操作完全由d3声明完成
使用d3检测svg元素属性的更改并对其采取行动
这是通过在selection.data()
方法中使用复合键
函数来实现的,并利用退出选择捕获更改的节点(其中x
、y
或fill
属性与更新数据不匹配的方块)
将更改的元素拼接到数据数组中,以便d3可以检测到更改
由于对数据数组元素的引用绑定到DOM元素,因此对数据的任何更改也将反映在selection.datum()
中。d3使用键
功能将数据值与基准
进行比较,以便将节点分类为更新、进入或退出。如果按下键
,这是数据/基准值的函数,则不会检测到数据的更改。通过splice
-ing对数据数组的更改,由selection.datum()
引用的值将不同于数据数组,因此数据更改将标记退出节点。
通过简单地操作属性并在退出选择上放置转换,而不是将其删除,它实际上变成了一个“已更改”的选择。
这仅在数据值为对象时有效
并发转换
命名转换用于确保x和y转换不会相互中断,但也有必要使用标记类属性锁定转换元素。这是使用转换开始和结束事件完成的
动画帧
d3.计时器
用于平滑动画和封送资源。d3Timer在更新变换之前、在每个动画帧之前回调以更新数据
使用d3.scale.ordinal()
管理定位
这很好,因为你知道它每次都有效,你甚至不必对此感到厌烦
$(函数(){
var容器,
svg,
网格高度=800,
网格宽度=1600,
细胞大小,细胞间距,
cellsColumns=100,
cellsRows=50,
正方形,
container=d3.select('.svg container'),
svg=container.append('svg')
.attr('width',gridWidth)
.attr('height',gridHeight)
.style({“背景色”:“黑色”,不透明度:1}),
createRandomRGB=函数(){
var red=Math.floor((Math.random()*256)).toString(),
绿色=Math.floor((Math.random()*256)).toString(),
蓝色=Math.floor((Math.random()*256)).toString(),
rgb='rgb('+红色+'、'+绿色+'、'+蓝色+)';
返回rgb;
},
createGrid=函数(宽度、高度){
var scaleHorizontal=d3.scale.ordinal()
.域(d3.范围(单元格列))
.范围带([0,宽度],1/15),
rangeHorizontal=scaleHorizontal.range(),
scaleVertical=d3.scale.ordinal()
.域(d3.范围(cellsRows))
.范围带([0,高度]),
rangeVertical=scaleVertical.range(),
平方=[];
rangeHorizontal.forEach(函数(dh,i){
rangeVertical.forEach(函数(dv,j){
var-indx;
正方形[indx=i+j*cellsColumns]={x:dh,y:dv,c:createRandomRGB(),indx:indx}
})
});
cellSize=scaleHorizontal.rangeBand();
细胞间距={
x:rangeHorizontal[1]-rangeHorizontal[0],
y:rangeVertical[1]-rangeVertical[0]
}
svg.selectAll(“rect”).data(正方形,函数(d,i){return d.indx})
.enter().append('rect')
.attr('类','单元')
.attr('width',cellSize)
.attr('height',cellSize)
.attr('x',函数(d){return d.x})
.attr('y',函数(d){返回d.y})
.style('fill',函数(d){return d.c});
返回方块;
},
choseRandom=功能(选项){
选项=选项| |[对,错];
var max=options.length;
返回选项[Math.floor(Math.random()*(max))];
},
pickRandomCell=函数(单元格){
var l=单元格。大小(),
r=数学地板(数学随机()*l);
返回l?d3.选择(单元格[0][r]).datum().indx:-1;
};
功能锁(锁类){
var c={cell:false};c[lockClass]=true;
d3.选择(本)。分类(c)
};
功能解锁(锁定类){
var c={cell:this.classList.length==1};c[lockClass]=false;
d3.选择(本)。分类(c);
};
函数置换颜色(){
var samples=Math.min(50,Math.max(~~(squares.length/50),1)),s,ii=[],i,k=0,
cells=d3。选择全部('.cell');
而(样本--){
doi=pickdrandomcell(cells);while(ii.indexOf(i)>-1&&k++<5&&i>-1);
如果(k<10&&i>-1){
ii.推动(i);
s=平方[i];
拼接(i,1,{x:s.x,y:s.y,c:createRandomRGB(),indx:s.indx});
}
}
}
函数置换位置(){
变量样本=数学最小值(20,
if (direction === 'x') {
selectedCell.transition("x").duration(1500)
.attr('x', newX)
.each("start", function () { lock.call(this, "lockedX") })
.each("end", function () { unlock.call(this, "lockedX") });
} else {
selectedCell.transition("y").duration(1500)
.attr('y', newY)
.each("start", function () { lock.call(this, "lockedX") })
.each("end", function () { unlock.call(this, "lockedX") });
}
function lock(lockClass) {
var c = { cell: false }; c[lockClass] = true;
d3.select(this).classed(c)
};
function unlock(lockClass) {
var c = { cell: this.classList.length == 1 }; c[lockClass] = false;
d3.select(this).classed(c);
};