gpt4 book ai didi

javascript - 为什么有些细胞不能完全移动

转载 作者:数据小太阳 更新时间:2023-10-29 05:29:33 26 4
gpt4 key购买 nike

我已经设置了这个 jsfiddle:http://jsfiddle.net/386er/dhzq6q6f/14/

var moveCell = function(direction) {

var cellToBeMoved = pickRandomCell();
var currentX = cellToBeMoved.x.baseVal.value;
var currentY = cellToBeMoved.y.baseVal.value;
var change = getPlusOrMinus() * (cellSize + 1 );
var newX = currentX + change;
var newY = currentY + change;
var selectedCell = d3.select(cellToBeMoved);


if (direction === 'x') {
selectedCell.transition().duration(1500)
.attr('x', newX );
} else {
selectedCell.transition().duration(1500)
.attr('y', newY );

}

在 moveCell 函数中,我选择了一个随机单元格,请求其当前的 x 和 y 坐标,然后加上或减去它的宽度或高度,以将其移动到相邻的单元格。

我想知道的是:如果您观察细胞移动,有些细胞只会部分移动到下一个细胞。谁能告诉我,为什么会这样?

最佳答案

在这种情况下要做的第一件事是将 .each("interrupt", function() { console.log("interrupted!") }); 放在你的转换上。然后你就会看到问题了。
如果您将转换命名为 selection.transition("name"),它应该会修复它,但这并不能修复它。
这意味着您必须按照@jcuenod 的建议进行操作,并排除正在移动的那些。一种惯用的方法是这样的......

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);
};

Here是证明这个概念的 fiddle 。


纯正地道的 d3 版本

只是为了完整性,这里是 d3 的方式。
我试图让它尽可能地地道。要点是...

  1. 纯数据驱动
    数据已更新,可视化操作完全留给 d3 声明。
  2. 使用 d3 检测 svg 元素属性的变化并采取行动
    这是通过在 selection.data() 方法中使用复合 key 函数并利用更改节点(xyfill 属性与更新后的数据不匹配)被退出选择捕获。
  3. 将更改的元素拼接到数据数组中,以便 d3 可以检测更改
    由于对数据数组元素的引用 绑定(bind)到 DOM 元素,因此对数据的任何更改也将反射(reflect)在 selection.datum() 中。 d3 使用 key 函数将数据值与 datum 进行比较,以便将节点分类为更新、进入或退出。如果生成了一个,即数据/基准值的函数,则不会检测到数据的更改。通过拼接-ing 更改到数据数组中,selection.datum() 引用的值将不同于数据数组,因此数据更改将标记退出节点。< br/>通过简单地操纵属性并将转换放在退出选择上而不是将其删除,它实际上变成了“已更改”的选择。
    这仅在数据值是对象时才有效。
  4. 并发转换
    命名转换用于确保 x 和 y 转换不会相互中断,但也有必要使用标记类属性来锁定转换元素。这是使用转换开始和结束事件完成的。
  5. 动画帧
    d3.timer 用于平滑动画和编码资源。在每个动画帧之前,d3Timer 回调以更新转换之前的数据。
  6. 使用 d3.scale.ordinal() 管理定位
    这很棒,因为它每次都有效,您甚至不必考虑它。

