スタイルシート ペントミノ パズル の説明
戻る


JavaScript を使わず,スタイルシートだけでペントミノ パズルを作ってみます.
画面
(これはキャプチャ画像です.これで遊ぶことはできません.)
使い方と仕組みについて説明します.


使い方

12 種類のペントミノのピースを組み合わせて長方形を作ります.
画面上部のラジオ ボタンで長方形の形を選ぶと,選んだ形の長方形が画面中央に表示されます.(これは単なるガイド表示です.これに合わせて並べなくても構いません.)
ペントミノのピースにマウス ポインタを置くと,裏返し,回転,移動のアイコンが表示されます.
アイコンの表示

裏返しアイコン 裏返しアイコン
回転アイコン 回転アイコン
移動アイコン 移動アイコン
裏返しアイコンをクリックするとピースが裏返し(鏡像)になります.
回転アイコンをクリックするとピースが時計回りに 90 度回転します.
移動アイコンをドラッグするとピースが動きます.背景が白の領域の内側に移動アイコンがある範囲で動かすことができます.
組み合わせの例
組み合わせの例

ピースの裏返し/回転の処理

チェック ボックスを使ってピースの裏返しの状態,ラジオ ボタンを使ってピースの回転の状態を保持します.
チェック ボックス/ラジオ ボタンは非表示にしておき,各チェック ボックス/ラジオ ボタンに対してラベル(LABEL 要素)を関連付けます.ラベルにスタイル付けして裏返し/回転のアイコンにしています.

裏返しのチェック ボックスは,裏返すと形が変わる(それを回転しても元と同じ形にはならない)ピースにあります.チェックされていないときが初期表示の状態で,チェックするとピースを裏返します.

回転のラジオ ボタンは,十字の形のピースを除く各ピースに 2 個または 4 個あります.初期表示の状態からそれぞれ 0 度,90 度,180 度,270 度回転した状態に対応します.チェックするとピースを該当する角度に回転します.
回転のラジオ ボタンのラベルは,現在の角度の次の角度に対応するものが表示されます.
回転のラジオ ボタンの説明
たとえば,現在 180 度の回転状態であれば 270 度回転した状態に対応するラベルが表示されます.つまり,ラベルをクリックすると 270 度回転した状態に変わります.

裏返しと回転の表示はアニメーションしています.
transform で裏返しと回転を行っています.
transform:rotate(var(--rotate)) scale3d(var(--mirror), 1, 2);
scale3d() が裏返しの座標変換で rotate() が回転の座標変換です.
カスタム プロパティ --mirror の値は 1 が初期状態で -1 が裏返した状態です.カスタム プロパティ --rotate の値は回転の角度です.
scale3d() は本来は scale() でよいのですが,scale() を使うと Opera で clip-path のエッジがぼけてしまうのです.scale3d() を使うとそれが回避できるので scale3d() を使っています.

--mirror は transition で,--rotate は animation でアニメーションしています.
--rotate に transition を使っていないのは,270 度から 0 度に変わるときに時計回りに回転するようにしたかったためです.transition で 270 度から 0 度へ回転させると反時計回りに 270 度回転してしまいます.時計回りに回転させるためには 270 度から 360 度(または -90 度から 0 度)の回転をさせる必要があります.そのため animation で角度を指定しています.

カスタム プロパティにアニメーションを適用するために,後述のように @ルールの @property でプロパティをアニメーション可能に設定しています.

このあたりは --rotate に transition を使えると,処理がかなり簡単になるのですが.
単に animation を使わなくて済むというだけでなく,--mirror--rotate をアニメーションしなくても transform をアニメーションすればよくなります.
transition:transform 200ms;
その場合,--mirror--rotate をアニメーションしないので,それらを @property で定義する必要もありません.
270 度から 0 度への回転を時計回りにするために,ちょっと処理が面倒になっています.


ピースの移動の処理

ピースを移動する処理のためにボタン(TYPE 属性 BUTTON の INPUT 要素)を使います.ボタンは非表示にしておき,各ボタンに対してラベルを関連付けます.ラベルにスタイル付けして移動のアイコンにしています.

ピースを移動した位置を取得するために,移動できる範囲に位置取得用の要素を敷き詰めます.
位置取得用の要素
要素ひとつの大きさはペントミノの正方形と同じです.初期状態ではこの要素は非表示になっています.

ボタンのラベルの上でマウス ボタンが押下されるとボタンが :active 状態になるので,位置取得用の要素を表示状態にします(透明なので表示状態にしても見えませんが).マウスを動かすとマウス ポインタが載っている位置取得用の要素が :hover 状態になるので,その要素の位置にピースの位置を合わせます.
ピースの移動
これだけだと,位置取得用の要素が :hover 状態でなくなると位置が初期状態に戻ってしまうので,:hover 状態でなくなった後も位置を保持しておくために transition の機能を流用します.
transition では,プロパティの設定値が変更されてから実際に値が変わり始めるまでのディレイを設定できます.ピースの lefttop のプロパティに,このようにディレイを設定します.
transition:left 0s 10000s, top 0s 10000s;
そうすると,位置取得用の要素が :hover 状態でなくなっても,ディレイで指定した時間が経過するまでは元の値が保持されます.ディレイに充分大きな値を指定することで設定した値を保持します.
位置を変更するときには transition を無効にして,値が変わるようにします.


カスタム プロパティの定義

カスタム プロパティ --mirror--rotate を @ルールの @property で定義しています.
@property の定義は,たとえばこのように書きます.
@property --a {
  syntax:'<integer>';
  inherits:true;
  initial-value:0;
}
上述したように,--mirror--rotate にアニメーションを使っています. カスタム プロパティに計算値によるアニメーションを使うためには,プロパティのデータ型を定義する必要があります.
@propertysyntax<number><angle> を指定することで,そのプロパティを計算値によるアニメーション可能にしています.


このおもちゃは Firefox 128 以上および Opera 91 以上用に作っていますが,Google Chrome 107 で動くことが確認できています.Google Chrome の他のバージョンでの動作は未確認です.


戻る