私は一度に一歩ずつ答えに取り組み、あなたと共有するつもりです.
最初の簡単なステップは、行の長さを短くしてコードを見やすくするためだけに、非常にマイナーな再フォーマットです。実際には、この時点ではおそらく行の長さを気にする必要はありませんが、ここでは短い行の方が適切に表示されます。
axis = [ "X","Y","Z" ];
document.write(
"@keyframes tumble { "+
"12% {transform:rotate" +
axis[Math.floor(Math.random()*3)] +
"(-" + Math.floor(Math.random()*180) + "deg) rotate" +
axis[Math.floor(Math.random()*3)] +
"(" + Math.floor(Math.random()*180) + "deg) rotate" +
axis[Math.floor(Math.random()*3)] +
"(" + Math.floor(Math.random()*180) + "deg)}" +
"32% {transform:rotate" +
axis[Math.floor(Math.random()*3)] +
"(-" + Math.floor(Math.random()*180) + "deg) rotate" +
axis[Math.floor(Math.random()*3)] +
"(" + Math.floor(Math.random()*180) + "deg) rotate" +
axis[Math.floor(Math.random()*3)] +
"(" + Math.floor(Math.random()*180) + "deg)}" +
"50% {transform:rotate" +
axis[Math.floor(Math.random()*3)] +
"( " + Math.floor(Math.random()*180) + "deg) rotate" +
axis[Math.floor(Math.random()*3)] +
"(" + Math.floor(Math.random()*180) + "deg) rotate" +
axis[Math.floor(Math.random()*3)] +
"(" + Math.floor(Math.random()*180) + "deg)}" +
"66% {transform:rotate" +
axis[Math.floor(Math.random()*3)] +
"( " + Math.floor(Math.random()*180) + "deg) rotate" +
axis[Math.floor(Math.random()*3)] +
"(" + Math.floor(Math.random()*180) + "deg) rotate" +
axis[Math.floor(Math.random()*3)] +
"(" + Math.floor(Math.random()*180) + "deg)}" +
"84% {transform:rotate" +
axis[Math.floor(Math.random()*3)] +
"( " + Math.floor(Math.random()*180) + "deg) rotate" +
axis[Math.floor(Math.random()*3)] +
"(" + Math.floor(Math.random()*180) + "deg) rotate" +
axis[Math.floor(Math.random()*3)] +
"(" + Math.floor(Math.random()*180) + "deg)}" +
"}</style>"
);
2 つの項目がすぐに飛び出します:<style>
生成されたコードの先頭にタグが欠落しているように見えます (</style>
最後に a があります)。そしてvar
、axis = ...
ステートメントに欠落があります。
次に明らかなことは、これら 2 つのパターンがコード内で何度も発生していることです。
Math.floor(Math.random()*3)
Math.floor(Math.random()*180)
それでは、いくつかの関数を記述してそれらを簡単にし、単純な検索と置換を行って、これらの関数を使用するように既存のコードを変更してみましょう。
// Return a random integer n in the range 0 <= n < limit
function randInt( limit ) {
return Math.floor( Math.random() * limit );
}
// Return a random integer n in the range 0 <= n < 3
function rand3() {
return randInt( 3 );
}
// Return a random integer n in the range 0 <= n < 180
function rand180() {
return randInt( 180 );
}
var axis = [ "X","Y","Z" ];
// Write a <style> tag to the document with a random animation
document.write(
"<style>@keyframes tumble { "+
"12% {transform:rotate" +
axis[rand3()] +
"(-" + rand180() + "deg) rotate" +
axis[rand3()] +
"(" + rand180() + "deg) rotate" +
axis[rand3()] +
"(" + rand180() + "deg)}" +
"32% {transform:rotate" +
axis[rand3()] +
"(-" + rand180() + "deg) rotate" +
axis[rand3()] +
"(" + rand180() + "deg) rotate" +
axis[rand3()] +
"(" + rand180() + "deg)}" +
"50% {transform:rotate" +
axis[rand3()] +
"( " + rand180() + "deg) rotate" +
axis[rand3()] +
"(" + rand180() + "deg) rotate" +
axis[rand3()] +
"(" + rand180() + "deg)}" +
"66% {transform:rotate" +
axis[rand3()] +
"( " + rand180() + "deg) rotate" +
axis[rand3()] +
"(" + rand180() + "deg) rotate" +
axis[rand3()] +
"(" + rand180() + "deg)}" +
"84% {transform:rotate" +
axis[rand3()] +
"( " + rand180() + "deg) rotate" +
axis[rand3()] +
"(" + rand180() + "deg) rotate" +
axis[rand3()] +
"(" + rand180() + "deg)}" +
"}</style>"
);
ご覧のとおり、コードはすでにはるかに単純になっています。
では、これら 5 つの類似したコード ブロックの中で何が同じで、何が違うのか見てみましょう。これらのブロックを、文字ごとの (行内) 差分を実行できるプログラムにロードすると便利です。これにはAraxis Mergeを使用します。Beyond Compareも良い選択です。これらは両方とも商用製品です。間違いなく優れた無料の代替品もあります。
最初のブロックと最後のブロックを比較すると、Araxis Merge は次のように表示します。