$(function () {
var container,
svg,
gridHeight = 800,
gridWidth = 1600,
cellSize, cellPitch,
cellsColumns = 100,
cellsRows = 50,
squares,

container = d3.select('.svg-container'),
svg = container.append('svg')
.attr('width', gridWidth)
.attr('height', gridHeight)
.style({ 'background-color': 'black', opacity: 1 }),

createRandomRGB = function () {
var red = Math.floor((Math.random() * 256)).toString(),
green = Math.floor((Math.random() * 256)).toString(),
blue = Math.floor((Math.random() * 256)).toString(),
rgb = 'rgb(' + red + ',' + green + ',' + blue + ')';
return rgb;
},

createGrid = function (width, height) {

var scaleHorizontal = d3.scale.ordinal()
.domain(d3.range(cellsColumns))
.rangeBands([0, width], 1 / 15),
rangeHorizontal = scaleHorizontal.range(),

scaleVertical = d3.scale.ordinal()
.domain(d3.range(cellsRows))
.rangeBands([0, height]),
rangeVertical = scaleVertical.range(),

squares = [];
rangeHorizontal.forEach(function (dh, i) {
rangeVertical.forEach(function (dv, j) {
var indx;
squares[indx = i + j * cellsColumns] = { x: dh, y: dv, c: createRandomRGB(), indx: indx }
})
});

cellSize = scaleHorizontal.rangeBand();
cellPitch = {
x: rangeHorizontal[1] - rangeHorizontal[0],
y: rangeVertical[1] - rangeVertical[0]
}

svg.selectAll("rect").data(squares, function (d, i) { return d.indx })
.enter().append('rect')
.attr('class', 'cell')
.attr('width', cellSize)
.attr('height', cellSize)
.attr('x', function (d) { return d.x })
.attr('y', function (d) { return d.y })
.style('fill', function (d) { return d.c });

return squares;
},

choseRandom = function (options) {
options = options || [true, false];
var max = options.length;
return options[Math.floor(Math.random() * (max))];
},

pickRandomCell = function (cells) {

var l = cells.size(),
r = Math.floor(Math.random() * l);

return l ? d3.select(cells[0][r]).datum().indx : -1;

};

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);
};

function permutateColours() {
var samples = Math.min(50, Math.max(~~(squares.length / 50),1)), s, ii = [], i, k = 0,
cells = d3.selectAll('.cell');
while (samples--) {
do i = pickRandomCell(cells); while (ii.indexOf(i) > -1 && k++ < 5 && i > -1);
if (k < 10 && i > -1) {
ii.push(i);
s = squares[i];
squares.splice(i, 1, { x: s.x, y: s.y, c: createRandomRGB(), indx: s.indx });
}
}

}

function permutatePositions() {
var samples = Math.min(20, Math.max(~~(squares.length / 100),1)), s, ss = [], d, m, p, k = 0,
cells = d3.selectAll('.cell');
while (samples--) {
do s = pickRandomCell(cells); while (ss.indexOf(s) > -1 && k++ < 5 && s > -1);
if (k < 10 && s > -1) {
ss.push(s);
d = squares[s];
m = { x: d.x, y: d.y, c: d.c, indx: d.indx };
m[p = choseRandom(["x", "y"])] = m[p] + choseRandom([-1, 1]) * cellPitch[p];

squares.splice(s, 1, m);
}
}
}

function updateSquares() {
//use a composite key function to transform the exit selection into
// an attribute update selection
//because it's the exit selection, d3 doesn't bind the new data
// that's done manually with the .each
var changes = svg.selectAll("rect")
.data(squares, function (d, i) { return d.indx + "_" + d.x + "_" + d.y + "_" + d.c; })
.exit().each(function (d, i, j) { d3.select(this).datum(squares[i]) })

changes.transition("x").duration(1500)
.attr('x', function (d) { return d.x })
.each("start", function () { lock.call(this, "lockedX") })
.each("end", function () { unlock.call(this, "lockedX") })

changes.transition("y").duration(1500)
.attr('y', function (d) { return d.y })
.each("start", function () { lock.call(this, "lockedY") })
.each("end", function () { unlock.call(this, "lockedY") });

changes.attr("stroke", "white")
.style("stroke-opacity", 0.6)
.transition("fill").duration(800)
.style('fill', function (d, i) { return d.c })
.style("stroke-opacity", 0)
.each("start", function () { lock.call(this, "lockedFill") })
.each("end", function () { unlock.call(this, "lockedFill") });
}
squares = createGrid(gridWidth, gridHeight);

d3.timer(function tick() {
permutateColours();
permutatePositions();
updateSquares();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<div class="svg-container"></div>

NOTE: requires d3 version 3.5.5 for the position transitions to run.

编辑:修复了锁定和解锁的问题。标记数据可能比将类写入 DOM 更好,但无论如何……这种方式很有趣。

关于javascript - 为什么有些细胞不能完全移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30322620/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com