jsPsychで待機画面（スピン）を表示する方法

[jsPsych](https://www.jspsych.org/v7/)で待機画面（以下、スピン）を表示する方法について解説します。jsPsychのバージョンは7で動作確認をしています。（2024年11月現在、バージョン8が最新）

# そもそもスピンとは？
こういう画面です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495823/aa2d58dc-7ac9-f64e-8ae9-23dd622516f5.png)

# 何のために？
オンライン実験中に、誰かと仮想的につながる（マッチング）感を出したいときなどに使えそうです。つまり、雰囲気です！

# 使用したライブラリー
spin.jsです。

https://spin.js.org/

上記サイト内に `opt` として見た目のサンプルが書かれてあり、基本的にはこれをそのまま使用できます（ただし、jsPsychで使う場合、colorを黒 #000000 に変更したほうがよい）。もっとこだわりたい方は、以下の図を参照してください。URL部分を参照して、`opt`の内容を書き換えればOK！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495823/f8c6664d-579c-4e10-f981-111e4a9bc78b.png)

# spin.jsのインストール
本来は、npmを使用するほうがよいと思いますが、jsPsychを使って実験を行いたいという多くの人は、npmを使っていないと思います。以下の画像を参考に、spin.umd.jsとspin.cssの２つのファイルをダウンロードして、実験プログラムと同じ場所に保存してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495823/1fa33a4f-bb1e-6287-4276-962ce636f59e.png)

# サンプルコード

以上で準備は完了しました。以下のコードでスピンが表示されるはずです。ヘッダー部分で、ダウンロードした２つのファイルを読み込むのを忘れずに。

[on_load 関数](https://www.jspsych.org/v7/overview/events/#on_load)を使用して、spin_trialが呼び出されたときにスピンを表示しています。スピンを停止するためのstop関数もありますが、jsPsychでは次の画面に移ったときにスピンのデータが消去されて結果的に止まるため、明記はしていません。

```html
<!DOCTYPE html>
<html>
  <head>
    <script src="./spin.umd.js"></script>
    <script src="https://unpkg.com/jspsych@7.3.4"></script>
    <script src="https://unpkg.com/@jspsych/plugin-html-keyboard-response@1.1.3"></script>
    <script src="https://unpkg.com/@jspsych/plugin-html-button-response@1.2.0"></script>
    <link href="https://unpkg.com/jspsych@7.3.4/css/jspsych.css" rel="stylesheet" type="text/css" />
    <link href="spin.css" rel="stylesheet" type="text/css" />
  </head>
  </head>
  <body></body>
  <script>

    // 待機画面（スピン）をjsPsychで表示する方法について解説しています。 https://spin.js.org/　を使用しました。

  const jsPsych = initJsPsych({
    on_finish: function() {
      jsPsych.data.displayData();
    }
  });

  // スピンの見た目。jsPsychでは背景のデフォルトが白なので、colorを黒に変更しています。
  const opts = {
    lines: 14, // The number of lines to draw
    length: 38, // The length of each line
    width: 17, // The line thickness
    radius: 45, // The radius of the inner circle
    scale: 1, // Scales overall size of the spinner
    corners: 1, // Corner roundness (0..1)
    speed: 1, // Rounds per second
    rotate: 0, // The rotation offset
    animation: 'spinner-line-fade-quick', // The CSS animation name for the lines
    direction: 1, // 1: clockwise, -1: counterclockwise
    // color: '#ffffff', // CSS color or array of colors
    color: '#000000', // jsPsychで見えやすくするため
    fadeColor: 'transparent', // CSS color or array of colors
    top: '50%', // Top position relative to parent
    left: '50%', // Left position relative to parent
    shadow: '0 0 1px transparent', // Box-shadow for the lines
    zIndex: 2000000000, // The z-index (defaults to 2e9)
    className: 'spinner', // The CSS class to assign to the spinner
    position: 'absolute', // Element positioning
  };

  const timeline = [];

  const stroop = { //ストループ課題
    type: jsPsychHtmlButtonResponse,
    stimulus: '<p style="color: red; font-size: 48px; font-weight: bold;">GREEN</p>',
    choices: ['Green', 'Blue', 'Red'],
    button_layout: "flex",
    prompt: "<p>What color is this word? (flex layout)</p>",
  }

  timeline.push(stroop); // スピン前

  const spin_trial = { // 待機画面
    type: jsPsychHtmlKeyboardResponse,
    stimulus: '<p>Loading...</p>',
    choices: "NO_KEYS",
    trial_duration: 3000, // スピンが回る時間
    on_load: function(){ // https://www.jspsych.org/v7/overview/events/#on_load
      const target = document.getElementById('jspsych-content');
      const spinner = new Spin.Spinner(opts).spin(target); // スピンの表示が始まる
    }
  };      
  timeline.push(spin_trial)

  timeline.push(stroop); // スピン後（スピンは自動で止まります）

  jsPsych.run(timeline);

  </script>
</html>

```