학습을 하는 화면은 뭔가 동적인 움직이 있으면 좋을 거 같다. 그래서 CSS 에니메이션을 테스트해 보고 코드를 만들어 주는 다음 사이트를 활용하여 구현하였다. Animista 사이트 안에서는 원하는 에니메이션을 선택하면 움직임을 바로 보여주어 테스트 해보고 원하는 에니메이션의 코드를 바로 보여주어 적용할 수 있다.
너무 현란한 움직임은 학습에 도움이 되지 않을 것 같아서 조금 심플한 (ENTRANCE-SLIDE-IN) 효과만 사용하였다. 공부를 시작하면 학습카드가 오른쪽에서 나오고, 학습이 끝나면 왼쪽으로 사라지는 효과를 주었다.
.study_card_container_hide, .quiz_card_container_hide{
-webkit-animation: slide-out-left 0.2s cubic-bezier(0.755, 0.050, 0.855, 0.060) both;
animation: slide-out-left 0.2s cubic-bezier(0.755, 0.050, 0.855, 0.060) both;
}
.study_card_container_show, .quiz_card_container_show {
-webkit-animation: slide-in-right 0.4s cubic-bezier(0.390, 0.575, 0.565, 1.000) both;
animation: slide-in-right 0.4s cubic-bezier(0.390, 0.575, 0.565, 1.000) both;
}
/* Animista에서 자동 생성된 코드 */
@-webkit-keyframes slide-out-left {
0% {-webkit-transform: translateX(0);transform: translateX(0);
opacity: 1;}
100% {-webkit-transform: translateX(-1000px);transform: translateX(-1000px);
opacity: 0;}
}
@keyframes slide-out-left {
0% {-webkit-transform: translateX(0);transform: translateX(0);
opacity: 1;}
100% {-webkit-transform: translateX(-1000px);transform: translateX(-1000px);
opacity: 0;}
}
@-webkit-keyframes slide-in-right {
0% {-webkit-transform: translateX(1000px);transform: translateX(1000px);
opacity: 0;}
100% {-webkit-transform: translateX(0px);transform: translateX(0px);
opacity: 1;}
}
@keyframes slide-in-right {
0% {-webkit-transform: translateX(1000px);transform: translateX(1000px);
opacity: 0;}
100% {-webkit-transform: translateX(0);transform: translateX(0);
opacity: 1;}
}
단어학습 목록 페이지에서 한개의 항목을 선택하면, 바로 학습화면(study.html)으로 전환을 한다. 이때 필요한 파라메터는 word_set의 _id 값을 id에 get 방식으로 데이터를 넘겼다. html의 자바스크립트에서만 모든걸 해걸하고 싶어서 URL에서 파라메터를 뽑아내는 Request 객체를 만들어 사용하였다. 아래 소스를 별도 util.js에 넣고 script로 불러왔다.
var Request = function(){
this.getParameter = function(name){
var rtnval = '';
var nowAddress = unescape(location.href);
var parameters = (nowAddress.slice(nowAddress.indexOf('?')+1, nowAddress.length)).split('&');
for(var i=0; i<parameters.length; i++){
var varName = parameters[i].split('=')[0];
if(varName.toUpperCase() == name.toUpperCase()){
rtnval = parameters[i].split('=')[1];
break;
}
}
return rtnval;
}
}
var request = new Request();
실제 사용하는 방법은 아래와 같이 간단하다. javac 나 nodejs에서처럼 id를 손쉽게 가져 올수 있다.
var id = request.getParameter('id');
위 id값으로 학습 데이터를 가져오는 router 를 생성하였다. ws_rel_model의 두 필드 word_set_id, word_id는 각각 word_set, word객체를 참조하는 형태로 되어 있기에, find().populate() 와 같은 행태로 3개의 collection을 조인할 수 있다.
const mongoose = require('mongoose');
const { ObjectId } = mongoose.Types;
const { Schema } = mongoose;
const user_model =
mongoose.models['user']||
mongoose.model('user',
new Schema({user_id:{type:String, unique:true, required: true},
pw:{type:String, required:true},
email:{type:String, required:true}}, { strict: false }));
const word_set_model =
mongoose.models['word_set']||
mongoose.model('word_set' ,
new Schema({user_id:{type:String, required:true},
title:{type:String, required:true}},
{ strict: false }));
const ws_rel_model=
mongoose.models['ws_rel_model']||
mongoose.model('ws_rel_model',
new Schema({user_id:{type:String, required:true},
word_set_id:{type:Schema.Types.ObjectId,ref:"word_set"},
word_id:{type:Schema.Types.ObjectId,ref:"word"}},
{ strict: false }));
const word_model =
mongoose.models['word']||
mongoose.model('word' ,
new Schema({w:{type:String, required:true, unique: true},
m:{type:String, required:true}},
{ strict: false }));
router.get('/word_set', async(req, res) => {
console.log(req.session.username)
if(req.session.username == undefined|| req.session.username==""){
res.json({isLogin:false, state:'success', message:''})
}else{
var result = await ws_rel_model.find(
{user_id: req.session.username, word_set_id: req.query.id}
).populate('word_id word_set_id')
console.log(result)
res.json({isLogin:true, user_id: req.session.username,
state:'success', data:result, message:''})
}
})
find()는 user_id와 word_set_id로 조회를 하고, populate에는 "word_set word" 와 같은 스트링만 입력하면 자동으로 조인되어 아래와 같은 데이터를 출력해 준다.
{
"isLogin":true,"user_id":"juhpark","state":"success",
"data":[
{"_id":"678513533b358b086979c558",
"user_id":"juhpark",
"word_set_id": {"_id":"678513533b358b086979c555",
"user_id":"juhpark",
"title":"11월",
"__v":0},
"word_id":{"_id":"678276859a30d5d1ddce7f0d",
"w":"sky",
"m":"하늘","__v":0},"__v":0}
},
{ ... },
{ ... }
],
"message":""
}
study.html 안에서 위 데이터를 호출하는 소스는 다음과 같다. data객체에 원하는 형태로 데이터를 담고, 완료되면 study_next_word() 함수를 호출하여 학습을 시작한다.
var obj={}
obj['id'] = id
$.get('/word/word_set', obj, function(d){
if(d.data.length>0){
/* data 객체에 원하는 형태로 담기 */
data['id'] = d.data[0]._id
data['user_id'] = d.user_id
data['title'] = d.data[0].word_set_id.title
data['word'] = new Array();
d.data.forEach(function(w){
console.log(w)
data['word'].push({id: w.word_id._id, w:w.word_id.w, m:w.word_id.m})
})
study_next_word() /* 학습데이터를 보여주는 로직 */
}else{
alert("조회된 자료가 없습니다.")
location.href="/list.html"
}
})
클릭, Enter, Space 등으로 해당카드를 선택하면, 가려진 녹색 창이 사라지고 뜻이 나오고 한번더 선택하면 카드가 왼쪽으로 사라지고 오른쪽에서 다음카드가 나타난다.
다음 작업으로는 학습이 끝났을때, 학습결과를 저장할 예정이다. 단어장을 다 끝냈을때만, word_set에 횟수를 기록하고 ws_rel_model에는 단어별로 학습 횟수를 기록해보자.
'Programming > 온라인 영어암기 단어장 개발' 카테고리의 다른 글
온라인 영어 암기 단어장 만들기(9) - 학습결과 저장하기 (0) | 2025.01.16 |
---|---|
온라인 영어 암기 단어장 만들기(7) - 단어장 저장하기 (0) | 2025.01.13 |
온라인 영어 암기 단어장 만들기(6) - Google Translate API를 활용한 단어 뜻 찾아오기 (0) | 2025.01.11 |
온라인 영어 암기 단어장 만들기(5) - 단어입력화면 만들기 (1) | 2025.01.04 |
온라인 영어 암기 단어장 만들기(4) - 데이터베이스 설계하기 (0) | 2024.12.03 |