はじめに
書籍「話を聞かない男、地図が読めない女」に掲載されている診断テストを、JavaScriptとWordPressを使ってWebアプリケーション化しました。30問の質問に答えるだけで、あなたの思考パターンを分析できる診断システムです。
本記事について
今回の診断テスト開発およびこの記事執筆は、Claude(Anthropic社のAI)との協業で進めました。AI時代の新しい開発スタイルの実践例として参考になれば幸いです。
この記事で分かること
- HTML/CSS/JavaScriptによる診断テストの実装方法
- WordPressのAJAX機能を使った利用回数カウンター機能
- レスポンシブ対応の診断UIの作り方
- スコア計算ロジックとリアルタイム結果表示
この記事の対象者
- JavaScript初心者から中級者
- WordPressでインタラクティブなコンテンツを作りたい方
- 診断系Webアプリに興味があるエンジニア
動作環境・使用技術
- HTML5 / CSS3 / Vanilla JavaScript
- WordPress 6.8.1
- Lightning テーマ 15.29.11
- レスポンシブデザイン対応
自己紹介
エンジニア/マーケターとして、クライアントの「こうしたい」をITとマーケの両視点から形にしています。最近は思想駆動型サービス開発の第一人者として、AIを活用した社会風刺的なサービス開発にも取り組んでいます。
完成品・デモ
まずは実際の動作をご覧ください:
実装した機能:
- 30問の選択式質問
- リアルタイム進捗表示
- 自動スコア計算
- 詳細結果解説
- 累計利用回数カウンター
- レスポンシブ対応
技術構成
使用した技術スタックは以下の通りです:
フロントエンド:
- HTML5(セマンティックなマークアップ)
- CSS3(フレックスボックス、グラデーション)
- Vanilla JavaScript(軽量実装)
バックエンド:
- WordPress(CMS基盤)
- PHP(AJAX処理)
- WordPress AJAX API(利用回数管理)
実装手順
1. 環境構築
WordPressの固定ページエディターで、カスタムHTMLブロックを使用して実装しました。プラグインを使わずに、コア機能だけで動作させています。
2. 基本HTML構造
診断テストの基本構造です:
<div class="brain-test-container">
<div id="progress-bar" class="progress-bar"></div>
<h2>男脳・女脳 診断テスト</h2>
<!-- 累計使用回数表示 -->
<div class="usage-stats">
<p class="total-usage">累計診断回数: <span id="total-count">読み込み中...</span>回</p>
</div>
<!-- 性別選択 -->
<div class="gender-select question">
<h3>性別を選んでください</h3>
<label><input type="radio" name="gender" value="male" required> 男性</label>
<label><input type="radio" name="gender" value="female" required> 女性</label>
</div>
<!-- 質問コンテナ -->
<div id="questions-container">
<!-- 30問の質問がここに入る -->
</div>
<!-- 結果表示エリア -->
<div id="score-display" class="score-display">
<h3>テスト結果</h3>
<p>合計点: <span id="score">0</span>点</p>
<div id="score-explanation">
<!-- 詳細解説がここに表示される -->
</div>
</div>
<button onclick="calculateScore()" class="score-button">採点する</button>
</div>
3. スタイリング
レスポンシブ対応とユーザビリティを重視したCSS:
.brain-test-container {
max-width: 800px;
margin: 0 auto;
font-family: sans-serif;
padding: 15px;
}
/* 累計使用回数表示のスタイル */
.usage-stats {
text-align: center;
margin: 15px 0 25px 0;
padding: 12px;
background: linear-gradient(135deg, #f3e7ff, #e8d5ff);
border-radius: 8px;
border: 2px solid #9b59b6;
box-shadow: 0 2px 8px rgba(155, 89, 182, 0.1);
}
.question {
margin-bottom: 20px;
padding: 15px;
border: 1px solid #ddd;
border-radius: 8px;
background: #fff;
}
.question label {
display: block;
margin: 10px 0;
padding: 10px;
border-radius: 4px;
cursor: pointer;
}
.question label:hover {
background: #f5f5f5;
}
/* 固定ボタンのスタイル */
.score-button {
position: fixed;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
padding: 15px 30px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 25px;
font-size: 16px;
cursor: pointer;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
z-index: 1000;
}
/* プログレスバー */
.progress-bar {
position: fixed;
top: 0;
left: 0;
width: 0%;
height: 4px;
background: #4CAF50;
transition: width 0.3s ease;
z-index: 1000;
}
4. JavaScriptロジック
スコア計算と結果表示の核となるJavaScript:
// ページ読み込み時に累計カウント表示
document.addEventListener('DOMContentLoaded', function() {
loadCurrentCount();
});
// 累計カウント数を取得して表示
function loadCurrentCount() {
fetch('/wp-admin/admin-ajax.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'action=brain_test_get_count'
})
.then(response => response.text())
.then(count => {
document.getElementById('total-count').textContent = count;
})
.catch(error => {
console.error('カウント取得エラー:', error);
document.getElementById('total-count').textContent = '0';
});
}
// カウンターを更新する関数
function updateUsageCounter() {
fetch('/wp-admin/admin-ajax.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'action=brain_test_counter'
})
.then(response => response.text())
.then(count => {
document.getElementById('total-count').textContent = count;
// カウント更新時のアニメーション効果
const countElement = document.getElementById('total-count');
countElement.style.transform = 'scale(1.2)';
countElement.style.transition = 'transform 0.3s ease';
setTimeout(() => {
countElement.style.transform = 'scale(1)';
}, 300);
})
.catch(error => {
console.error('カウンター更新エラー:', error);
});
}
// メインのスコア計算関数
function calculateScore() {
var score = 0;
var answeredQuestions = 0;
// 全30問をループで処理
for(var i = 1; i <= 30; i++) {
var radios = document.getElementsByName('q' + i);
var answered = false;
for(var j = 0; j < radios.length; j++) {
if(radios[j].checked) {
answered = true;
// スコア計算ロジック
switch(radios[j].value) {
case 'a':
score += 10;
break;
case 'b':
score += 5;
break;
case 'c':
score -= 5;
break;
}
}
}
if(answered) {
answeredQuestions++;
}
}
// 採点成功時にカウンターを更新
updateUsageCounter();
// 結果表示
displayResults(score, answeredQuestions);
}
// 結果表示関数
function displayResults(score, answeredQuestions) {
var display = document.getElementById('score-display');
var scoreSpan = document.getElementById('score');
var brainType = document.getElementById('brain-type');
// 脳タイプの判定ロジック
var typeText = "";
if (score < 150) {
typeText = "あなたは【男脳タイプ】です。";
} else if (score <= 180) {
typeText = "あなたは【バランス型】です。";
} else {
typeText = "あなたは【女脳タイプ】です。";
}
display.style.display = 'block';
scoreSpan.textContent = score;
brainType.textContent = typeText;
}
5. WordPress側のPHP実装
JavaScript側のAJAX通信を受け取るため、functions.phpに以下を追加しました:
// AJAX ハンドラー関数
function brain_test_counter_increment() {
$count = get_option('brain_test_usage_count', 0);
$count++;
update_option('brain_test_usage_count', $count);
wp_die($count);
}
function brain_test_counter_get() {
$count = get_option('brain_test_usage_count', 0);
wp_die($count);
}
// AJAX アクション登録
add_action('wp_ajax_brain_test_counter', 'brain_test_counter_increment');
add_action('wp_ajax_nopriv_brain_test_counter', 'brain_test_counter_increment');
add_action('wp_ajax_brain_test_get_count', 'brain_test_counter_get');
add_action('wp_ajax_nopriv_brain_test_get_count', 'brain_test_counter_get');
実装のポイント:
-
wp_ajax_nopriv_でログインしていないユーザーからもアクセス可能 -
get_option()/update_option()でWordPressの設定テーブルを活用 -
wp_die()でレスポンス終了(WordPressのベストプラクティス)
工夫したポイント・苦労した点
1. ユーザーエクスペリエンスの最適化
固定ボタンによる操作性向上:
30問すべて回答後、画面をスクロールすることなく採点できるよう、採点ボタンを画面下部に固定配置しました。
視覚的フィードバック:
利用回数更新時にアニメーション効果を追加し、アクションが実行されたことをユーザーに分かりやすく伝えています。
2. WordPress AJAX連携
データ永続化の実装:
WordPressのwp_optionsテーブルを使用してカウンターデータを永続化しました。テーマ変更やプラグイン更新の影響を受けない安全な実装です。
エラーハンドリング:
ネットワークエラーやサーバーエラーが発生した場合でも、診断機能自体は継続して利用できるよう設計しています。
3. パフォーマンス最適化
Vanilla JavaScript採用:
jQueryを使わずにVanilla JavaScriptで実装し、軽量化を図りました。外部ライブラリ依存を避けることで、読み込み速度も向上しています。
非同期処理:
カウンター更新処理を非同期で実行し、ユーザーの診断体験を阻害しないよう配慮しました。
まとめ
書籍の診断テストをWeb化することで、紙ベースでは実現できなかった以下の価値を提供できました:
- 自動採点機能による即座の結果表示
- リアルタイムカウンターによる社会的証明の可視化
- レスポンシブ対応による多デバイス対応
- シェア機能による拡散性の向上
単純な機能ながら、ユーザビリティとエンターテイメント性を両立させた実装となりました。
WordPressとJavaScriptの連携パターンとしても参考になる事例だと思います。診断系コンテンツやインタラクティブなWebアプリケーション開発の参考になれば幸いです。
参考リンク
参考書籍
📚 話を聞かない男、地図が読めない女
アラン・ピーズ (著), バーバラ・ピーズ (著), 藤井 留美 (翻訳)
この書籍の診断テストを元に今回のWebアプリケーションを開発しました。男女の脳の違いについて科学的な観点から解説されており、非常に興味深い内容です。
