Open26
Nuxt3で少し特殊なアンケートフォームを作る
ピン留めされたアイテム
自己紹介
- 高校二年生
- 都内の中高一貫に通っている
- 部活:科学
やりたいこと
アンケートフォームを作る
調査したい内容
色の組み合わせが、見分けやすさに与える影響について
もっとくわしく
なぜNuxt?
つかったことがあるから
なんのため?
学校の課題
どこが特殊?
- 普通のアンケート
- 「○○」について賛成ですか、反対ですか
- あなたは、「○○」という単語を聞いたことがありますか
- 「○○」という政策は必要だと思いますか?
- 今回の調査
- この色の組み合わせは、見やすいですか?
色の見分けやすさを調べる。誰がやってもそんなに結果わからないはず。自分だけを対象とした調査としてもよいが、時間がかかりすぎる。みんなに分担してもらいたい
結局
本当に分析に必要なデータは、数人の協力者に頼むことにする。途中で回答をやめてしまうかもしれない
アンケートの実施目的は、『「数人の協力者」と「学校に通う多数の生徒」の、色の感じ方に有意な差が存在しないことを示すため』
作りたいもの
ユーザー視点
- トップページひらく
- 初めて開いた人は、調査について説明するページに転送
- 「同意」をタップすると、調査の一覧ページが開く
- 調査の一覧から、回答したいものを選択
- 画面に、二種類の色の組み合わせが表示される
- 「見やすい」~「見にくい」の4段階から選択
- 次の色の組み合わせが表示される
- 5~7をくりかえす
- すべての色の組み合わせについて回答し終わると、調査の一覧ページに戻る
ページ別
- トップページ
- 調査の一覧が並ぶ
- 調査について説明し、同意を求めるページ
- 実際に調査を行うページ
コンポーネント別
- ヘッダー
- 「?」アイコンで、調査について説明するモーダルが開く
- データは、同意を求めるためのページと同じところから取ってきたい
- 調査一覧ページにならぶボタン
- 調査について少しだけ説明する
- 調査一覧ページで
v-for
で並べる
- 調査時に色を表示
- 調査時に文字を表示
- 「背景」と「その上に表示された文字」の色を変化させ、文字が読みやすいか調査
- 調査時に、見分けやすさを選択するボタン
- スマホでも簡単に押せるようにしたい
- いろんなところでつかう、モーダルウィンドウ
- 「調査への協力ありがとう」
- 「この調査では、こんなことをします。この条件に同意する必要があります」
データの保存
GASにPOSTを送信する。
参考
本当にできるのか?
GASでLINE Botを作ったことがあるからいけるはず
実装したコード
main.gs
function doGet(e) {
return HtmlService.createHtmlOutput("論文アンケート")
}
function doPost(e) {
const dataArray = e.postData.contents.split(",");
ContentService.createTextOutput(JSON.stringify(e));
SaveData(dataArray);
return ContentService.createTextOutput(JSON.stringify(dataArray));
}
function SaveData(data) {
// dataの0番目には、シートの名前が入っている
try {
let sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(data[0]);
let dataSplice = data.splice(0, 1, Utilities.getUuid(),Utilities.formatDate(new Date(), 'JST', 'yyyy-MM-dd HH:mm:ss'));
// 一番下にデータを追加
sheet.appendRow(data);
} catch {
throw new Error("関数SaveDataで、エラーが発生しました");
}
}
データの構造をどうしよう
調査するための色のデータ
何パターンかに対応する必要がある
調査で質問する時に使うデータ
- 色の id、コードの組み合わせ
- 質問項目では、色のコードを名前で指定したい。設定ミスを防ぐため
これは、すべての調査で共通化すればよいのでは?\rightarrow
- 質問項目では、色のコードを名前で指定したい。設定ミスを防ぐため
- 調査の種類
- 色を二色見比べるもの、背景色と文字の色の組み合わせを評価するもの
- 何問あるのか
調査終了時、ブラウザからGASに送るデータ
- 調査のID
- その人が何回目に調査に回答したか
- 回答データ
- 色の組み合わせに名前を付けたもの(名前は数値にしようかな)
とりあえず書いてみる
{
"research-id": "01020303", //
"data": {
"colors": [
//色の組み合わせを、表を使って表現する(対戦表みたいな感じ)。その場所を、数値を使って指定する感じ
[1, 1, 1],
[1, 1, 2],
[1, 1, 3],
[1, 1, 4],
[1, 1, 5],
[1, 1, 6],
[1, 2, 1]
// 以下たくさん続く
]
}
}
現時点での構成
- アクセスしたら,Cookieの有無をしらべ,なかったら
/about
へ転送 -
/about
で,アンケート調査について説明する - 「同意」ボタンをクリックしたら,Cookieをセットしトップページへ転送
実装したコード
about.vue
<!-- アンケート調査について説明するページ -->
<template>
<p class="text-h4 mb-8 text-center">この調査について</p>
<!-- いろいろせつめいする -->
<div class="my-7">
<v-btn class="bg-primary mx-auto" to="/" @click="click">
アンケートに解答する
</v-btn>
</div>
</template>
<script setup>
const cookie = useCookie("visited", { maxAge: 60 * 60 * 24 * 30 * 2 });
function click() {
cookie.value = true;
}
</script>
index.vue
<!-- トップページ -->
<template>
<!-- アンケート調査のリンク -->
</template>
<script setup>
definePageMeta({
middleware: [
function (to, from) {
if (!useCookie("visited").value) {
return navigateTo("/about");
}
},
],
});
</script>
困ったところ
-
useCookie()
の有効期限の指定方法
ちゃんと,
maxAge Specifies the number (in seconds) to be the value for the Max-Age Set-Cookie attribute.
って書いてあった。秒数で指定する。
- Cookieを取得する方法
useCookie("visited").value
の.value
が抜けていた。
参考
- トップページに来たら,調査のリンクが二つ。
- 色の見分けやすさ
- 色の組み合わせの感じ方
- クリックすると,
/research/[slug]
へ転送
途中まで
components/DisplayColor.vue
<template>
<div :style="colors">
<div class="w-100 color1 h-50 pa-auto">aaa</div>
<div class="w-100 color2 h-50 pa-auto">aaa</div>
</div>
</template>
<style>
.color1 {
background-color: var(--color1);
}
.color2 {
background-color: var(--color2);
}
</style>
<script setup>
const colors = {
"--color1": "#222222",
"--color2": "#777777",
};
</script>
引っかかったところ
-
:style="colors"
の指定(colorsは,変数名と値を指定した配列)
これを指定すると,style="--color1: #222222; --color2: #777777;"
と展開される。
その:style=""
を指定した要素の配下でのみ使用可能
なぜだかわからないが,下のサイトのやり方だとうまくいかなかった
- vuetifyのpadding
ちゃんとドキュメントを読もう!
結局
いろいろ試したら、上記参考サイトのやり方で実装できた
components/DisplayColor.vue
<template>
<div>
{{ type }}
<div class="w-100 color1 pa-auto h-half"></div>
<div class="w-100 color2 h-half pa-auto"></div>
</div>
</template>
<style scoped>
.color1 {
background-color: v-bind(color1);
}
.color2 {
background-color: v-bind(color2);
}
.h-half {
height: 30dvh;
}
</style>
<script setup lang="ts">
interface Props {
type: string | string[];
id: number;
}
interface colorDatas {
type: number;
data: {
color1: string;
color2: string;
};
}
import colorData from "@/assets/json/1.json";
const id = withDefaults(defineProps<Props>(), {
id: 1,
});
const color1 = ref("#222222");
watch(id, (next, prev) => {
color1.value = colorData.data[id.id].color1;
});
const color2 = computed(() => {
return colorData.data[id.id].color2;
});
</script>
watchとcomputed、両方描いてみたけどどっちでもできた
DisplayColor.vue
<script setup lang="ts">
interface Props {
type: string | string[];
id: number;
group_id: number;
}
interface colorDatas {
type: number;
data: {
colorA: string;
colorB: string;
};
}
import colorData2 from "@/assets/json/combination_list.json";
const Props = withDefaults(defineProps<Props>(), {
id: 0,
group_id: 0,
});
const colorA = computed(() => {
const l = colorData2[Props.group_id][Props.id][0][1];
const c = colorData2[Props.group_id][Props.id][0][2];
const h = colorData2[Props.group_id][Props.id][0][0];
return [l + "% " + (c * 134) / 100 + " " + h];
});
const colorB = computed(() => {
const l = colorData2[Props.group_id][Props.id][1][1];
const c = colorData2[Props.group_id][Props.id][1][2];
const h = colorData2[Props.group_id][Props.id][1][0];
return [l + "% " + (c * 134) / 100 + " " + h];
});
</script>
表色系を変更したので,L・c・hそれぞれの値を定義しています。
combination_list.jsonの一部
[
[
[[225,66.6,33.3],[315,33.3,50]],
[[45,66.6,66.6],[135,33.3,50]],
[[135,33.3,66.6],[45,33.3,66.6]],
[[135,50,66.6],[45,50,50]],
[[45,33.3,33.3],[45,50,33.3]],[[45,50,33.3],[315,33.3,33.3]],[[45,33.3,66.6],[45,33.3,33.3]],[[135,33.3,66.6],[135,50,66.6]],[[45,33.3,50],[135,50,50]],[[45,33.3,50],[45,50,66.6]],[[135,33.3,33.3],[135,50,66.6]],[[135,33.3,50],[315,50,66.6]],[[45,50,50],[45,66.6,66.6]],[[135,33.3,66.6],[315,33.3,66.6]],[[135,33.3,66.6],[225,33.3,66.6]],[[135,33.3,50],[45,66.6,66.6]],[[135,33.3,33.3],[45,50,66.6]],[[135,33.3,50],[315,33.3,66.6]],[[45,33.3,50],[45,66.6,50]],[[45,33.3,33.3],[45,50,50]],[[135,33.3,50],[45,33.3,66.6]],[[45,50,50],[45,66.6,33.3]],[[45,33.3,33.3],[225,50,33.3]],[[45,50,33.3],[315,50,50]],[[135,50,33.3],[45,50,33.3]],[[45,50,66.6],[225,33.3,50]],[[135,50,33.3],[135,50,50]],[[45,66.6,33.3],[45,66.6,66.6]],[[45,50,50],[225,66.6,66.6]],[[45,50,50],[225,50,33.3]],[[135,33.3,66.6],[225,33.3,50]],[[135,33.3,66.6],[225,66.6,66.6]],[[135,33.3,50],[225,50,66.6]],[[45,66.6,50],[135,50,33.3]],[[135,50,66.6],[135,66.6,33.3]],[[45,33.3,66.6],[45,66.6,33.3]],[[315,50,50],[135,50,66.6]],[[45,66.6,50],[135,66.6,66.6]],[[315,66.6,33.3],[315,33.3,66.6]],[[45,66.6,50],[45,50,50]],[[225,66.6,66.6],[135,33.3,50]],[[45,50,50],[135,50,33.3]],[[315,33.3,50],[225,66.6,33.3]],[[315,33.3,33.3],[225,66.6,50]],[[135,50,33.3],[45,33.3,66.6]],[[225,66.6,50],[315,50,66.6]],[[225,66.6,50],[45,50,66.6]],[[315,33.3,66.6],[225,33.3,50]],[[225,66.6,50],[135,66.6,50]],[[225,66.6,66.6],[135,33.3,66.6]],[[135,33.3,50],[315,33.3,50]],[[225,66.6,66.6],[45,50,33.3]],[[315,33.3,50],[225,66.6,50]],[[225,66.6,66.6],[315,66.6,50]],[[315,33.3,50],[135,66.6,66.6]],[[135,33.3,33.3],[225,66.6,33.3]],[[45,50,33.3],[315,33.3,66.6]],[[225,66.6,66.6],[225,33.3,50]],[[315,33.3,33.3],[135,66.6,66.6]],[[135,66.6,33.3],[45,50,66.6]],[[315,33.3,33.3],[225,33.3,66.6]],[[315,33.3,66.6],[225,33.3,66.6]],[[45,66.6,50],[45,50,33.3]]
],
['省略'],
['省略'],
]
これで63組の数値のペアがあります。
これが20組あります。
結局
- 36*35 =1260パターンの色の組み合わせを作った。
- 1260÷20=63だから,一人63件ずつ回答してもらうことにした。少なくとも20人にアンケートする。
- だいたい330人くらいの人から,659×63件の回答をもらった。(二つのテーマを合わせて。)
ミス発覚
色のリストを出力するために書いたコードにミスがあった。
8行目にあるカウントの定義が、10行目と11行目の間にあった。
20グループに分類したつもりだったが、すべてのグループの中身が全く同じデータになっていた。