予言通りにカードを当てるマジックアプリ

クソアプリAdvent Calendarの13日目です。

# Webサイトでカードマジックをする

筆者は趣味でよくカードマジックをやります。
トランプの技法を練習して、難しかったトリックができたときなんかは、
すごく達成感を感じます。


一言にカードマジックといっても、
技法を多用するものから、「セルフワーキング」といって「この通りにカードを配ると自動的にそういう現象が起こる」というものもあります。つまり、技術がなくても実施できるマジックはたくさんあるのです。

今日は、そんな技術のいらないカードマジックをわざわざWebの技術を使って再現してみました。

## You Will Take a Red Card

先にプレイしたい方はここからどうぞ
[デモサイト](https://shinya.github.io/numbers-chosen/index.html)

![capture 2020-12-13 19.45.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72413/688c9276-7a4e-3d15-01f9-b9ddb8c91200.png)

あなたは、1〜6のうち好きな数字を選びます。
すると、予言どおりにあなたの選んだ数字が赤いカードを導き出します。

結論から先にいうと、提示された数字のうちどれを選んでも、
あなたは赤いカードを選んでしまうというものです。

そんなばかな・・・

と思ってやってみるとあら不思議。
必ずあなたは赤いカードを選んでしまいます。


## 種明かし

これは、かの有名なマジシャン「ダイ・バーノン」が考案した
「You Will Take a Red Card」（あなたは赤いカードを選ぶ）
というマジックです。

何度かプレイをしているとさすがに気づくと思うのですが、
これは選んだ数字の意味がマジシャン側（＝アプリ側）によって変えられる側面を持っています。

なんの数字を選んでも「裏地が赤のカード」か「ダイヤの6」を選ばされるようになっています。

ちゃんちゃん

# 技術的なこと

ソースコードはここに→ [Github](https://github.com/shinya/numbers-chosen)


筆者は古き技術しか知らないエンジニアであり、最近のReactJSとかはてんでわかりません。
そのため、古代の技術「jQuery」を使って構築をしました。

CSSのアニメーション機能を使って、ひっくり返すエフェクトを使っています。

ちなみに画像の名前についている `face` というのは数字が書いてある方で、
`back` というのは裏の柄が描かれている方を指します。

```html
    <div class="card-box">
        <div class="wrapper">
            <img src="images/back-1.png" id="no1-back" class="card active">
            <img src="images/face-4.png" id="no1-face"  class="card">
        </div>
        <div class="wrapper">
            <img src="images/face-a.png" class="card active" id="no2-back">
            <img src="images/back-2.png" class="card" id="no2-face">
        </div>
        <div class="wrapper" id="w3">
            <img src="images/back-1.png" class="card active" id="no3-back">
            <img src="images/face-6.png" class="card" id="no3-face">
        </div>
        <div class="wrapper">
            <img src="images/face-5.png" class="card active" id="no4-back">
            <img src="images/back-1.png" class="card" id="no4-face">
        </div>
        <div class="wrapper">
            <img src="images/back-1.png" class="card active" id="no5-back">
            <img src="images/face-3.png" class="card" id="no5-face">
        </div>
        <div class="wrapper">
            <img src="images/face-2.png" class="card active" id="no6-back">
            <img src="images/back-1.png" class="card" id="no6-face">
        </div>
    </div>
```

表のカードと裏のカードがそれぞれ `card` というクラスに属しており、
またその2つのカードを `wrapper` というdivタグで囲み、
その中でアニメーションと一緒にz-indexを入れ替えています。

```css:base.css
.wrapper {
	display: inline-block;
	width: 200px;
	position: relative;
	-webkit-transform: rotateY(0deg);
	-ms-transform: rotateY(0deg);
	transform: rotateY(0deg);
}
.wrapper.animate {
	-webkit-transition: 0.5s linear;
	-ms-transition: 0.5s linear;
	transition: 0.5s linear;
	-webkit-transform: rotateY(90deg);
	-ms-transform: rotateY(90deg);
	transform: rotateY(90deg);
}
.wrapper.animateEnd {
	-webkit-transition: 0.5s linear;
	-ms-transition: 0.5s linear;
	transition: 0.5s linear;
	-webkit-transform: rotateY(180deg);
	-ms-transform: rotateY(180deg);
	transform: rotateY(180deg);
}
```

```css
.card {
	position: absolute;
	display: inline-block;
	width: 200px;
	visibility: hidden;
	z-index: 1;
}
.card.animate {
	visibility: visible;
	z-index: 1;
}
.card.active {
	visibility: visible;
	z-index: 2;
}
.wrapper.animateEnd .card.active {
	-webkit-transform: scale(-1, 1);
	-ms-transform: scale(-1, 1);
	transform: scale(-1, 1);
}
```

Javascript（jQuery）の処理で、この `animate` のクラスを付け替えることにより、
ひっくり返るアニメーションを実現しています。
（下記の参考サイトからまんま利用させてもらっています。ありがとうございます。）

```javascript:main.js
var flipCard = function(target){
	var $currentElm = $('#no' + target + '-back');
	var $targetElm = $('#no' + target + '-face');
	var parent = $currentElm.parent();

	parent.addClass("animate");
	$targetElm.addClass("animate");
	var timer = setTimeout(function() {
		$currentElm.removeClass("active").addClass("animate");
		$targetElm.removeClass("animate").addClass("active");
		parent.removeClass("animate").addClass("animateEnd");
		var timer = setTimeout(function() {
			parent.removeClass("animateEnd");
			$currentElm.removeClass("animate");
			parent.removeClass("animate");
		}, 500);
	}, 500);
	return false;
};
```

# 結論

このマジックはトランプを使ってやるから、面白いのであり、
また
【予言の書を予め封筒に入れておくなどして、相手が選んだあとに見せるから効果がある】
というのが一番見せ所であります。
オンラインのWebサイトでやったところで、なんの面白みもないですね。

トランプの画像をIllustratorで作ってるのに一番時間を費やした気がします。
この記事を見たみなさんは、ぜひ **実際のトランプで** お子さんなどに実演してあげてください。

## あとがき

スマホで見た時にレイアウトが崩れるので、後ほど修正します。

## 参考サイト

* [CSS3のtransform3dとjQueryを使って、ひっくり返すアニメーション](https://sterfield.co.jp/designer/css3%E3%81%AEtransform3d%E3%81%A8jquery%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%80%81%E3%81%B2%E3%81%A3%E3%81%8F%E3%82%8A%E8%BF%94%E3%81%99%E3%82%A2%E3%83%8B%E3%83%A1%E3%83%BC%E3%82%B7%E3%83%A7/)
* 手品のアイデア
    * http://www.clio.ne.jp/home/hashiba/tane22.htm