webucks project_220222
저번 로그인 페이지에서 로그인하면 넘어오게 되는 그 페이지입니다.
총 12장의 이미지가 들어있는 갤러리입니다.
- 커피 사진과 이름은 모두 다르게 해주세요.
- 반응형을 고려하지 않으셔도 괜찮습니다.
- 반응형을 고려하신다면 커피 리스트는 flex-wrap 혹은 grid를 활용해주세요.
- 커피 이미지에 마우스를 호버했을 때 이미지를 확대해주세요.
사실 위의 조건들은 css단계에서 처리 가능한 기능이라서 크게 어렵지 않아요.
제가 어려웠던건..
사진 12개를 일일이 html로 작성하기 귀찮은데, 이걸 어떻게 자바스크립트로 처리할 방법 없을까?
였습니다.
리스트 html 생성
- 커피의 종류별로 객체를 생성한다. 커피의 데이터는 이미지경로와 이름으로 구성되어 있다.
- ex) 콜드 브루 커피=
{name:'나이트로 바닐라 크림',imgUrl:'/img/cb-01.jpg'}
브루드 커피={name:'아이스 커피',imgUrl:'/img/b-01.jpg'}
- 객체의 이름과 이미지 경로를 각각 읽어와
<ul>
의 하위 태그로 구성한다.
- 갤러리 1개의 HTML 구조
<section class="coffee-section cold-brew"> <h3 class="coffee-section-title">콜드 브루 커피 ☕</h3> <ul class="coffee-gall"> <!--여기부터--> <li> <a class="coffee-thumbnail" href="#"> <div class="coffee-img"><img src="img/cb-01.jpg" alt="cb-01"/></div> <p class="coffee-name">커피이름</p> </a> </li> <!--여기까지 생성할 부분--> </ul> </section>
const coldBrewList = [{
name: '나이트로 바닐라 크림',
imgUrl: 'img/cb-01.jpg'
}, {
name: '나이트로 콜드 브루',
imgUrl: 'img/cb-02.jpg'
}, {
name: '돌체 콜드 브루',
imgUrl: 'img/cb-03.jpg'
}, {
name: '바닐라 크림 콜드 브루',
imgUrl: 'img/cb-04.jpg'
}, {
name: '벨벳 다크 모카 나이트로',
imgUrl: 'img/cb-05.jpg'
}, {
name: '시그니처 더 블랙 콜드 브루',
imgUrl: 'img/cb-06.jpg'
}, {
name: '제주 비자림 콜드 브루',
imgUrl: 'img/cb-07.jpg'
}, {
name: '콜드 브루',
imgUrl: 'img/cb-08.jpg'
}, {
name: '콜드 브루 몰트',
imgUrl: 'img/cb-09.jpg'
}, {
name: '콜드 브루 오트 라떼',
imgUrl: 'img/cb-10.jpg'
}]
const brewedList = [{
name: '아이스 커피',
imgUrl: 'img/b-01.jpg'
}, {
name: '오늘의 커피',
imgUrl: 'img/b-02.jpg'
}]
이렇게 배열로 한번 감싸고 안에 객체 여러개를 넣었습니다.
const coldBrewGall = document.querySelector('.cold-brew .coffee-gall'),
brewedGall = document.querySelector('.brewed .coffee-gall');
그리고 태그가 들어갈 곳인 각각의 갤러리 ul
태그를 변수로 지정해줍니다.
return
명령문은 값을 하나만 반환할 수 있습니다.
마음만으로는 객체 내의 이름과 url을 한꺼번에 뽑아내고 싶은데 return의 특성때문에 이름 따로, url 따로 뽑아내기로 했어요.
function exportName(data) {
let coffeeName = [];
for (let key in data) {
coffeeName.push(data[key]['name']);
}
return coffeeName;
}
function exportUrl(data) {
let coffeeImg = [];
for (let key in data) {
coffeeImg.push(data[key]['imgUrl']);
}
return coffeeImg;
}
파라미터 data
에 위에서 지정해준 객체 coldBrewList
,brewedList
가 들어갈거에요.
이제 저기서 객체들을 차례로 확인하면서 key
값인 name
과 imgUrl
들의 value
를 뽑아내 배열로 반환합니다.
function addCoffeeList(obj, gallery) {
let nameIndex = exportName(obj);
let imgIndex = exportUrl(obj);
for (let i = 0; i < obj.length; i++) {
}
};
addCoffeeList(coldBrewList, coldBrewGall);
addCoffeeList(brewedList, brewedGall);
함수 addCoffeeList
은 파라미터로 객체 이름과 출력해낼 갤러리 이름을 받아낼겁니다.
마음만으로는 위쪽에서 반환된 coffeeName
과 coffeeImg
변수를 그대로 가져오고 싶습니다. 그런데 저 변수들은 exportName
내에서만 활용이 가능한 변수라서 또 변수를 지정해뒀어요.
이제 변수 nameIndex
와 imgIndex
가 그 자리를 대신합니다.
그리고 객체의 데이터 개수만큼 for문이 작동할텐데, 저렇게 다중 구조의 HTML을 삽입하려면 어떻게 해야할까요? 그래서 찾아봤습니다.
function function1() {
var ul = document.getElementById("list");
var li = document.createElement("li");//변수 li는 <li>태그
li.appendChild(document.createTextNode("Four"));//<li>태그 내에 'Four'이라는 텍스트 삽입, <li>Four</li>로 만들어짐
ul.appendChild(li);//이런 li가 ul 하위에 추가됨
}
와~createElement
로 태그를 하나하나 만들어준 다음 createTextNode
로 데이터를 넣고appendChild
를 쓰면 되는군요~
되겠냐고
<li>
<a class="coffee-thumbnail" href="#">
<div class="coffee-img"><img src="img/cb-01.jpg" alt="cb-01"/></div>
<p class="coffee-name">커피이름</p>
</a>
</li>
저는 li
밑에 a
가 있고 또 그 안에 div
와 p
가 있는 복잡한걸 만들고... 거기에 클래스랑 url까지 줄거라니까요?
일단 더이상 생각하기 싫어서, 변수 자체를 이렇게 만들어 줍니다.
function addCoffeeList(obj, gallery) {
let nameIndex = exportName(obj);
let imgIndex = exportUrl(obj);
for (let i = 0; i < obj.length; i++) {
let listTag = `<li><a class="coffee-thumbnail" href="#">
<div class="coffee-img">
<img src="${imgIndex[i]}" alt="${imgIndex[i].substr(4,imgIndex[i].length)}"/>
</div><p class="coffee-name">${nameIndex[i]}</p></a></li>`
}
};
src
에는 i번째 데이터의 이미지 경로가 들어갈테고, alt
값에는 이미지 경로에서 /img/
만 제외한 cb-01.jpg
형식의 텍스트가 들어갈 예정입니다.
.coffee-name
안에는 i번째nameIndex
인 이름값이 들어가고..
하지만 이러한 태그를 아무리 HTML에 넣으려 해봤자,
appendChild(listTag)
: 실패
append(listTag)
: 실패
어쩌라는 걸까요? 슬퍼진 저는 이렇게 생성된 li태그를 배열에 담아둔 후 무작정 태그들을 집어넣기로 했습니다.
function addCoffeeList(obj, gallery) {
let nameIndex = exportName(obj);
let imgIndex = exportUrl(obj);
let tagArray = [];
for (let i = 0; i < obj.length; i++) {
let listTag = `<li><a class="coffee-thumbnail" href="#">
<div class="coffee-img">
<img src="${imgIndex[i]}" alt="${imgIndex[i].substr(4,imgIndex[i].length)}"/>
</div><p class="coffee-name">${nameIndex[i]}</p></a></li>`
tagArray.push(listTag);
}
};
이제 배열 tagArray
에 담긴 열 몇개의 li들을 다시 뽑아내어 html에 삽입해야 합니다.
문제
gallery.innerHTML = tagArray;
이런 식으로 tagArray
안의 태그들을 그대로 넣었다가는,
배열 내의 쉼표까지 전부 화면에 나타납니다.
그래서 쉼표들을 전부 제거해줘야 했습니다.
해결
검색해보니 join()
이라는 메소드가 있더라고요.( join에 대하여 )
배열의 모든 요소를 연결해 하나의 문자열로 만들어주는 메소드입니다.
function addCoffeeList(obj, gallery) {
let nameIndex = exportName(obj);
let imgIndex = exportUrl(obj);
let tagArray = [];
for (let i = 0; i < obj.length; i++) {
let listTag = `<li><a class="coffee-thumbnail" href="#">
<div class="coffee-img">
<img src="${imgIndex[i]}" alt="${imgIndex[i].substr(4,imgIndex[i].length)}"/>
</div><p class="coffee-name">${nameIndex[i]}</p></a></li>`
tagArray.push(listTag);
}
let tagToString = tagArray.join('');
gallery.innerHTML = tagToString;
};
곧장 실행해봤더니, 이 방법으로 성공!
이제 객체에 데이터 몇개만 추가해주면 리스트가 저절로 만들어지네요!
//coffee-gall 리스트 추가
const coldBrewList = [{
name: '나이트로 바닐라 크림',
imgUrl: 'img/cb-01.jpg'
}, {
name: '나이트로 콜드 브루',
imgUrl: 'img/cb-02.jpg'
}, {
name: '돌체 콜드 브루',
imgUrl: 'img/cb-03.jpg'
}, {
name: '바닐라 크림 콜드 브루',
imgUrl: 'img/cb-04.jpg'
}, {
name: '벨벳 다크 모카 나이트로',
imgUrl: 'img/cb-05.jpg'
}, {
name: '시그니처 더 블랙 콜드 브루',
imgUrl: 'img/cb-06.jpg'
}, {
name: '제주 비자림 콜드 브루',
imgUrl: 'img/cb-07.jpg'
}, {
name: '콜드 브루',
imgUrl: 'img/cb-08.jpg'
}, {
name: '콜드 브루 몰트',
imgUrl: 'img/cb-09.jpg'
}, {
name: '콜드 브루 오트 라떼',
imgUrl: 'img/cb-10.jpg'
}]
const brewedList = [{
name: '아이스 커피',
imgUrl: 'img/b-01.jpg'
}, {
name: '오늘의 커피',
imgUrl: 'img/b-02.jpg'
}]
//변수 선언
const coldBrewGall = document.querySelector('.cold-brew .coffee-gall'),
brewedGall = document.querySelector('.brewed .coffee-gall');
//함수 선언
function exportName(data) {
let coffeeName = [];
for (let key in data) {
coffeeName.push(data[key]['name']);
}
return coffeeName;
}
function exportUrl(data) {
let coffeeImg = [];
for (let key in data) {
coffeeImg.push(data[key]['imgUrl']);
}
return coffeeImg;
}
function addCoffeeList(obj, gallery) {
let nameIndex = exportName(obj);
let imgIndex = exportUrl(obj);
let tagArray = [];
for (let i = 0; i < obj.length; i++) {
let listTag = `<li><a class="coffee-thumbnail" href="#">
<div class="coffee-img">
<img src="${imgIndex[i]}" alt="${imgIndex[i].substr(4,imgIndex[i].length)}"/>
</div><p class="coffee-name">${nameIndex[i]}</p></a></li>`
tagArray.push(listTag);
}
let tagToString = tagArray.join('');
gallery.innerHTML = tagToString;
};
addCoffeeList(coldBrewList, coldBrewGall);
addCoffeeList(brewedList, brewedGall);
로그인 페이지의 버튼 새로고침 현상 때처럼 스트레스를 받지는 않았지만, 만족할만한 검색 결과가 계속 나오지 않아 꽤 애를 먹었습니다.
그래도 예전 디자이너 시절때 하나하나 html코드로 갤러리를 짰을 때에 비하면 굉장히 많은 발전을 이루었다고 생각해서 뿌듯해집니다.
잘 봤어요 :)