Vue.jsで画像をドラッグアンドドロップで同じカテゴリ同士になるようにする問題を作ってみました。
点数と点数に応じて文言も変わります。
サンプル
HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" />
<link rel="stylesheet" href="./css/narabikae_default.css" />
<title>ドラッグ&ドロップ問題</title>
</head>
<body>
<div id="app" class="container mt-5">
<h1>{{ message }}</h1>
<div class="d-flex justify-content-between bg-dark p-3">
<div class="bg-secondary p-2 m-2 w-100" @drop="dropList($event, 'A')" @dragover.prevent @dragenter.prevent>
<h2 class="text-light">くだもの</h2>
<div class="bg-white m-2 p-2 choice" v-for="(list,index) in CategoryA" draggable
@dragstart="dragList($event,list.id)">
<img :src="list.image_link" />
{{list.name}}
</div>
</div>
<div class="bg-secondary p-2 m-2 w-100" @drop="dropList($event, 'B')" @dragover.prevent @dragenter.prevent>
<h2 class="text-light">どうぶつ</h2>
<div class="bg-white m-2 p-2 choice" v-for="(list,index) in CategoryB" draggable
@dragstart="dragList($event,list.id)">
<img :src="list.image_link" />
{{list.name}}
</div>
</div>
<div class="bg-secondary p-2 m-2 w-100 " @drop="dropList($event, 'C')" @dragover.prevent @dragenter.prevent>
<h2 class="text-light">のりもの</h2>
<div class="bg-white m-2 p-2 choice" v-for="(list,index) in CategoryC" draggable
@dragstart="dragList($event,list.id)">
<img :src="list.image_link" />
{{list.name}}
</div>
</div>
<div class="bg-secondary p-2 m-2 w-100" @drop="dropList($event, 'D')" @dragover.prevent @dragenter.prevent>
<h2 class="text-light">ぜんぶつかってね!</h2>
<div class="bg-white m-2 p-2 choice" v-for="(list,index) in CategoryD" draggable
@dragstart="dragList($event,list.id)">
<img :src="list.image_link" />
{{list.name}}
</div>
</div>
</div>
<div class="answer" v-if="answer.length > 0">
<div v-if="answer == '3'">
すべて使ってください
</div>
<div v-else-if="this.percent_score == 100">
素晴らしい
</div>
<div v-else-if="this.percent_score > 70">
惜しい!
</div>
<div v-else-if="this.percent_score > 50">
もう少し頑張って
</div>
<div v-else-if="this.percent_score > 10">
YBAINE
</div>
<div v-else>
( ^ω^)・・・
</div>
<p v-if="answer != '3'">正答率は{{percent_score}}%</p>
</div>
<div class="endBtn">
<input type="button" value="結果をみる" @click="kekka" />
</div>
</div>
<script src="./js/narabikae_script.js"></script>
</body>
</html>
CSS
.answer {
text-align: center;
font-size: 36px;
padding: 25px 0;
}
.endBtn {
text-align: center;
margin-top: 50px;
margin-bottom: 50px;
}
.endBtn input {
border: none;
background: none;
background-color: #808080;
padding: 25px 30px;
border-radius: 10px;
color: #fff;
box-shadow: 5px 5px rgba(0, 0, 0, 0.6);
transition: 0.5s;
}
.endBtn input:hover {
box-shadow: 4px 4px rgba(0, 0, 0, 0.6);
transform: translate(1px, 1px);
transition: 0.5s;
}
.endBtn input:active {
box-shadow: none;
transform: translate(5px, 5px);
transition: 0.5s;
}
.choice {
cursor: grab;
/*文字などの選択禁止*/
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
.choice img {
width: 30%;
}
.choice:active {
cursor: grabbing;
}
/*Webkit系画像のドラッグ&ドロップの禁止*/
img {
-webkit-user-drag: none;
}
img[draggable="true"] {
-webkit-user-drag: auto;
}
JavaScript
window.onload = function () {
const app = new Vue({
el: "#app",
data: {
message: "おなじグループにわけよう!",
list_ends: [],
lists: [
/*食べ物*/
{
id: 1,
name: "黄色いリンゴ",
image_link: "./media/frut/fruit_apple_yellow.png",
category: "D",
answer: "A",
},
{
id: 2,
name: "メロン",
image_link: "./media/frut/fruit_prince_melon.png",
category: "D",
answer: "A",
},
{
id: 3,
name: "シークワーサー",
image_link: "./media/frut/fruit_shi-kuwa-sa_shikuwasa.png",
category: "D",
answer: "A",
},
{
id: 4,
name: "すいか",
image_link: "./media/frut/fruit_suika_kodama.png",
category: "D",
answer: "A",
},
/*乗り物*/
{
id: 5,
name: "くるま",
image_link: "./media/norimono/car_go_kart_man.png",
category: "D",
answer: "C",
},
{
id: 6,
name: "ぎゅうしゃ",
image_link: "./media/norimono/hinamatsuri_gyuusya.png",
category: "D",
answer: "C",
},
{
id: 7,
name: "しんかんせん",
image_link: "./media/norimono/tube_train_hyperloop.png",
category: "D",
answer: "C",
},
{
id: 8,
name: "せんしゃ",
image_link: "./media/norimono/war_kettenkrad.png",
category: "D",
answer: "C",
},
/*どうぶつ*/
{
id: 9,
name: "いぬさん",
image_link: "./media/animal/animal_mizugi_boy_inu.png",
category: "D",
answer: "B",
},
{
id: 10,
name: "くまさん",
image_link: "./media/animal/animal_mizugi_boy_kuma.png",
category: "D",
answer: "B",
},
{
id: 11,
name: "ねこさん",
image_link: "./media/animal/animal_mizugi_boy_neko.png",
category: "D",
answer: "B",
},
{
id: 12,
name: "うさぎさん",
image_link: "./media/animal/animal_mizugi_boy_usagi.png",
category: "D",
answer: "B",
},
],
answer: "",
percent_score: "",
},
computed: {
CategoryA() {
return this.list_ends.filter((list) => list.category == "A");
},
CategoryB() {
return this.list_ends.filter((list) => list.category == "B");
},
CategoryC() {
return this.list_ends.filter((list) => list.category == "C");
},
CategoryD() {
return this.list_ends.filter((list) => list.category == "D");
},
},
mounted: function () {
this.list_ends = this.shuffle(this.lists);
},
methods: {
shuffle: function (array) {
for (let i = array.length - 1; i > 0; i--) {
let r = Math.floor(Math.random() * (i + 1));
let tmp = array[i];
array[i] = array[r];
array[r] = tmp;
}
console.log(array);
return array;
},
dragList(event, dragId) {
event.dataTransfer.effectAllowed = "move";
event.dataTransfer.dropEffect = "move";
event.dataTransfer.setData("list-id", dragId);
},
dropList(event, dropCategory) {
const dragId = event.dataTransfer.getData("list-id");
const dragList = this.lists.find((list) => list.id == dragId);
dragList.category = dropCategory;
},
kekka: function () {
var edge = null;
var atari = null;
var Dcount = 0;
var score = [];
var total_score = 0;
var total_count = this.lists.length;
var percent_score = 0;
for (i = 0; i < 3; i++) {
score[i] = 0;
}
this.lists.forEach((list) => {
if (list.category == "A") {
if (list.answer != "A") {
edge = true;
} else {
atari = true;
score[0]++;
}
}
if (list.category == "B") {
if (list.answer != "B") {
edge = true;
} else {
atari = true;
score[1]++;
}
}
if (list.category == "C") {
if (list.answer != "C") {
edge = true;
} else {
atari = true;
score[2]++;
}
}
if (list.category == "D") {
Dcount++;
}
});
if (Dcount == 0) {
if (edge == true) {
this.answer = "2";
} else if (atari == true) {
this.answer = "1";
}
} else {
this.answer = "3";
}
score.forEach(function (sco) {
total_score += sco;
});
percent_score = Math.ceil((total_score / total_count) * 100);
this.percent_score = percent_score;
},
},
});
};