(フォントが気に入らなくても、Araxis のせいにしないでください。これは私の個人的な設定です。ワード ラップで幅を狭くしているのは、ここの列に収まるようにするためです。)
違いは 2 つだけであることがわかります。1 行目のパーセンテージ数と3 行目の"(-"
vs.です。"( "
実際、これらはすべてのブロック間で唯一の 2 つの違いです。
したがって、今できることは、このコード スニペットを返す関数を記述して、これら 2 つの値をプラグインできるようにすることです。
// Return a transform:rotate string with the specified
// percent and flag
function makeTransform( percent, flag ) {
return (
percent + "% {transform:rotate" +
axis[rand3()] +
"(" + flag + rand180() + "deg) rotate" +
axis[rand3()] +
"(" + rand180() + "deg) rotate" +
axis[rand3()] +
"(" + rand180() + "deg)}"
);
}
その関数を見ると、まだいくつかのことが繰り返されています。しかし、この時点では非常に単純です。繰り返しはかなり少ないです。しかし、ここまで来たら、そのコードをもう少しリファクタリングする方法を見てみましょう。
// Return a random axis and degree string
function randAxisDegree( flag ) {
return axis[rand3()] + "(" + flag + rand180() + "deg)";
}
// Return a transform:rotate string with the specified
// percent and flag
function makeTransform( percent, flag ) {
return (
percent + "% {transform:rotate" +
randAxisDegree(flag) + " rotate" +
randAxisDegree("") + " rotate" +
randAxisDegree("") +
"}"
);
}
もちろん、以前に作成した 関数rand3()
とrand180()
関数が実際には必要ではないことに気付くかもしれません。なぜなら、これらはそれぞれ 1 つの場所でしか使用されず、別個の関数である必要がまったくないからです。
実際、コードを振り返ってみると、これら 2 つの関数は、複数の場所で呼び出されたとしてもあまり役に立ちません。rand3()
randInt(3)
rand()
rand(3)
rand3()
この回答を編集して、最初からこのアプローチを採用したいと思いますが、リファクタリングがたどるやや曲がった道を示すために、そのままにしておきましょう。ただし、ここでそれらを削除し、randInt()
から直接呼び出しrandAxisDegree()
ます。
// Return a random axis and degree string
function randAxisDegree( flag ) {
return axis[randInt(3)] + "(" + flag + randInt(180) + "deg)";
}
これで、すべてがどのように適合するかがわかります。
// Return a random integer n in the range 0 <= n < limit
function randInt( limit ) {
return Math.floor( Math.random() * limit );
}
var axis = [ "X", "Y", "Z" ];
// Return a random axis and degree string
function randAxisDegree( flag ) {
return axis[randInt(3)] + "(" + flag + randInt(180) + "deg)";
}
// Return a transform:rotate string with the specified
// percent and flag
function makeTransform( percent, flag ) {
return (
percent + "% {transform:rotate" +
randAxisDegree(flag) + " rotate" +
randAxisDegree("") + " rotate" +
randAxisDegree("") +
"}"
);
}
// Write a <style> tag to the document with a random animation
document.write(
"<style>@keyframes tumble { " +
makeTransform( 12, "-" ) +
makeTransform( 32, "-" ) +
makeTransform( 50, " " ) +
makeTransform( 66, " " ) +
makeTransform( 84, " " ) +
"}</style>"
);