加えてTransform後のどの面が正面を向いているかを判断しています。
HTMLでのDIVの配置、CSS設定は3D 四面の応用です。
5つの立方体のDiceを配置する。
<div id="view">
<div id="cube1" onclick="selCube(this, false);">
<div class="face f1">1</div>
<div class="face f2">2</div>
<div class="face f3">3</div>
<div class="face f4">4</div>
<div class="face f5">5</div>
<div class="face f6">6</div>
</div>
<div id="cube2" onclick="selCube(this, false);">
<div class="face f1">1</div>
<div class="face f2">2</div>
<div class="face f3">3</div>
<div class="face f4">4</div>
<div class="face f5">5</div>
<div class="face f6">6</div>
</div>
以下同様にcube3~cube5を配置する。
</div>
(selCubeはtapされたときにそのDiceを選択状態にするfunction)
上記DIVを配置するCSS
全体の位置
#view {
width:640px;
height:600px;
margin:0px auto 0px auto;
-webkit-transform:translateX(1px);
-webkit-perspective: 1600;
-webkit-perspective-origin-x: 550px;
-webkit-perspective-origin-y: 600px;
}
各cube共通設定
#cube1, #cube2, #cube3, #cube4, #cube5 {
position:absolute;
display:none;
height:200px;
width:200px;
-webkit-transform-style: preserve-3d;
-webkit-transform:translateZ(-3000px);
}
上列3個のDiceのtop位置
#cube1, #cube2, #cube3 {
margin-top: -240px;
}
下列3個のDiceのY位置
#cube4, #cube5 {
margin-top: 60px;
}
各Diceの横位置。cube2は中央なので設定不要。
#cube1 { margin-left:320px; }
#cube3 { margin-left:-320px; }
#cube4 { margin-left:160px; }
#cube5 { margin-left:-160px; }
Dice各面の共通設定
.face {
position: absolute;
height: 160px;
width: 160px;
padding: 20px;
font-size: 150px;
text-align;center;
vertical-align;center;
color: transparent;
border:solid 4px darkgray;
background-color: rgba(50, 50, 50, 0.5);
-webkit-border-radius: 40px;
}
6面各々の位置決め、およびイメージ設定。
.f1 {
-webkit-transform: rotateX(90deg) translateZ(100px);
background-image:url("../Images/1.png");
}
.f2 {
-webkit-transform: translateZ(100px);
background-image:url("../Images/2.png");
}
.f3 {
-webkit-transform: rotateY(90deg) translateZ(100px);
background-image:url("../Images/3.png");
}
.f4 {
-webkit-transform: rotateX(180deg) translateZ(100px);
background-image:url("../Images/4.png");
}
.f5 {
-webkit-transform: rotateY(-90deg) translateZ(100px);
background-image:url("../Images/5.png");
}
.f6 {
-webkit-transform: rotateX(-90deg) translateZ(100px) ;
background-image:url("../Images/6.png");
}
JavaScript
//Diceコンストラクタ
Dice = function(cube) {
this.cube = cube;
this.x = Dice.rand() * 360;
this.y = Dice.rand() * 360;
this.z = Dice.rand() * 360;
this.dx = this.dy = this.dz = 0;
this.dist = -200; //traslateZ
this.sec = 0.1;
this.interval = 100; //msec;
this.timer = null;
//同一DiceでTimerイベントを複数実行しないようにするためのフラグ。
this.busy = false;
//trueの間、落下・回転を続ける。
this.flag = true;
//何故かiOSでは2,3が入れ替わるので、OSに合わせてfacesのindexを設定
this.fArr = isIOS ? new Array(1,3,2,4,5,6) : new Array(1,2,3,4,5,6);
}
//Dice初期化. 5個のDiceに対応するインスタンスを作り、cubes配列にセット.
//選択されていないDiceは0とする.
//spotsArrは正面を向いている面が何かを判断するための配列。
Dice.init = function() {
Dice.spotsArr = new Array(
(cubes[0].getAttribute("selected") != "true" ? Dice.spotsArr[0] : 0),
(cubes[1].getAttribute("selected") != "true" ? Dice.spotsArr[1] : 0),
(cubes[2].getAttribute("selected") != "true" ? Dice.spotsArr[2] : 0),
(cubes[3].getAttribute("selected") != "true" ? Dice.spotsArr[3] : 0),
(cubes[4].getAttribute("selected") != "true" ? Dice.spotsArr[4] : 0));
Dice._seed = Math.random(new Date().getTime());
}
//選択状態を表すために背景色を変更するとBackground-Imageが無効になるので再設定する。
Dice.prototype.setImageUrl = function() {
this.cube.setAttribute("needsImage", false);
for(var i=0; i<this.cube.childNodes.length; i++) {
var face = this.cube.childNodes[i];
if (face.nodeType == 1) {
face.style.backgroundImage = face.getAttribute("url");
face.style.color = "transparent";
}
}
}
//乱数生成
Dice.rand = function() {
Dice._seed = Math.random(Dice._seed);
return Math.random(new Date().getTime());
}
//タイマーイベントで呼び出される。
Dice.roll = function(o) {
//selected属性をリセットする。
o.cube.setAttribute("selected", "false");
//引数のDiceインスタンスのrollを呼ぶ。
o.roll();
}
//Diceを振る。WebKitの場合のみ実行。
Dice.prototype.roll = function() {
if (!isWebKit || this.busy) return;
this.busy = true;
//画像がセットされていないときに画像をセット。
if (this.cube.getAttribute("needsImage") == "true") this.setImageUrl();
//this.cube.setAttribute("selected", "false");
try {
//視点の高さ(距離)設定
var dist = (isIOS ? -1560 : -800);
//高さによりロジックを変える。
if (this.flag && this.dist > dist) {
//まだdistまで落下していない場合。
//乱数初期化
Dice._seed = Math.random(new Date().getTime());
//乱数を用いて回転角設定。
var r1 = Dice.rand() * 40;
var r2 = Dice.rand() * 40;
var r3 = Dice.rand() * 40;
//直前の回転角に加え、今回の回転をセット。
this.x += r1;
this.y += r2;
this.z += r3;
//落下速度調整
this.dist -= 70;
//次回の回転をTimerでセット。
this.timer = setTimeout(Dice.roll, this.interval, this);
} else {
//distまで落下した一番正面を向いている面を真正面に向ける。
var mX = this.x % 90; var amX = Math.abs(mX);
var mY = this.y % 90; var amY = Math.abs(mY);
var mZ = this.z % 90; var amZ = Math.abs(mZ);
if (amX > 1 || amY > 1 || amZ > 1) {
if (this.interval > 10) this.interval -= 1;
this.x = (amX > 3 ? this.x - 3 : this.x - mX);
this.y = (amY > 3 ? this.y - 3 : this.y - mY);
this.z = (amZ > 3 ? this.z - 3 : this.z - mZ);
this.flag = false;
this.timer = setTimeout(Dice.roll, this.interval, this);
this.interval = 10;
} else {
//真正面を向いたら組み合わせ結果を表示。
this.setSpots();
}
}
//上の計算結果でTransformを実行。
this.cube.style.webkitTransform = "translateZ(" + this.dist + "px) "
+ "rotateX("+ this.x + "deg) "
+ "rotateY("+ this.y + "deg) "
+ "rotateZ("+ this.z + "deg) ";
this.cube.style.display = "inline";
} catch(e) {
alert("Dice.roll: " + e);
} finally {
this.busy = false;
}
}
//正面を向いている目を判断する。
//X,Y,Z軸各々について回転角から面の位置を判断する。
//Timerイベントで実行されるときはthis=window。
Dice.prototype.setSpots = function() {
//360°回転すると元に戻るので残りの角度で判断。
//rotateの順に合わせ、Z、Y、Xの順で判断。順序は重要。
var rz = this.z % 360;
//90°毎に面をシフト。
while(rz >= 90) {
rz -= 90;
var t = this.fArr[0];
this.fArr[0] = this.fArr[4];
this.fArr[4] = this.fArr[5];
this.fArr[5] = this.fArr[1];
this.fArr[1] = t;
}
var ry = this.y % 360;
while(ry >= 90) {
ry -= 90;
var t = this.fArr[2];
this.fArr[2] = this.fArr[4];
this.fArr[4] = this.fArr[3];
this.fArr[3] = this.fArr[1];
this.fArr[1] = t;
}
var rx = this.x % 360;
while(rx >= 90) {
rx -= 90;
var t = this.fArr[2];
this.fArr[2] = this.fArr[5];
this.fArr[5] = this.fArr[3];
this.fArr[3] = this.fArr[0];
this.fArr[0] = t;
}
//5つのcubeのどれかを判断。
var n = new Number(this.cube.id.charAt(4));
Dice.spotsArr[n-1] = this.fArr[2];
//5つのDice全部の目がセットされたら役を表示。
if (Dice.spotsArr[0]>0
&& Dice.spotsArr[1]>0
&& Dice.spotsArr[2]>0
&& Dice.spotsArr[3]>0
&& Dice.spotsArr[4]>0) {
Dice.showSpots();
}
}
//役判断用フラグ
Dice.spotsArr = new Array(0,0,0,0,0);
Dice.pair1 = null;
Dice.pair2 = null;
Dice.three = null;
Dice.four = null;
Dice.five = null;
Dice.fullHouse = null;
//回転終了時の正面の目の組み合わせから役を判断、表示する。
Dice.showSpots = function() {
//役のフラグをクリア
Dice.pair1 = Dice.pair2 = Dice.three = Dice.four = Dice.five = Dice.fullHouse = null;
//正面を向いている目の配列をコピーし、ソートする。
var arr = new Array(Dice.spotsArr[0],Dice.spotsArr[1],Dice.spotsArr[2],Dice.spotsArr[3],Dice.spotsArr[4]);
arr.sort();
//役の判断。
Dice.findCombinations(arr);
//役のフラグから役の名前を設定。
var str = "";
if (Dice.pair1 != null) {
if (Dice.pair2 == null) str += "One Pair[" + Dice.pair1 +"]<br>";
else str += "Tow Pairs[" + Dice.pair1 + "," + Dice.pair2 +"]<br>";
} else if (Dice.three != null) {
str += "Three Of A Kind[" + Dice.three +"]<br>";
} else if (Dice.four != null) {
str += "Four Of A Kind[" + Dice.four +"]<br>";
} else if (Dice.five != null) {
str += "Five[" + Dice.five +"]<br>";
} else if (Dice.fullHouse != null) {
str += "Full House[" + Dice.fullHouse +"]<br>";
} else {
str += "All Different[" + arr +"]<br>";
}
//役を表示。
var div = document.getElementById("memo");
div.innerHTML = str + "\n" + Dice.spotsArr;
}
//役を見つける。
Dice.findCombinations = function(arr) {
var i=1, j=0, n=0, s=arr[0];
for(; i<5; i++) {
if (s == arr[i]) {
n++;
} else {
Dice.setPairs(n+1, s);
n = 0;
s = arr[i];
}
}
if (n > 0) Dice.setPairs(n+1, s);
if (Dice.three && Dice.pair1) {
Dice.fullHouse = Dice.three + "," + Dice.pair1;
Dice.three = Dice.pair1 = null;
}
}
//pair, three, four, fiveのフラグをセット。
Dice.setPairs = function(n, s) {
if (n == 2) {
if (Dice.pair1 == null) Dice.pair1 = s;
else Dice.pair2 = s;
} else if (n == 3) {
Dice.three = s;
} else if (n == 4) {
Dice.four = s;
} else if (n == 5) {
Dice.five = s;
}
}
//----- Diceを使用するfunction -----
var cubes = null;
//初期化(body.onloadなどで実行)
function init() {
//cubeのDIVを配列にセット
cubes = new Array(cube1, cube2, cube3, cube4, cube5);
var divs = document.getElementsByTagName("DIV");
//全Diceを選択状態にする。
selAll();
//Diceを振る。
roll();
}
//選択状態のDiceを振る。
function roll() {
Dice.init();
for(var i=0; i<5; i++) {
if (cubes[i].getAttribute("selected") == "true") new Dice(cubes[i]).roll();
}
}
//Diceを選択状態にセット、または反転する。
function selCube(c, selAll) {
if (!selAll && c.getAttribute("selected") == "true") {
//touchまたはclickされ、選択状態の場合は非選択状態にする。
c.setAttribute("selected", "false");
new Dice(c).setImageUrl();
} else {
//sellAllから呼ばれた時、または非選択状態のときは選択状態にする。
c.setAttribute("needsImage", "true");
c.setAttribute("selected", true);
var state = "true";
//cの子要素の背景色、文字色を設定。
var color = "rgba(130, 130, 255, 0.5)"; //半透明
for(var i=0; i<c.childNodes.length; i++) {
if (c.childNodes[i].nodeType == 1) { //ElementType
if (state == "true") c.childNodes[i].style.background = color;
if (state == "true") c.childNodes[i].style.color = "black";
}
}
}
}
function selAll() {
for(var i=0; i<5; i++) {
selCube(cubes[i], true);
}
}
//Diceコンストラクタ
Dice = function(cube) {
this.cube = cube;
this.x = Dice.rand() * 360;
this.y = Dice.rand() * 360;
this.z = Dice.rand() * 360;
this.dx = this.dy = this.dz = 0;
this.dist = -200; //traslateZ
this.sec = 0.1;
this.interval = 100; //msec;
this.timer = null;
//同一DiceでTimerイベントを複数実行しないようにするためのフラグ。
this.busy = false;
//trueの間、落下・回転を続ける。
this.flag = true;
//何故かiOSでは2,3が入れ替わるので、OSに合わせてfacesのindexを設定
this.fArr = isIOS ? new Array(1,3,2,4,5,6) : new Array(1,2,3,4,5,6);
}
//Dice初期化. 5個のDiceに対応するインスタンスを作り、cubes配列にセット.
//選択されていないDiceは0とする.
//spotsArrは正面を向いている面が何かを判断するための配列。
Dice.init = function() {
Dice.spotsArr = new Array(
(cubes[0].getAttribute("selected") != "true" ? Dice.spotsArr[0] : 0),
(cubes[1].getAttribute("selected") != "true" ? Dice.spotsArr[1] : 0),
(cubes[2].getAttribute("selected") != "true" ? Dice.spotsArr[2] : 0),
(cubes[3].getAttribute("selected") != "true" ? Dice.spotsArr[3] : 0),
(cubes[4].getAttribute("selected") != "true" ? Dice.spotsArr[4] : 0));
Dice._seed = Math.random(new Date().getTime());
}
//選択状態を表すために背景色を変更するとBackground-Imageが無効になるので再設定する。
Dice.prototype.setImageUrl = function() {
this.cube.setAttribute("needsImage", false);
for(var i=0; i<this.cube.childNodes.length; i++) {
var face = this.cube.childNodes[i];
if (face.nodeType == 1) {
face.style.backgroundImage = face.getAttribute("url");
face.style.color = "transparent";
}
}
}
//乱数生成
Dice.rand = function() {
Dice._seed = Math.random(Dice._seed);
return Math.random(new Date().getTime());
}
//タイマーイベントで呼び出される。
Dice.roll = function(o) {
//selected属性をリセットする。
o.cube.setAttribute("selected", "false");
//引数のDiceインスタンスのrollを呼ぶ。
o.roll();
}
//Diceを振る。WebKitの場合のみ実行。
Dice.prototype.roll = function() {
if (!isWebKit || this.busy) return;
this.busy = true;
//画像がセットされていないときに画像をセット。
if (this.cube.getAttribute("needsImage") == "true") this.setImageUrl();
//this.cube.setAttribute("selected", "false");
try {
//視点の高さ(距離)設定
var dist = (isIOS ? -1560 : -800);
//高さによりロジックを変える。
if (this.flag && this.dist > dist) {
//まだdistまで落下していない場合。
//乱数初期化
Dice._seed = Math.random(new Date().getTime());
//乱数を用いて回転角設定。
var r1 = Dice.rand() * 40;
var r2 = Dice.rand() * 40;
var r3 = Dice.rand() * 40;
//直前の回転角に加え、今回の回転をセット。
this.x += r1;
this.y += r2;
this.z += r3;
//落下速度調整
this.dist -= 70;
//次回の回転をTimerでセット。
this.timer = setTimeout(Dice.roll, this.interval, this);
} else {
//distまで落下した一番正面を向いている面を真正面に向ける。
var mX = this.x % 90; var amX = Math.abs(mX);
var mY = this.y % 90; var amY = Math.abs(mY);
var mZ = this.z % 90; var amZ = Math.abs(mZ);
if (amX > 1 || amY > 1 || amZ > 1) {
if (this.interval > 10) this.interval -= 1;
this.x = (amX > 3 ? this.x - 3 : this.x - mX);
this.y = (amY > 3 ? this.y - 3 : this.y - mY);
this.z = (amZ > 3 ? this.z - 3 : this.z - mZ);
this.flag = false;
this.timer = setTimeout(Dice.roll, this.interval, this);
this.interval = 10;
} else {
//真正面を向いたら組み合わせ結果を表示。
this.setSpots();
}
}
//上の計算結果でTransformを実行。
this.cube.style.webkitTransform = "translateZ(" + this.dist + "px) "
+ "rotateX("+ this.x + "deg) "
+ "rotateY("+ this.y + "deg) "
+ "rotateZ("+ this.z + "deg) ";
this.cube.style.display = "inline";
} catch(e) {
alert("Dice.roll: " + e);
} finally {
this.busy = false;
}
}
//正面を向いている目を判断する。
//X,Y,Z軸各々について回転角から面の位置を判断する。
//Timerイベントで実行されるときはthis=window。
Dice.prototype.setSpots = function() {
//360°回転すると元に戻るので残りの角度で判断。
//rotateの順に合わせ、Z、Y、Xの順で判断。順序は重要。
var rz = this.z % 360;
//90°毎に面をシフト。
while(rz >= 90) {
rz -= 90;
var t = this.fArr[0];
this.fArr[0] = this.fArr[4];
this.fArr[4] = this.fArr[5];
this.fArr[5] = this.fArr[1];
this.fArr[1] = t;
}
var ry = this.y % 360;
while(ry >= 90) {
ry -= 90;
var t = this.fArr[2];
this.fArr[2] = this.fArr[4];
this.fArr[4] = this.fArr[3];
this.fArr[3] = this.fArr[1];
this.fArr[1] = t;
}
var rx = this.x % 360;
while(rx >= 90) {
rx -= 90;
var t = this.fArr[2];
this.fArr[2] = this.fArr[5];
this.fArr[5] = this.fArr[3];
this.fArr[3] = this.fArr[0];
this.fArr[0] = t;
}
//5つのcubeのどれかを判断。
var n = new Number(this.cube.id.charAt(4));
Dice.spotsArr[n-1] = this.fArr[2];
//5つのDice全部の目がセットされたら役を表示。
if (Dice.spotsArr[0]>0
&& Dice.spotsArr[1]>0
&& Dice.spotsArr[2]>0
&& Dice.spotsArr[3]>0
&& Dice.spotsArr[4]>0) {
Dice.showSpots();
}
}
//役判断用フラグ
Dice.spotsArr = new Array(0,0,0,0,0);
Dice.pair1 = null;
Dice.pair2 = null;
Dice.three = null;
Dice.four = null;
Dice.five = null;
Dice.fullHouse = null;
//回転終了時の正面の目の組み合わせから役を判断、表示する。
Dice.showSpots = function() {
//役のフラグをクリア
Dice.pair1 = Dice.pair2 = Dice.three = Dice.four = Dice.five = Dice.fullHouse = null;
//正面を向いている目の配列をコピーし、ソートする。
var arr = new Array(Dice.spotsArr[0],Dice.spotsArr[1],Dice.spotsArr[2],Dice.spotsArr[3],Dice.spotsArr[4]);
arr.sort();
//役の判断。
Dice.findCombinations(arr);
//役のフラグから役の名前を設定。
var str = "";
if (Dice.pair1 != null) {
if (Dice.pair2 == null) str += "One Pair[" + Dice.pair1 +"]<br>";
else str += "Tow Pairs[" + Dice.pair1 + "," + Dice.pair2 +"]<br>";
} else if (Dice.three != null) {
str += "Three Of A Kind[" + Dice.three +"]<br>";
} else if (Dice.four != null) {
str += "Four Of A Kind[" + Dice.four +"]<br>";
} else if (Dice.five != null) {
str += "Five[" + Dice.five +"]<br>";
} else if (Dice.fullHouse != null) {
str += "Full House[" + Dice.fullHouse +"]<br>";
} else {
str += "All Different[" + arr +"]<br>";
}
//役を表示。
var div = document.getElementById("memo");
div.innerHTML = str + "\n" + Dice.spotsArr;
}
//役を見つける。
Dice.findCombinations = function(arr) {
var i=1, j=0, n=0, s=arr[0];
for(; i<5; i++) {
if (s == arr[i]) {
n++;
} else {
Dice.setPairs(n+1, s);
n = 0;
s = arr[i];
}
}
if (n > 0) Dice.setPairs(n+1, s);
if (Dice.three && Dice.pair1) {
Dice.fullHouse = Dice.three + "," + Dice.pair1;
Dice.three = Dice.pair1 = null;
}
}
//pair, three, four, fiveのフラグをセット。
Dice.setPairs = function(n, s) {
if (n == 2) {
if (Dice.pair1 == null) Dice.pair1 = s;
else Dice.pair2 = s;
} else if (n == 3) {
Dice.three = s;
} else if (n == 4) {
Dice.four = s;
} else if (n == 5) {
Dice.five = s;
}
}
//----- Diceを使用するfunction -----
var cubes = null;
//初期化(body.onloadなどで実行)
function init() {
//cubeのDIVを配列にセット
cubes = new Array(cube1, cube2, cube3, cube4, cube5);
var divs = document.getElementsByTagName("DIV");
//全Diceを選択状態にする。
selAll();
//Diceを振る。
roll();
}
//選択状態のDiceを振る。
function roll() {
Dice.init();
for(var i=0; i<5; i++) {
if (cubes[i].getAttribute("selected") == "true") new Dice(cubes[i]).roll();
}
}
//Diceを選択状態にセット、または反転する。
function selCube(c, selAll) {
if (!selAll && c.getAttribute("selected") == "true") {
//touchまたはclickされ、選択状態の場合は非選択状態にする。
c.setAttribute("selected", "false");
new Dice(c).setImageUrl();
} else {
//sellAllから呼ばれた時、または非選択状態のときは選択状態にする。
c.setAttribute("needsImage", "true");
c.setAttribute("selected", true);
var state = "true";
//cの子要素の背景色、文字色を設定。
var color = "rgba(130, 130, 255, 0.5)"; //半透明
for(var i=0; i<c.childNodes.length; i++) {
if (c.childNodes[i].nodeType == 1) { //ElementType
if (state == "true") c.childNodes[i].style.background = color;
if (state == "true") c.childNodes[i].style.color = "black";
}
}
}
}
function selAll() {
for(var i=0; i<5; i++) {
selCube(cubes[i], true);
}
}
3D Translate実装例(2) Diceについて
0 件のコメント:
コメントを投稿