Javascript-koden blir ltt komplisert fordi vi vi kontrollere rokader og beregne posisjoner.
I prinsipp er logikken slik:
1 les neste trekk og kontroller formatet
2 lokaliser de elementene som er til og fra
disse har samme id som ruteangivelsen i trekket
3 beregn den absolutte posisjonen til disse elementene
4 sett opp keyframes
5 start animasjone med en timeout som rydder opp
--
6 on timeout
sett endelig posisjon for brikken
skru av classen active
Scriptet er i sin helhet slik.
_animate.js
// remember what we are doing when active
var aniMove={
fromSq:null,
toSq:null,
runIm:null,
castling:false,
caTarnFrom:null,
caTarnTo:null
}
var aniMoveList=null;
var aniIndex=null;
var isAnimating=false;
// content of empty square
var empty='<img class="movable" src="no_piece.gif" alt="no">';
// sjekk if move txt is correct
function isMoveOk(m){
m=m.trim();
// rokade ?
if((m=="0-0")||(m=="0-0-0"))
return true;
var ids=m.split("-");
if(ids.length!=2){
alert("Feil trekk format: "+ids);
return false;
}
var re=new RegExp("[a-h][1-8]");
if((! ids[0].trim().match(re)) || (! ids[1].trim().match(re))){
alert("Feil trekk format: "+ids);
return false;
}
return true;
}
// start one move
// we aloow rocade(castling). Some details to take care off
// short:0-0, long 0-0-0
function animateOneMove(){
var S=aniMoveList[aniIndex].trim();
if(!isMoveOk(S))
return;
// must pick up castling here
// and prepare the unanimated tower move
aniMove.castling=false;
if((S=="0-0") && (aniIndex %2 == 0)){
// short white
aniMove.castling=true;
S="e1-g1";aniMove.caTarnFrom="h1"; aniMove.caTarnTo="f1";
}else if((S=="0-0-0") && (aniIndex %2 == 0)){
// long white
aniMove.castling=true;
S="e1-c1";aniMove.caTarnFrom="a1";aniMove.caTarnTo="d1";
}else if((S=="0-0") && (aniIndex %2 != 0)){
// short black
aniMove.castling=true;
S="e8-g8";aniMove.caTarnFrom="h8";aniMove.caTarnTo="f8";
}else if((S=="0-0-0") && (aniIndex %2 != 0)){
// long black
aniMove.castling=true;
S="e8-c8";aniMove.caTarnFrom="a8";aniMove.caTarnTo="d8";
}
var ids=S.split("-");
fromId=ids[0]; toId=ids[1];
aniMove.fromSq=document.getElementById(fromId);
aniMove.toSq=document.getElementById(toId);
// find absolute positions on screen (jQuery)
var FROM = $(aniMove.fromSq).offset();
var TO = $(aniMove.toSq).offset();
var FRT=FROM.top; var FRL=FROM.left;
var TRT=TO.top; var TRL=TO.left;
// set keyframes for animation
var sElt=document.getElementById("keyframes");
var coordinates=" mymove {from{left:"+FRL+"px; top:"+FRT+"px}"+
" to{ left:"+TRL+"px; top:"+TRT+"px} }";
sElt.innerHTML="@-webkit-keyframes " +coordinates+
"@-moz-keyframes " +coordinates+
"@keyframes "+coordinates;
// activate the image on the square we move from
aniMove.runIm=aniMove.fromSq.firstChild;
aniMove.runIm.classList.add("active");
setTimeout(function()
{
// move is done
// fix and reset
aniMove.runIm.classList.remove("active");
aniMove.toSq.innerHTML=aniMove.fromSq.innerHTML;
aniMove.fromSq.innerHTML=empty;
// handle tarn move in castling, unanimated
if(aniMove.castling){
document.getElementById(aniMove.caTarnTo).innerHTML=
document.getElementById(aniMove.caTarnFrom).innerHTML;
document.getElementById(aniMove.caTarnFrom).innerHTML=empty;
}
// more moves ?
aniIndex++;
if((isAnimating) && (aniIndex < aniMoveList.length)){
animateOneMove();
}
},
2900); // comparable to duration in CSS .active
}
function stopAnimation(){
isAnimating=false;
}
function startAnimation(){
isAnimating=true;
animateOneMove();
}
function reloadBoard(){
// fill the board, initial position
document.getElementById("board").innerHTML=basicBoard;
isAnimating=false;
// establish movelist from textarea
var S=document.getElementById("movetxt").value;
aniMoveList=S.split(",");
aniIndex=0;
}
Selve sjakkbrekket er beskrevet som en string som legges inn på siden ved oppstart