打字稿:将图像向左移动,然后向右移动



第一个免责声明:我对Typescript/javascript/前端开发仍然非常陌生

背景:我有一组图像(代表一手牌(。当轮到AI出牌时,我试图展示"思考"的模拟,而不是立即出牌。我的模拟是遍历一手牌并"选择"每张牌("选择"是指将图像稍微向左移动,然后向右移动(。

我正在使用Visual Studio Code,并且正在Chrome中调试。我当前的代码如下。前提是进行 API 调用(这实际上是执行 AI 逻辑的地方(。然后演示文稿遍历卡片,每张卡片等待 1/4 秒,将卡片向左移动,再等待 1/4 秒,然后将卡片移回右侧。"选择"完所有牌后,打出实际的牌。我目前在回调函数中拥有所有内容以使其保持同步,但我不确定我什至需要这样做。

// Call in to the API, which will perform the AI logic
// The API will return a slot that was played, which contains the card placed into that slot
opponentTurn(callback)
{
this.boardService.opponentTurn()
.subscribe(
cardPlayed =>
{
// Set the card played
let cardData = [];
cardData = JSON.parse(cardPlayed.toString());
// To add a slight hint of "thinking", let's "select" (slightly move the card to the left) each card down, up, and back down to the card that the API selected
this.selectCard(function(_thisagain) {
// Done
// Now simulate the move
_thisagain.dragService.simulateDragDrop(cardData);
});        
callback(this);
}
);
}
// Call this to "select" a card; used by the AI "thinking" simulation
selectCard(callback)
{
for (var i = 0; i < this.players[1].cardHand.length; i++)
{
let imgObj = document.getElementById(this.players[1].name + i);     
if (imgObj != null)
{
this.moveCard(imgObj, '400px', function(_thisagain) {
_thisagain.moveCard(imgObj, '350px', function() {
// Done
});
});
}
}
callback(this);
}
moveCard(imgObj, position, callback)
{
this.wait(250, function() {
imgObj.style.right = position;
});
callback(this);
}
wait(ms, callback)
{
var start = new Date().getTime();
var end = start;
while(end < start + ms)
{
end = new Date().getTime();
}
callback(this);
}

所以我遇到的困难是代码有效,但只有当我在它上面放置断点时。例如,如果我在"_thisagain.moveCard(imgObj, '350px', function(( {"行上放置一个断点,然后对其进行调试,我可以看到每张卡都向左移动并回到右侧,就像我每次"继续"时所期望的那样。如果我删除断点,牌根本不会移动(但我仍然需要等待在棋盘上打牌(。

仍然是Typescript/javascript的新手,我不太确定发生了什么。似乎当我设置断点时,会发生重绘以显示卡移。如果没有断点,似乎不会发生重绘。不过,我不知道如何纠正这一点,因此我在这里

因此,经过更多的研究和大量的试错,我让它工作了。真正让我走上正轨的帖子是这样的: 长时间运行函数上的 DOM 刷新

在这个问题中,有一个答案说: "网页是基于单个线程控制器更新的,一半的浏览器不会更新 DOM 或样式,直到你的 JS 执行停止,将计算控制权交还给浏览器。">

原来这就是我错过的钥匙。我在单个语句中处理了太多内容,并且 js 没有发布回浏览器,因此 DOM/html 没有更新以显示"动画"。

然后,我使用同样发布在那里的答案中的jsfiddle示例将一个"worker"线程拼凑在一起,该线程根据程序"状态"将进程分解为块,并使用setTimeout((将控制权交还给浏览器。每个工作线程仍设置为回调函数,以确保每个块中的处理在继续之前完成。对于我最初问题的意图,一切都在工作。我仍在重构,我相信可能有更好的方法来达到结果,但现在我很满意。

为了将来可能帮助可能偶然发现我的问题的人,这就是我的工作线程中的内容。当然,我对术语的选择可能是不正确的,但它的要点是这样的。当我想启动流程流时,我可以设置"状态"文本并呼叫工作人员。然后,工作人员根据需要处理流。

doHeavyWork() {
if (this.status == 'finish')
{
// All steps done 
}
else
{
let _this = this;
switch (_this.status)
{
case 'start':
_this.status = 'working';
_this.opSelectCard = 0;
this.opponentTurn(function(response) {
_this.opCardData = response;
_this.status = 'selectCard';
});
break;
case 'selectCard':
_this.status = 'working';
this.selectCard(_this.opSelectCard, function(response) {
_this.opImgObj = response;
_this.status = 'moveCardLeft';
});
break;
case 'moveCardLeft':
_this.status = 'working';
this.moveCardLeft(_this.opImgObj, '-25px', function(root) {
_this.status = 'moveCardRight';
});
break;
case 'moveCardRight':
_this.status = 'working';
this.moveCardRight(_this.opImgObj, '1px', function(root) {
_this.opSelectCard++;
if (_this.opSelectCard < _this.players[1].cardHand.length)
{
_this.status = 'selectCard';
}
else
{
_this.status = 'simulateDragDrop';
}
});
break;
case 'simulateDragDrop':
_this.status = 'working';
this.dragService.simulateDragDrop(_this.opCardData, function(root) {
_this.status = 'refreshDisplay';
});
break;
case 'refreshDisplay':
_this.status = 'working';
this.refreshCardDisplay(function(root) {
_this.status = 'refreshDisplay';
});
break;
case 'refreshBoard':
_this.status = 'working';
this.refreshBoard(_this.boardCards, function(root) {
_this.status = 'updateScore';
});
break;
case 'updateScore':
_this.status = 'working';
this.updateScore(_this.boardCards, function(_this) {
_this.status = 'switchTurns';
});
break;
case 'switchTurns':
_this.status = 'working';
this.switchTurns(function(_this) {
if (_this.turn == 1)
{
_this.status = 'finish';
}
else
{
_this.status = 'start';
}
});
break;
}
setTimeout(function() {
_this.doHeavyWork();
}, 0);
}
}

最新更新