CSS Transforms関連記事のまとめ的意味を込めて、くるくる回るサイコロを作成してみました。下のサイコロ(の開き)をクリック(またはhover)すると、クリックした間だけアニメーションします。CSSのみ(と思ったらiPhoneだと期待したようにactive状態にならないので、touchstartしたときにdice-actionというclassを追加するようにJavascriptを入れた)。
* { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .dice { -webkit-transform-style: preserve-3d; -moz-transform-style: preserve-3d; -ms-transform-style: preserve-3d; -o-transform-style: preserve-3d; transform-style: preserve-3d; -webkit-perspective: 1000px; -moz-perspective: 1000px; -ms-perspective: 1000px; -o-perspective: 1000px; perspective: 1000px; -webkit-perspective-origin: 50% 50%; -moz-perspective-origin: 50% 50%; -ms-perspective-origin: 50% 50%; -o-perspective-origin: 50% 50%; perspective-origin: 50% 50%; position: relative; width: 400px; height: 400px; } .dice > div, .dice .five, .dice .six { position: absolute; width: 100px; height: 100px; border: 1px solid #ddd; background-color: rgba(158, 158, 158, 0.1); line-height: 100px; text-align: center; } .dice .one { top: 100px; left: 200px; } .dice .two { top: 0; left: 200px; -webkit-transform-origin: bottom left; -moz-transform-origin: bottom left; -ms-transform-origin: bottom left; -o-transform-origin: bottom left; transform-origin: bottom left; border-bottom: none; } .dice .three { top: 100px; left: 300px; -webkit-transform-origin: top left; -moz-transform-origin: top left; -ms-transform-origin: top left; -o-transform-origin: top left; transform-origin: top left; border-left: none; } .dice .three .inner { -webkit-transform: rotateZ(90deg); -moz-transform: rotateZ(90deg); -ms-transform: rotateZ(90deg); -o-transform: rotateZ(90deg); transform: rotateZ(90deg); } .dice .four { top: 100px; left: 100px; -webkit-transform-origin: top right; -moz-transform-origin: top right; -ms-transform-origin: top right; -o-transform-origin: top right; transform-origin: top right; border-right: none; } .dice .four .inner { -webkit-transform: rotateZ(-90deg); -moz-transform: rotateZ(-90deg); -ms-transform: rotateZ(-90deg); -o-transform: rotateZ(-90deg); transform: rotateZ(-90deg); } .dice .five-six { top: 200px; left: 200px; -webkit-transform-origin: top left; -moz-transform-origin: top left; -ms-transform-origin: top left; -o-transform-origin: top left; transform-origin: top left; border: none; background: transparent; height: 200px; -webkit-transform-style: preserve-3d; -moz-transform-style: preserve-3d; -ms-transform-style: preserve-3d; -o-transform-style: preserve-3d; transform-style: preserve-3d; } .dice .five { top: 0; left: 0; border-top: none; border-bottom: none; } .dice .five .inner { -webkit-transform: rotateZ(180deg); -moz-transform: rotateZ(180deg); -ms-transform: rotateZ(180deg); -o-transform: rotateZ(180deg); transform: rotateZ(180deg); } .dice .six { top: 100px; left: 0; -webkit-transform-origin: top left; -moz-transform-origin: top left; -ms-transform-origin: top left; -o-transform-origin: top left; transform-origin: top left; } .dice .six .inner { -webkit-transform: rotateZ(180deg); -moz-transform: rotateZ(180deg); -ms-transform: rotateZ(180deg); -o-transform: rotateZ(180deg); transform: rotateZ(180deg); } .dice:hover, .dice:active, .dice-active { -moz-animation-duration: 5s; -moz-animation-name: cube; -moz-animation-iteration-count: infinite; -moz-animation-timing-function: linear; -webkit-animation-duration: 5s; -webkit-animation-name: cube; -webkit-animation-iteration-count: infinite; -webkit-animation-timing-function: linear; -ms-animation-duration: 5s; -ms-animation-name: cube; -ms-animation-iteration-count: infinite; -ms-animation-timing-function: linear; -o-animation-duration: 5s; -o-animation-name: cube; -o-animation-iteration-count: infinite; -o-animation-timing-function: linear; animation-duration: 5s; animation-name: cube; animation-iteration-count: infinite; animation-timing-function: linear; } .dice:hover .two, .dice:active .two, .dice-active .two { -webkit-transform: rotateX(-90deg); -moz-transform: rotateX(-90deg); -ms-transform: rotateX(-90deg); -o-transform: rotateX(-90deg); transform: rotateX(-90deg); } .dice:hover .three, .dice:active .three, .dice-active .three { -webkit-transform: rotateY(-90deg); -moz-transform: rotateY(-90deg); -ms-transform: rotateY(-90deg); -o-transform: rotateY(-90deg); transform: rotateY(-90deg); } .dice:hover .four, .dice:active .four, .dice-active .four { -webkit-transform: rotateY(90deg); -moz-transform: rotateY(90deg); -ms-transform: rotateY(90deg); -o-transform: rotateY(90deg); transform: rotateY(90deg); } .dice:hover .five-six, .dice:active .five-six, .dice-active .five-six { -webkit-transform: rotateX(90deg); -moz-transform: rotateX(90deg); -ms-transform: rotateX(90deg); -o-transform: rotateX(90deg); transform: rotateX(90deg); } .dice:hover .six, .dice:active .six, .dice-active .six { -webkit-transform: rotateX(90deg); -moz-transform: rotateX(90deg); -ms-transform: rotateX(90deg); -o-transform: rotateX(90deg); transform: rotateX(90deg); } .dice:hover .two, .dice:active .two, .dice-active .two { -moz-animation-duration: 2s; -moz-animation-name: cube-two; -moz-animation-iteration-count: 1; -moz-animation-timing-function: ease; -moz-animation-delay: 0s; -webkit-animation-duration: 2s; -webkit-animation-name: cube-two; -webkit-animation-iteration-count: 1; -webkit-animation-timing-function: ease; -webkit-animation-delay: 0s; -ms-animation-duration: 2s; -ms-animation-name: cube-two; -ms-animation-iteration-count: 1; -ms-animation-timing-function: ease; -ms-animation-delay: 0s; -o-animation-duration: 2s; -o-animation-name: cube-two; -o-animation-iteration-count: 1; -o-animation-timing-function: ease; -o-animation-delay: 0s; animation-duration: 2s; animation-name: cube-two; animation-iteration-count: 1; animation-timing-function: ease; animation-delay: 0s; } .dice:hover .three, .dice:active .three, .dice-active .three { -moz-animation-duration: 2s; -moz-animation-name: cube-three; -moz-animation-iteration-count: 1; -moz-animation-timing-function: ease; -moz-animation-delay: 0s; -webkit-animation-duration: 2s; -webkit-animation-name: cube-three; -webkit-animation-iteration-count: 1; -webkit-animation-timing-function: ease; -webkit-animation-delay: 0s; -ms-animation-duration: 2s; -ms-animation-name: cube-three; -ms-animation-iteration-count: 1; -ms-animation-timing-function: ease; -ms-animation-delay: 0s; -o-animation-duration: 2s; -o-animation-name: cube-three; -o-animation-iteration-count: 1; -o-animation-timing-function: ease; -o-animation-delay: 0s; animation-duration: 2s; animation-name: cube-three; animation-iteration-count: 1; animation-timing-function: ease; animation-delay: 0s; } .dice:hover .four, .dice:active .four, .dice-active .four { -moz-animation-duration: 2s; -moz-animation-name: cube-four; -moz-animation-iteration-count: 1; -moz-animation-timing-function: ease; -moz-animation-delay: 0s; -webkit-animation-duration: 2s; -webkit-animation-name: cube-four; -webkit-animation-iteration-count: 1; -webkit-animation-timing-function: ease; -webkit-animation-delay: 0s; -ms-animation-duration: 2s; -ms-animation-name: cube-four; -ms-animation-iteration-count: 1; -ms-animation-timing-function: ease; -ms-animation-delay: 0s; -o-animation-duration: 2s; -o-animation-name: cube-four; -o-animation-iteration-count: 1; -o-animation-timing-function: ease; -o-animation-delay: 0s; animation-duration: 2s; animation-name: cube-four; animation-iteration-count: 1; animation-timing-function: ease; animation-delay: 0s; } .dice:hover .five-six, .dice:active .five-six, .dice-active .five-six { -moz-animation-duration: 2s; -moz-animation-name: cube-five-six; -moz-animation-iteration-count: 1; -moz-animation-timing-function: ease; -moz-animation-delay: 0s; -webkit-animation-duration: 2s; -webkit-animation-name: cube-five-six; -webkit-animation-iteration-count: 1; -webkit-animation-timing-function: ease; -webkit-animation-delay: 0s; -ms-animation-duration: 2s; -ms-animation-name: cube-five-six; -ms-animation-iteration-count: 1; -ms-animation-timing-function: ease; -ms-animation-delay: 0s; -o-animation-duration: 2s; -o-animation-name: cube-five-six; -o-animation-iteration-count: 1; -o-animation-timing-function: ease; -o-animation-delay: 0s; animation-duration: 2s; animation-name: cube-five-six; animation-iteration-count: 1; animation-timing-function: ease; animation-delay: 0s; } .dice:hover .six, .dice:active .six, .dice-active .six { -moz-animation-duration: 4s; -moz-animation-name: cube-six; -moz-animation-iteration-count: 1; -moz-animation-timing-function: ease; -moz-animation-delay: 0s; -webkit-animation-duration: 4s; -webkit-animation-name: cube-six; -webkit-animation-iteration-count: 1; -webkit-animation-timing-function: ease; -webkit-animation-delay: 0s; -ms-animation-duration: 4s; -ms-animation-name: cube-six; -ms-animation-iteration-count: 1; -ms-animation-timing-function: ease; -ms-animation-delay: 0s; -o-animation-duration: 4s; -o-animation-name: cube-six; -o-animation-iteration-count: 1; -o-animation-timing-function: ease; -o-animation-delay: 0s; animation-duration: 4s; animation-name: cube-six; animation-iteration-count: 1; animation-timing-function: ease; animation-delay: 0s; } @-moz-keyframes cube { 0% { -moz-transform: rotateY(0deg) rotateX(0deg) rotateZ(0deg); } 20% { -moz-transform: rotateY(30deg) rotateX(180deg) rotateZ(72deg); } 40% { -moz-transform: rotateY(60deg) rotateX(230deg) rotateZ(144deg); } 60% { -moz-transform: rotateY(90deg) rotateX(280deg) rotateZ(236deg); } 80% { -moz-transform: rotateY(180deg) rotateX(300deg) rotateZ(298deg); } 100% { -moz-transform: rotateY(360deg) rotateX(360deg) rotateZ(360deg); } } @-moz-keyframes cube-two { 0% { -moz-transform: rotateX(0deg); } 100% { -moz-transform: rotateX(-90deg); } } @-moz-keyframes cube-three { 0% { -moz-transform: rotateY(0deg); } 100% { -moz-transform: rotateY(-90deg); } } @-moz-keyframes cube-four { 0% { -moz-transform: rotateY(0deg); } 100% { -moz-transform: rotateY(90deg); } } @-moz-keyframes cube-five-six { 0% { -moz-transform: rotateX(0deg); } 100% { -moz-transform: rotateX(90deg); } } @-moz-keyframes cube-six { 0% { -moz-transform: rotateX(0deg); } 100% { -moz-transform: rotateX(90deg); } } @-webkit-keyframes cube { 0% { -webkit-transform: rotateY(0deg) rotateX(0deg) rotateZ(0deg); } 20% { -webkit-transform: rotateY(30deg) rotateX(180deg) rotateZ(72deg); } 40% { -webkit-transform: rotateY(60deg) rotateX(230deg) rotateZ(144deg); } 60% { -webkit-transform: rotateY(90deg) rotateX(280deg) rotateZ(236deg); } 80% { -webkit-transform: rotateY(180deg) rotateX(300deg) rotateZ(298deg); } 100% { -webkit-transform: rotateY(360deg) rotateX(360deg) rotateZ(360deg); } } @-webkit-keyframes cube-two { 0% { -webkit-transform: rotateX(0deg); } 100% { -webkit-transform: rotateX(-90deg); } } @-webkit-keyframes cube-three { 0% { -webkit-transform: rotateY(0deg); } 100% { -webkit-transform: rotateY(-90deg); } } @-webkit-keyframes cube-four { 0% { -webkit-transform: rotateY(0deg); } 100% { -webkit-transform: rotateY(90deg); } } @-webkit-keyframes cube-five-six { 0% { -webkit-transform: rotateX(0deg); } 100% { -webkit-transform: rotateX(90deg); } } @-webkit-keyframes cube-six { 0% { -webkit-transform: rotateX(0deg); } 100% { -webkit-transform: rotateX(90deg); } } @-o-keyframes cube { 0% { -o-transform: rotateY(0deg) rotateX(0deg) rotateZ(0deg); } 20% { -o-transform: rotateY(30deg) rotateX(180deg) rotateZ(72deg); } 40% { -o-transform: rotateY(60deg) rotateX(230deg) rotateZ(144deg); } 60% { -o-transform: rotateY(90deg) rotateX(280deg) rotateZ(236deg); } 80% { -o-transform: rotateY(180deg) rotateX(300deg) rotateZ(298deg); } 100% { -o-transform: rotateY(360deg) rotateX(360deg) rotateZ(360deg); } } @-o-keyframes cube-two { 0% { -o-transform: rotateX(0deg); } 100% { -o-transform: rotateX(-90deg); } } @-o-keyframes cube-three { 0% { -o-transform: rotateY(0deg); } 100% { -o-transform: rotateY(-90deg); } } @-o-keyframes cube-four { 0% { -o-transform: rotateY(0deg); } 100% { -o-transform: rotateY(90deg); } } @-o-keyframes cube-five-six { 0% { -o-transform: rotateX(0deg); } 100% { -o-transform: rotateX(90deg); } } @-o-keyframes cube-six { 0% { -o-transform: rotateX(0deg); } 100% { -o-transform: rotateX(90deg); } } @keyframes cube { 0% { -webkit-transform: rotateY(0deg) rotateX(0deg) rotateZ(0deg); -moz-transform: rotateY(0deg) rotateX(0deg) rotateZ(0deg); -ms-transform: rotateY(0deg) rotateX(0deg) rotateZ(0deg); -o-transform: rotateY(0deg) rotateX(0deg) rotateZ(0deg); transform: rotateY(0deg) rotateX(0deg) rotateZ(0deg); } 20% { -webkit-transform: rotateY(30deg) rotateX(180deg) rotateZ(72deg); -moz-transform: rotateY(30deg) rotateX(180deg) rotateZ(72deg); -ms-transform: rotateY(30deg) rotateX(180deg) rotateZ(72deg); -o-transform: rotateY(30deg) rotateX(180deg) rotateZ(72deg); transform: rotateY(30deg) rotateX(180deg) rotateZ(72deg); } 40% { -webkit-transform: rotateY(60deg) rotateX(230deg) rotateZ(144deg); -moz-transform: rotateY(60deg) rotateX(230deg) rotateZ(144deg); -ms-transform: rotateY(60deg) rotateX(230deg) rotateZ(144deg); -o-transform: rotateY(60deg) rotateX(230deg) rotateZ(144deg); transform: rotateY(60deg) rotateX(230deg) rotateZ(144deg); } 60% { -webkit-transform: rotateY(90deg) rotateX(280deg) rotateZ(236deg); -moz-transform: rotateY(90deg) rotateX(280deg) rotateZ(236deg); -ms-transform: rotateY(90deg) rotateX(280deg) rotateZ(236deg); -o-transform: rotateY(90deg) rotateX(280deg) rotateZ(236deg); transform: rotateY(90deg) rotateX(280deg) rotateZ(236deg); } 80% { -webkit-transform: rotateY(180deg) rotateX(300deg) rotateZ(298deg); -moz-transform: rotateY(180deg) rotateX(300deg) rotateZ(298deg); -ms-transform: rotateY(180deg) rotateX(300deg) rotateZ(298deg); -o-transform: rotateY(180deg) rotateX(300deg) rotateZ(298deg); transform: rotateY(180deg) rotateX(300deg) rotateZ(298deg); } 100% { -webkit-transform: rotateY(360deg) rotateX(360deg) rotateZ(360deg); -moz-transform: rotateY(360deg) rotateX(360deg) rotateZ(360deg); -ms-transform: rotateY(360deg) rotateX(360deg) rotateZ(360deg); -o-transform: rotateY(360deg) rotateX(360deg) rotateZ(360deg); transform: rotateY(360deg) rotateX(360deg) rotateZ(360deg); } } @keyframes cube-two { 0% { -webkit-transform: rotateX(0deg); -moz-transform: rotateX(0deg); -ms-transform: rotateX(0deg); -o-transform: rotateX(0deg); transform: rotateX(0deg); } 100% { -webkit-transform: rotateX(90deg); -moz-transform: rotateX(90deg); -ms-transform: rotateX(90deg); -o-transform: rotateX(90deg); transform: rotateX(90deg); } } @keyframes cube-three { 0% { -webkit-transform: rotateY(0deg); -moz-transform: rotateY(0deg); -ms-transform: rotateY(0deg); -o-transform: rotateY(0deg); transform: rotateY(0deg); } 100% { -webkit-transform: rotateY(90deg); -moz-transform: rotateY(90deg); -ms-transform: rotateY(90deg); -o-transform: rotateY(90deg); transform: rotateY(90deg); } } @keyframes cube-four { 0% { -webkit-transform: rotateY(0deg); -moz-transform: rotateY(0deg); -ms-transform: rotateY(0deg); -o-transform: rotateY(0deg); transform: rotateY(0deg); } 100% { -webkit-transform: rotateY(-90deg); -moz-transform: rotateY(-90deg); -ms-transform: rotateY(-90deg); -o-transform: rotateY(-90deg); transform: rotateY(-90deg); } } @keyframes cube-five-six { 0% { -webkit-transform: rotateX(0deg); -moz-transform: rotateX(0deg); -ms-transform: rotateX(0deg); -o-transform: rotateX(0deg); transform: rotateX(0deg); } 100% { -webkit-transform: rotateX(-90deg); -moz-transform: rotateX(-90deg); -ms-transform: rotateX(-90deg); -o-transform: rotateX(-90deg); transform: rotateX(-90deg); } } @keyframes cube-six { 0% { -webkit-transform: rotateX(0deg); -moz-transform: rotateX(0deg); -ms-transform: rotateX(0deg); -o-transform: rotateX(0deg); transform: rotateX(0deg); } 100% { -webkit-transform: rotateX(-90deg); -moz-transform: rotateX(-90deg); -ms-transform: rotateX(-90deg); -o-transform: rotateX(-90deg); transform: rotateX(-90deg); } }
1
2
3
4
5
6
Firefox/Chromeでは動作確認済み。Operaはtransformの3Dが未対応なので、動作しません。IE10でも動きますが、何か変…
sassのコードは下記のような感じ。
1 | @import "compass/css3/box-sizing"; |
vendor prefixのせいもありやたら長いですが、やっていることは全体をてきとうに回転させつつ、サイコロの各面の要素を90度に回転させているだけです。あとは、各面の接しているところが離れないようにtransform-originを設定していたりとか、「5」と「6」は二面を90度に曲げたあとに「6」だけさらに90度曲げるために、five-sixという親divを用意してそこに3D rendering contextを別途生成しています。でも、そのくらい。
という感じ。実用的かどうかはさておき、いつの間にかCSSだけでここまでできるようになっていて、いろいろすごい。隔世の感があります。
CSS Transforms 関連記事
- CSS Transforms: transform
- CSS Transforms: transform-origin
- CSS Transforms: perspective
- CSS Transforms: 3D rendering context (transform-style)
- CSS Transforms: backface-visibility
var dice = document.getElementById(‘dice’); dice.addEventListener(‘touchstart’,function(e){ e.preventDefalt(); e.stopPropagation(); dice.className = ‘dice dice-active’; }); dice.addEventListener(‘touchend’,function(e){ dice.className = ‘dice’; });