데이터 차트를 보여줘야 하는데 이것을 도넛 모양으로 표현할 때가 있다.

이제 것 라이브러리를 사용하여 크게 신경 쓰지 않았지만,

데이터가 추가 된다거나, 변경되고, 유기적인 데이터가 아닌 가벼운 데이터의 경우 도넛 모양의 차트만 그려줄 거라 하드코딩으로 해보기로 했다.

 

 

일단 구조를....

 

 

이런 도넛 모양의 차트를 기준으로 시작해봤다.

 

     1. 베이스 원형

     2. 가운데 뚫어줄 원형

     3. % 별로 컬러가 입혀질 원형

     4. 데이터 표시 라벨

 

 

 

 

1. 일단 css로만 해볼까?

일단 한개 수치만 띄어보자.

 

<HTML>

<div class="chart">
  <div class="chart-bar"></div>
</div>

 

<CSS3>

.chart{
  margin:0;
  padding:0;
  list-style-type: none;
  overflow: hidden;
  position: relative;
  width: 280px;
  height: 280px;
  border-radius:320px;
  background:gray;
}
.chart:after{
  content:'';
  position:absolute;
  top:0;left:0;bottom:0;right:0;
  margin:auto;
  width:80%;
  height:80%;
  background:#fff;
  border-radius:100%;
}
.chart-bar{
  position: absolute;
  top:50%;left:50%;
  background:skyblue;
  height:110%;  
  width:45%;
  transform: translate(-50%,-50%) rotateZ(-45deg);
  transform-origin:center;
}

chart-bar의  width 값과 transform값의 rotateZ로 변경하면 될 거 같았다.

 

이건 대체 무슨129 ㅇㅁㅇ!!!!

 

 

2. background:conic-gradient() 의 사용하기

원의 중심점에서 끝점, 각도 끝점까지 해서 대략 원뿔모양식으로 처리를 해야했다.

 

<HTML5>

<div class="chart">
  <div class="chart-bar" data-deg="50"></div>
</div>

 

<CSS3>

.chart {
  position: relative;
  width: 300px;
  height: 300px;
  border-radius: 50%;
  transition: 0.3s;
  background:lightgray;
  display:inline-block;
}

.chart:after{ /* 가상선택자는 도넛 모양을 만들기 위함이다.*/
  content:'';
  background: #fff;  /* 백그라운드 컬러로 중앙가리기 */
  position: absolute;
  top:50%; left:50%;
  width:200px; height:200px; /* 도넛의 너비 설정 */
  border-radius: 50%;
  transform: translate(-50%, -50%);
}
.chart-bar{
  width: inherit;
  height: inherit;
  border-radius: 50%;
  background: conic-gradient(#9986dd 50deg, #fbb871 50deg); /* 차트 설정 */
}

 

위 모양처럼 나온다

 

 conic-gradient은 시작지점을 설정하지 않으면 12시부터(시계로 빗대어 말하자면) 시작하게 된다.

 

 

background: conic-gradient(#9986dd 50deg, #fbb871 50deg); 

인자값 :  첫 시작 컬러 00번째  각도까지, 두 번째 컬러 00번째 각도부터 전체 

 

 

 

 

background: conic-gradient( red 36deg, orange 36deg 170deg, yellow 170deg);

차트가 여러 개가 될 경우는 중간 차트 시작 지점 , 끝 지점 설정해야 한다.

 

 

 

굳이 시작점과 끝 지점 각도를 전부 설정하는 이유는 차트 경계를 엣지 있게 처리하기 위함이다. 

컬러+시작각도 만 넣으면 경계는 스무스하게 그라데이션으로 처리된다.

 

 

 

background: conic-gradient( red 36deg, orange 170deg, yellow);

 

 

 

 

 

1) 첫번째 시작 기준점을 옮기고 싶다면 from 

 

 

background: conic-gradient(from 45deg, red 36deg, orange 170deg, yellow);

 

 

 

 

 

2) 원 중심점 옮기기 - at(x축, y축)

 

 

background: conic-gradient(at 60% 25%, red 36deg, orange 170deg, yellow);

 

 

 

 

 

3) 여러 속성을 한꺼번에 사용

 

 

background: conic-gradient(from 30deg at 40% 35%,  red , orange , yellow);

 

 

 

 

 

자세한 내용은 아래 링크 참고하자

https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/conic-gradient()
ㄴ 링크에서 보시다시피 ie는 전혀 지원하진 않지만 엣지부터 다른 브라우저들은 지원하고 있다.

https://www.w3schools.com/css/css3_gradients_conic.asp
ㄴ 파이 차트 그리는 방식을 상세히 설명하고 있다

 

conic-gradient() - CSS: Cascading Style Sheets | MDN

The conic-gradient() CSS function creates an image consisting of a gradient with color transitions rotated around a center point (rather than radiating from the center). Example conic gradients include pie charts and color wheels. The result of the conic-g

developer.mozilla.org

 

CSS Conic Gradients

W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.

www.w3schools.com

 

 

 

3. 최종 : 디테일하게 설계

이제 데이터 수치 라벨, 데이터 그래프를 나눠주면 그리고자 했었던 차트를 완성할 수 있다.

 

<HTML5>

<div class="chartWrap">
  
  <div class="chart">
    <div class="chart-bar" data-deg="50"></div>
    <div class="chart-bar" data-deg="95"></div>
    <div class="chart-bar" data-deg="200"></div>
    <div class="chart-bar" data-deg="15"></div>
  </div>
  
</div>

 

<CSS3>

.chartWrap{
  position: relative;
  width: 300px;
  height: 300px;
  margin:100px;
}
.chart {
  position: relative;
  width: 300px;
  height: 300px;
  border-radius: 50%;
  transition: 0.3s;
  background:lightgray;
  display:inline-block;
}
.chart:after{
  content:'';
  background: #fff;
  position: absolute;
  top:50%; left:50%;
  width:170px; height:170px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
}
.chart-bar{
  width: inherit;
  height: inherit;
  border-radius: 50%;
  position: relative;
}

.chart-total{
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background:gray;
  width:100%;
}
.chart-total span{
  position: absolute;
  color:#777;
}
.chart-total-num{
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size:1.3rem;
  font-weight:bold;
  color:#333;
}
.chart-total-text1{
  top:-150px;right:-10px;
}
.chart-total-text2{
  top:-50px;right:-70px;
}
.chart-total-text3{
  top:120px;right:30px;
}
.chart-total-text4{
  top:0;left:-70px;
}

 

<javascript>

var _chart = document.querySelector('.chart');
var _chartBar = document.querySelectorAll('.chart-bar');
var color = ['#9986dd','#fbb871','#bd72ac','#f599dc'] //색상
var newDeg = []; //차트 deg

function insertAfter(newNode, referenceNode) {
    referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}

function chartLabel(){
  var _div = document.createElement('div');
  _div.className = 'chart-total';
  _div.innerHTML = `<span class="chart-total-num">Total:<br> 3,135</span>
                    <span class="chart-total-text1">Automobile</span>
                    <span class="chart-total-text2">Disablility</span>
                    <span class="chart-total-text3">Life</span>
                    <span class="chart-total-text4">Property</span>`;
  insertAfter(_div,_chart);
}

function chartDraw(){ 
  for( var i=0;i<_chartBar.length;i++){
    var _num = _chartBar[i].dataset.deg
    newDeg.push( _num )
  }

  var num = newDeg.length - newDeg.length;
  _chart.style.background = 'conic-gradient(#9986dd '+
                                                newDeg[num]+'deg, #fbb871 '+
                                                newDeg[num]+'deg '+newDeg[num+1]+'deg, #bd72ac '+
                                                newDeg[1]+'deg '+newDeg[2]+'deg, #f599dc '+
                                                newDeg[2]+'deg )';
  
  chartLabel();
}

chartDraw();

 

&amp;lt;result&amp;gt;

 

See the Pen Untitled by JNoony (@jnoony) on CodePen.

728x90

'css' 카테고리의 다른 글

[scss] scss 컴파일 해보기  (1) 2022.08.07
[css+javascript] 룰렛  (1) 2021.04.21
[css] 레이아웃 그리기  (0) 2021.03.30
[css] reset파일 만들기 귀찮을 때  (0) 2021.03.17
[css] 크로스브라우징  (0) 2021.03.17

요즘 React, Vue, Angular 등 프레임워크/라이브러리를 이용한 SPA(Single Page Application)를 제작을 많이 하게 되는데 리스트를 페이징 보다는 more버튼으로 처리하고 있다. 대다수의 사용자들이 더보기 버튼을 더 선호하기 때문이라는 결과도 있고 페이징보다는 더보기 버튼이 리스트가 더 빠르다고 느끼기도 하는 거 같다.

앞으로도 많이 사용할거 같고, 공부하는 겸 가볍게 만들어본다.

 

[참고] brunch.co.kr/@blackindigo-red/13
 

무한 스크롤 vs 페이지네이션 vs '더보기' 버튼

이커머스에서 어떤 로딩 방법을 사용하면 좋을지에 대한 UT 결과 | (출처 : [Infinite Scrolling, Pagination Or “Load More” Buttons? Usability Findings In eCommerce – Smashing Magazine]의 기사를 번역 및 가공한 컨텐

brunch.co.kr

 

1. 리스트 조건

실무를 할때엔 개발 document API 받아서 진행하므로 스터디 할땐,  DB 연결이나, 로컬스토어가 아닌 ajax를 사용하여 JSON파일의 데이터를 리스트로 구현해 보자.

 

[preview img]

[ 조건 ]

- 1025px 이상은 리스트 열 안에 4개씩, 8개씩 보이게

- 769px 까지는 리스트 열 안에 3개씩

- 500px 모바일에서는 열 1개씩

- 데이터 JSON으로 넘기기[mokup data]

- 썸네일 이미지는 크기 상관없이 중간에 위치

- 이메일은 한 줄 말줄임 처리

 

JSON 데이터는 아래 사이트에서 더미 데이터로 만들면 된다.
[mokup data] www.mockaroo.com/
 

Mockaroo - Random Data Generator and API Mocking Tool | JSON / CSV / SQL / Excel

Mock your back-end API and start coding your UI today. It's hard to put together a meaningful UI prototype without making real requests to an API. By making real requests, you'll uncover problems with application flow, timing, and API design early, improvi

www.mockaroo.com

 

 

2. 코딩

이번 리스트는 javascript를 연습하는 게 목적이고, 나중에 실무를 할 때 많은 데이터들을 동적으로 그려지는 게 유지보수, 운영이나 구축하는 데 있어 핵심이다고 생각하여 HTML 태그를 js에서 그려오는 형태로 제작하기로 했다.

 

<HMTL5>

<div class="wrap">
	<ul class="listWrap"></ul>
</div>

 

<JS>

"use strict";

const dataURL = './data/MOCK_DATA.json';
const _WRAP = document.querySelector('.wrap');
const _UL = document.querySelector('.listWrap');

const list = {
    init:function(){
    	// ajax로 데이터 불러오기
        list.ajax();
    },
    listView:function(data){
    	// Column안에 들어갈 리스트 그리기
        let _LI = document.createElement('li');
        _LI.className = 'list';
        _LI.innerHTML = `<div class="list-thum">
                            <img src="${data.img}" alt="img-${data.id}">
                         </div>
                         <div class="list-user">
                            <span>${data.username}</span>
                            <span>${data.date}</span>
                         </div>
                         <div class="list-email">${data.email}</div>`;
        return _LI;
    },
    more:function(length,max){
        //more button
        let _BTN = document.createElement('button');
        _BTN.className = 'btn-more';
        _BTN.innerText = 'more';
        return length > max && _WRAP.appendChild( _BTN ); 
    },
    ajax:function(){
        $.ajax ({
            type : 'get',
            url: dataURL,
            datatype : 'json',
            success : function(data){    
                const max = 8; // 최대 8개
                let start = 0; // 리스트데이터 시작번호
				
                // 처음 리스트 데이터
                for(let i=start;i<max;i++){
                    _UL.appendChild( list.listView( data[i] ) );
                }
				
                // 마지막 리스트 도달시
                const _P = document.createElement('p');
                      _P.innerText='...List END'; 
                
                let cnt = 1; // 버튼클릭수 
                list.more(data.length,max).addEventListener('click',function(e){
                    // 클릭수
                    cnt++;
                    
                    /***** 
                    * 보여질 데이터 초과시 
                    */
                    // 더보기버튼으로 불러올 리스트 개수
                    // data.length(총 데이터 개수) / max(최대 8개)
                    if( data.length / max < cnt ){
                        const target = e.target;
                        target.after(_P);
                        return false
                    };
					
                    // 다음 리스트 그리기
                    for(let i=max*(cnt-1);i<max*cnt;i++){
                        _UL.appendChild( list.listView( data[i] ) );
                    }
                });
            },
            error : function(err){
                 console.log('err : ',err)
            }
        })
    },
}

//리스트 그려지도록 선언
list.init();

 

 

 

3. 최종 화면단

이미지스러운 걸 넣으려고 인터넷에 떠돌아다니는 https://api.tvmaze.com/search/shows?q=batman 를참고했는데,

데이터 길이가 10개라서 1줄에 4개씩 처리하게 됐다.

 

코드는 위에 작성한 대로 사용했고, 다른  json 데이터를 가져와도 쉽게 고칠 수 있었다. 

다만 뭔가 좀 더 보기 쉽거나 간결하게 작성하는 방법은... object 보다는 함수로 작성하여 불러오는 게 낫나 싶기도 하다.

 

PC버전은 코드펜으로 넘어가서 확인하자 ㅎ.ㅎ

 

728x90

생각보다 이벤트 페이지에서 많이 사용되는 룰렛을 jQuery가 아닌 javascript로만 구현해 보고 싶어졌다.

jQuery를 사용한다면 코딩 몇줄로 구현되어 웬만한 브라우저에 지원되겠지만....

 

구글 검색 '룰렛'

이벤트 페이지는 그래픽/디자인이 많이 들어가기 때문에 대체로 이미지를 활용하게 된다.

 

[작업 플로우]

1. 최소 돌림판, 지시화살표, 버튼 의 엘리먼트가 필요

2. 지시화살표는 상단에 고정

3. 버튼을 클릭시 -> 몇바퀴 360도 회전하다가 멈춤

4. 멈추는 대상은 랜덤이여야함 

5. 돌림판은 이미지, 지시화살표는 css로 처리

 

1. start / stop

클래스 이름을 잘못지었으나, 수정하기 귀찮으니 그대로 진행. 

부모객체 div.rouletter의 크기를 400 x 400 으로 정하고, 돌림판의 크기를 350 x 350으로 하여 중간에 위치하게 했다.

버튼을 클릭해서 start로 만든다음 돌림판을 stop누를때까지 회전을 시킬꺼라 keyframe을 사용해주자.

 

<div class="rouletter">
    <div class="rouletter-bg"><div class="rouletter-wacu"></div></div>
    <div class="rouletter-arrow"></div>
    <button class="rouletter-btn">start</button>
</div>
.rouletter{
	position: relative;
    width:400px;
    height:400px;
}
.rouletter-bg{
	position: absolute;
    top:50%;
    left:50%;
    transform:translate(-50%,-50%);
    width:350px;
    height:350px;
    border-radius:350px;
	overflow:hidden;
}
.rouletter-wacu{
    width:100%;height:100%;
	background:#f5f5f2 url('https://m.lifeplanet.co.kr:444/commons/slink/administrator/openInnovation/img/MO)%20360%ED%94%8C%EB%9E%98%EB%8B%9B_%EB%A3%B0%EB%A0%9B%ED%8C%90_476x476_201026.png') no-repeat;
    background-size:100%;
    transform-origin: center;
}
.rouletter-arrow{
	position: absolute;
    top:0;
    left:50%;
    transform:translateX(-50%);
    width:1px;
    height:1px;
    border-right:10px solid transparent;
    border-left:10px solid transparent;
    border-top:40px solid red;
    border-bottom:0px solid transparent;
}
.rouletter-btn{
	position: absolute;
    top:50%;
    left:50%;
    transform:translate(-50%,-50%);
    width:80px;
    height:80px;
    border-radius:80px;
    background:#fff;
    border-image: linear-gradient(to right, #fbfcb9be, #ffcdf3aa, #65d3ffaa);
    border: 2px solid;
}

// 돌림판 회전 애니메이션
.on{
    animation-name: ani;
    animation-duration: 0.1s;
    animation-fill-mode: forwards;  
    animation-iteration-count: infinite;
}

@keyframes ani{
    0% { 
        transform: rotate(0deg); 
    	transition-timing-function: ease-out;
    }
    100%{ 
        transform: rotate(360deg); 
    }
}

 

애니메이션은 클래스명 on에 담아놓고, javascript로 명령해주자.

 

var rouletter = {
	// 부여할 숫자 랜덤으로 하기
    random:function(){
        min = Math.ceil(0);
        max = Math.floor(5);
        return Math.floor(Math.random() * (max - min)) + min;      
    },
    // start 버튼
    start:function(){
    	var btn = document.querySelector('.rouletter-btn');
        var panel = document.querySelector('.rouletter-wacu');
        
        panel.classList.add('on');
        btn.innerText = 'stop';
    },
    // stop 버튼
    stop:function(){
        var btn = document.querySelector('.rouletter-btn');
    	var panel = document.querySelector('.rouletter-wacu');
        // 돌림판 형태가 6개로 분할되어있어 필요한 각도를 array로 만들었다.
        // 후에 length로 for문으로 돌려서 array처리로 변경하면 보다 동적으로 대처할수 있겠다.
        var deg = [60,120,180,240,300,360];
        
        panel.style.transform = 'rotate('+ deg[rouletter.random()] +'deg)';
        panel.classList.remove('on');
        btn.innerText = 'start';
    }
}
                                 
document.addEventListener('click',function(e){
    var target = e.target
    if( target.tagName === 'BUTTON'){
        target.innerText === 'start' 
            ? rouletter.start() : rouletter.stop();
    }
})

< preview >

 

 

 

2. start

 

start/stop 상태에서 버튼한번 클릭으로 결과 도출하는 상태도 만들어보자.

그리고 돌림판을 몇바퀴 회전시키다가 멈춤처리를 할것이라 css에서 keyframe을 사용하지 않고 js에서 처리 할것이다.

var rolLength = 6;

var rolette = {
	rRandom :function(){
      var min = Math.ceil(0);
      var max = Math.floor(rolLength-1);
      return Math.floor(Math.random() * (max - min)) + min;
    },
	rRotate:function(){
    	var panel = document.querySelector(".rouletter-wacu");
        var deg = [];
        for (var i = 1, len = rolLength; i <= len; i++) {
          deg.push((360 / len) * i);
        }

        var baseDeg = 7200; //20바퀴회전
        var stopDeg = baseDeg + deg[rolette.rRandom()]; // + 부여된 랜덤숫자에 해당하는각도
        panel.animate(
          //keyframe
          [
            { transform: "rotate(0deg)" },
            { transform: "rotate(" + stopDeg + "deg)" }
          ],
          // animation option
          {
            fill: "forwards",
            duration: 7000,
            easing: "ease-out"
          }
        );
    }
}


document.addEventListener("click", function (e) {
  var target = e.target;
  if (target.tagName === "BUTTON") {
    rolette.rRotate();
  }
});

 

<preview>

 

위 코드는 최신브라우저에서만 가능하다. 

ie 자체는 아예 무시된 경우인데, 아무래도 cross 처리 되는 룰렛도 만들어야겠다.

 

 

3. 보안된 룰렛

IE 꺼저라

하.. 그나마 두루두루 쓸수 있는 코드로 변경하면서 좀 보안해보자.

  1. 위에 코드들은 회전하는 동안 클릭을 할 수 있기때문에 동작중 클릭막기.

  2. css에서는 이미지에 transition옵션을 추가해주고 element.animate()의 대체요소로 setInterval() 활용,

    > transition-timing-function: ease-in-out;
    > transition: 2s;

 

var rolLength = 6;

const rRandom = () => {
  var min = Math.ceil(0);
  var max = Math.floor(rolLength - 1);
  return Math.floor(Math.random() * (max - min)) + min;
};

const rRotate = () => {
  var panel = document.querySelector(".rouletter-wacu");
  var btn = document.querySelector(".rouletter-btn");
  var deg = [];
  for (var i = 1, len = rolLength; i <= len; i++) {
    deg.push((360 / len) * i);
  }

  var num = 0; //회전을 시킬 횟수
  var ani = setInterval(() => {
    num++; //인터벌 수치만큼 증가
    panel.style.transform = "rotate(" + 360 * num + "deg)";
    // 버튼 이벤트 막기
    btn.disabled = true; //button,input
    btn.style.pointerEvents = "none"; //a 태그
	
    // 횟수 50에 다달았을때,
    if (num === 50) {
      clearInterval(ani); //회전 삭제
      panel.style.transform = "rotate(" + deg[rRandom()] + "deg)"; //랜덤숫자로 멈춤
    } 
  }, 50);
};

document.addEventListener("click", function (e) {
  var target = e.target;
  if (target.tagName === "BUTTON") {
    rRotate();
	
    // transition-timing-function 를 ease-in-out로 적용 햇기때문에 잔여초 이후 버튼활성화
    setTimeout(() => {
      target.disabled = false;
      target.style.pointerEvents = "auto";
      console.log("이벤트가 끝남");
    }, 5500);
  }
});

 

<preview>

 

 

 

4. 최종

결과 팝업까지 띄어야 프론트에서 할수있는 부분을 다 한거 같다.

랜덤숫자 부분은 사은품 갯수가 한정되어 있고 디비에 데이터도 저장해야 하기 때문에 관련해서는 백엔드에서 예외, 중복 처리 및 데이터 처리를 해야 할것이다.

 

* html

<!DOCTYPE html>
<html>
  <head>
    <title>룰렛</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <div id="app"></div>

    <script src="src/roulette.js"></script>
  </body>
</html>

 

*css

.rouletter {
  position: relative;
  width: 400px;
  height: 400px;
}
.rouletter-bg {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 350px;
  height: 350px;
  border-radius: 350px;
  overflow: hidden;
}
.rouletter-wacu {
  width: 100%;
  height: 100%;
  background: #f5f5f2
    url("https://m.lifeplanet.co.kr:444/commons/slink/administrator/openInnovation/img/MO)%20360%ED%94%8C%EB%9E%98%EB%8B%9B_%EB%A3%B0%EB%A0%9B%ED%8C%90_476x476_201026.png")
    no-repeat;
  background-size: 100%;
  transform-origin: center;
  transition-timing-function: ease-in-out;
  transition: 2s;
}
.rouletter-arrow {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 1px;
  height: 1px;
  border-right: 10px solid transparent;
  border-left: 10px solid transparent;
  border-top: 40px solid red;
  border-bottom: 0px solid transparent;
}
.rouletter-btn {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 80px;
  height: 80px;
  border-radius: 80px;
  background: #fff;
  border-image: linear-gradient(to right, #fbfcb9be, #ffcdf3aa, #65d3ffaa);
  border: 2px solid;
}

.hidden-input {
  display: none;
}

 

*javascript

var rolLength = 6; // 해당 룰렛 콘텐츠 갯수
var setNum; // 랜덤숫자 담을 변수
var hiddenInput = document.createElement("input");
hiddenInput.className = "hidden-input";

//랜덤숫자부여
const rRandom = () => {
  var min = Math.ceil(0);
  var max = Math.floor(rolLength - 1);
  return Math.floor(Math.random() * (max - min)) + min;
};

const rRotate = () => {
  var panel = document.querySelector(".rouletter-wacu");
  var btn = document.querySelector(".rouletter-btn");
  var deg = [];
  // 룰렛 각도 설정(rolLength = 6)
  for (var i = 1, len = rolLength; i <= len; i++) {
    deg.push((360 / len) * i);
  }
  
  // 랜덤 생성된 숫자를 히든 인풋에 넣기
  var num = 0;
  document.body.append(hiddenInput);
  setNum = hiddenInput.value = rRandom();
	
  // 애니설정
  var ani = setInterval(() => {
    num++;
    panel.style.transform = "rotate(" + 360 * num + "deg)";
    btn.disabled = true; //button,input
    btn.style.pointerEvents = "none"; //a 태그
    
    // 총 50에 다달했을때, 즉 마지막 바퀴를 돌고나서
    if (num === 50) {
      clearInterval(ani);
      panel.style.transform = `rotate(${deg[setNum]}deg)`;
    }
  }, 50);
};

// 정해진 alert띄우기, custom modal등
const rLayerPopup = (num) => {
  switch (num) {
    case 1:
      alert("당첨!! 스타벅스 아메리카노");
      break;
    case 3:
      alert("당첨!! 햄버거 세트 교환권");
      break;
    case 5:
      alert("당첨!! CU 3,000원 상품권");
      break;
    default:
      alert("꽝! 다음기회에");
  }
};

// reset
const rReset = (ele) => {
  setTimeout(() => {
    ele.disabled = false;
    ele.style.pointerEvents = "auto";
    rLayerPopup(setNum);
    hiddenInput.remove();
  }, 5500);
};

// 룰렛 이벤트 클릭 버튼
document.addEventListener("click", function (e) {
  var target = e.target;
  if (target.tagName === "BUTTON") {
    rRotate();
    rReset(target);
  }
});

// roulette default
document.getElementById("app").innerHTML = `
<div class="rouletter">
    <div class="rouletter-bg">
        <div class="rouletter-wacu"></div>
    </div>
    <div class="rouletter-arrow"></div>
    <button class="rouletter-btn">start</button>
</div>
`;

 

<preview>

 

 

 

728x90

'css' 카테고리의 다른 글

[scss] scss 컴파일 해보기  (1) 2022.08.07
[css] 도넛 차트 그리기  (0) 2021.06.03
[css] 레이아웃 그리기  (0) 2021.03.30
[css] reset파일 만들기 귀찮을 때  (0) 2021.03.17
[css] 크로스브라우징  (0) 2021.03.17
기본 연산자, 논리 연산자를 이용한 동적 셀렉트 박스를 구현하면서 javascript를 많이 경험해 보자

1. 연산자

수학 연산자

  • 덧셈 연산자 +
  • 뺄셈 연산자 -
  • 곱셈 연산자 *
  • 나눗셈 연산자 /
  • 나머지 연산자 %
  • 거듭제곱 연산자 **
var a = 3;
var b = 2;
var c = 4;

[나머지연산자]
a % b = 1  // 3을 2로 나눈 후 나머지 출력

[거듭제곱 연산자]
a ** b = 9   // a를 b의 수만큼 곱한 수 출력
a ** c = 81  // a를 c의 수만큼 곱한 수 출력

 

할당 연산자 = 

let a = 1;
let b = 2;
let c = 3 - (a = b + 1); //a = 3 , c = 0;

let aa, bb, cc;
aa = bb = cc = 2 + 3;  // aa = 5, bb = 5, cc = 5

// 위 코드와 동일한 코드, 가독성 좋게 줄을 나눠서처리
cc = 2 + 3;
bb = cc;
aa = cc;

 

복합 할당 연산자

let n = 5;
n += 3;     // n은 8
n *= 4;     // n은 32, 위 덧셈이 적용되어 8 *4 계산이 출력
n += 1 + 4  // n은 37

let a = 1, b = 1;
let c = ++a; // 2
let d = b++; // 1

let aa = 2;
let x = 1 + (aa *= 2);  // x = 5

 

증감 감소 연산자

See the Pen gOgxvEr by JNoony (@jnoony) on CodePen.

 

 

비트 연산자 : 인수를 32비트 정수로 변환하여 이진 연산을 수행

  • 비트 AND &
  • 비트 OR |
  • 비트 XOR ^
  • 비트 NOT ~
  • 왼쪽 시프트(LEFT SHIFT) >>
  • 오른쪽 시프트(RIGHT SHIFT) <<
  • 부호 없는 오른쪽 시프트(ZERO-FILL RIGHT SHIFT) >>>

 

쉼표 연산자: 코드를 짧게 쓰려는 의도로 가끔 사용

let a = (1 + 2, 3 + 4);  // a = 7;

 

 

 

2. 비교 연산자

불린 형 반환

alert(2 > 1)   // treu
alert(2 == 1)  // false
alert(2 != 1)  // true

//반환된 변수 변수에 할당
let result = 5 > 4;
alert(result)  // true

 

문자열 비교

alert('z' > 'a');      // true
alert('pink' > 'red')  // false
alert('Bee' > 'Be')    // true
alert( '2' > 1 );      // true
alert( '01' == 1 );    // true

alert( 'c' == 'C' )   // false
alert( 'c' > 'C' )    // true
alert( 'c' < 'C' )    // false

 

문자열 비교 시 적용되는 알고리즘은 다음과 같습니다. (영어는 사전 순이 아니라 유니코드 순.)

unicode-table.com/kr/alphabets/english/
 

영어 알파벳

유니 코드 문자 검색 웹 서비스. 즐겨 찾는 문자를 찾아서 복사하십시오 : 😎 에모지, ️ 화살표, ✪ 별, 💲 통화, 🈂️ 글쓰기 시스템 및 기타 🚩

unicode-table.com

  1. 두 문자열의 첫 글자를 비교
  2. 첫 번째 문자열의 첫 글자가 다른 문자열의 첫 글자보다 크면(작으면), 첫 번째 문자열이 두 번째 문자열보다 크다고(작다고) 결론 내고 비교를 종료합니다.
  3. 두 문자열의 첫 글자가 같으면 두 번째 글자를 같은 방식으로 비교합니다.
  4. 글자 간 비교가 끝날 때까지 이 과정을 반복합니다.
  5. 비교가 종료되었고 문자열의 길이도 같다면 두 문자열은 동일하다고 결론 냅니다. 비교가 종료되었지만 두 문자열의 길이가 다르면 길이가 긴 문자열이 더 크다고 결론 냅니다.

 

일치 연산자

alert( 0 == false );    // true
alert( ' ' == false );  // true :: 동등모드
alert( 0 === false );   // false  ::엄격모드 

alert( null === undefined ); // false
alert( null == undefined );  // true

 

null vs 0  , 비교가 불가능한 undefined

alert( null > 0 );   // false
alert( null == 0 );  // false
alert( null >= 0 );  // true

alert( undefined > 0 );  // false 
alert( undefined < 0 );  // false 
alert( undefined == 0 ); // false 

 

 

 

3. if문

let year = prompt('오늘은 몇년도?', '');
if (year == 2021) {
  alert( "정답입니다!" );
}
else if(year > 2021) {
  alert( '년도를 내리시지' ); 
}
else {
  alert( '오답입니다!' ); 
}

 

 

 

 

4. 논리 연산자

  • || (or)  :  result = value1 || value2;
  • && (and)  : result = a && b;
  • ! (not) : result =! value;
  • ?? (null 병합)
alert( 1 && null && 2 );  // null
alert( null || 2 && 3 || 4 );   // 3

 

※ '??'와 '||'의 차이

let height = 0;
alert(height || 100);  // 100
alert(height ?? 100);  // 0, height가 null이나 undefined일 경우에만 100


let _height = null;
let _width = null;
let area = (_height ?? 100) * (_width ?? 50);

alert(area);  // 5000
alert(_height ?? (100 * _width) ?? 50)  // 0

 

 

 

5. while과 for 반복문

let i = 0;
while(i < 3){
   alert(i);
   i++;
} // 0,1,2가 출력됨

while(i){
   alert(i--)
} // 3,2,1 이 출력됨

 

do... while 반복문

let i = 0;
do{
   alert( i );
   i++;
} while ( i < 3 );  // 0,1,2 출력

 

for 반복문

for( let i = 0;i < 3;i++ ){
  alert(i)
} //0,1,2 출력

 

반복문 빠져나오기

let sum = 0;
while(true){
   let val = +prompt('숫자 입력','');
   if( !val ) break;  // 숫자 쓰는란이 ''이면 빠져나옴
   sum += val;  // 숫자 입력한 만큼 더해짐
}
alert('총: '+sum);  

 

다음 반복으로 넘어가기

for( let i=0; i<10; i++){
   if( i % 2 == 0){
      alert(i)
   } // 0,2,4,6,8
}

 

 

 

 

6. 정리한 내용 모아서 간단한 동적 Select Box 만들기

<!-- HTML5 -->
<h1>오늘 뭐 먹지?</h1>
<select id="sel">
  <option>--종류 고르기--</option>
  <option value="food1">양식</option>
  <option value="food2">한식</option>
  <option value="food3">분식</option>
  <option value="food4">중식</option>
  <option value="food5">일식</option>
  <option value="food6">패스트푸드</option>
  <option value="food7">편의점</option>
</select>

 

/*********
* javascript
*********/ 
//첫번째 셀박
let selBox = document.querySelector('#sel'); 

//첫번째 셀박의 selected 감지
selBox.addEventListener('input',function(e){
  // 배열오브젝트 데이터에 selected된 value값으로 filter
  let data = listData.filter(item => item.name === e.target.value);
  
  // 첫번째 value에 관련된 두번째 셀박 그리기
  secondSelBox(data[0].name, data[0].data);
  
  // 다음 선택시 이전 두번째 셀박 삭제하기
  document.querySelectorAll('select')[1].nextSibling.remove();
})

// 선택한 Element 다음형제 만드는 프로토타입 만들기
Element.prototype.appendAfter = function (element) {
    element.parentNode.insertBefore(this, element.nextSibling);
}, false;

// 두번째 셀박 그리기 함수
function secondSelBox(name,data){
  var sel = document.createElement('select');
  sel.id = 's-'+name;
  for ( let i=0,len = data.length; i<len;i++) {
    var opt = document.createElement("option");
    opt.value = data[i].val;
    opt.innerHTML = data[i].name;
    sel.appendChild(opt);
  } 
  sel.appendAfter(document.getElementById('sel'));
}



//데이터
var listData = [
  {
    name:"food1",
    data:[
      {val:'sec-food1',name:'돈까스'},
      {val:'sec-food2',name:'스테이크'},
      {val:'sec-food3',name:'폭립'}
    ],
  },
  {
    name:'food2',
    data:[
      {val:'sec-food1',name:'콩비지'},
      {val:'sec-food2',name:'보리밥'},
      {val:'sec-food3',name:'해물칼국수'}
    ]
  },
  {
    name:'food3',
    data:[
      {val:'sec-food1',name:'김밥'},
      {val:'sec-food2',name:'즉석떡볶이'},
      {val:'sec-food3',name:'쫄면'},
      {val:'sec-food4',name:'오뎅'},
      {val:'sec-food5',name:'비빔만두'}
    ]
  },
  {
    name:'food4',
    data:[
      {val:'sec-food1',name:'마라탕'},
      {val:'sec-food2',name:'꿔바로우'}
    ]
  },
  {
    name:'food5',
    data:[
      {val:'sec-food1',name:'초밥'},
      {val:'sec-food2',name:'다코야키'}
    ]
  },
  {
    name:'food6',
    data:[
      {val:'sec-food1',name:'감자튀김'}
    ]
  },
  {
    name:'food7',
    data:[
      {val:'sec-food1',name:'라면'},
      {val:'sec-food2',name:'커피우유'},
      {val:'sec-food3',name:'과자'},
      {val:'sec-food3',name:'아이스크림'}
    ]
  }
]

 

See the Pen ZELXyqw by JNoony (@jnoony) on CodePen.

 

728x90

브라우저 환경에서 사용되는 최소한의 사용자 인터페이스 기능

 

1. 기본적인 사용방법

1) alert

메시지를 지정할 수 있는 경고 대화 상자

 

/*
* alert(message)
*/

var txt = 'alert! 경고!!';
function text(){ return 'alert! 경고!!' }

window.alert('alert! 경고!!')
alert('alert! 경고!!')
alert(txt)
alert(text())
//위의 4개의 alert는 동일한 결과를 도출한다

 

 

2) prompt

사용자가 텍스트를 입력할 수 있도록 안내하는 선택적 메세지를 갖고 있는 대화 상자

 

/*******************************************************
* prompt(title, [default]);
* Internet Explorer(IE)에서는 항상 '기본값’을 넣어주세요.
* prompt("Test", ''); <-- IE 사용자를 위한 매개변수 처리
********************************************************/

let year = prompt('오늘이 몇년도?', 2021);

alert(`오늘은 ${year}년 입니다.`); // 오늘은 2021년 입니다.

 

확인버튼 일경우 취소버튼 일경우
undefined : 값이 할당되지 않은 상태
null  :  존재하지 않는(nothing) 값, 비어 있는(empty) 값, 알 수 없는(unknown) 값

 

3) confirm

확인과 취소 두 버튼을 가지며 메시지를 지정할 수 있는 모달 대화 상자

 

/*******************************************************
* confirm(question);
********************************************************/

let tired = confirm('피곤하십니까?');

alert( tired ); // 확인 -> true,  취소 -> false

 

확인 취소
불린형 : true, false를 나타낼 때

 

 

 

2. 활용 - form

간단한 form을 짜서 유효성 검사 경고창을 띄어보자

<결과물>

See the Pen jOyVymr by JNoony (@jnoony) on CodePen.

 

 

728x90

유지보수나, 운영팀에 있다 보면 코드를 보고 발 빠르게 대처해야 한다. 

그러기 위해선 자신이 주력으로 사용하는 프로그래밍 언어에 대해 이해가 있어야 리소스를 덜 낭비하고 쉽게 처리할 수 있다.

하나의 레이아웃으로 여러 코드를 이용하여 그려보면 css를 깊게 활용할 수 있고, 다양한 이슈 상황에 대처하는 연습이 된다고 생각한다.

 

 

point ) visual과 cont 사이엔 빈 공간

 

1. float:left;

웹사이트의 화면은 포토샵의 레이아웃처럼 겹겹이 올리는 방식으로 스타일을 사용하고 있어 float:left 같은 레이아웃을 강제적으로 바꿔주는 코드는 많이 사용하면 할수록 웹브라우저의 반응속도가 더디게 된다.

요즘은 float보다 폭넓게 활용할수 있는 코드가 많이 업데이트됐기 때문에 지양하고 있지만 아직 많이 사용하고 있어 활용해보았다.

 

See the Pen BapLLgP by JNoony (@jnoony) on CodePen.

.Tip)

float:left를 너무 많이 쓰다보면 부모객체를 잃어버릴때가 있다. 

이렇게 되면 margin이나 padding값이 이상하게 먹거나 안먹히고, 자식객체들이 조금씩 틀어져서 나가는 경우가 발생한다.

이럴경우 필요에 따라 높이값을 줘도 되지만, 권장하지 않는다.

요즘은 반응형으로 제작을 하게 되는데 디바이스가 바뀔때마다 높이값을 조정하는 사태가 벌어지는데 이는 유지보수 하는데 좋은 방법이 아니기 때문이다.

대부분  부모객체에 overflow:hidden을 사용하게 되면 원만히 해결된다.

 

 

2. display:flex;

See the Pen jOyMVRW by JNoony (@jnoony) on CodePen.

 

 

3. display:grid;

728x90

'css' 카테고리의 다른 글

[scss] scss 컴파일 해보기  (1) 2022.08.07
[css] 도넛 차트 그리기  (0) 2021.06.03
[css+javascript] 룰렛  (1) 2021.04.21
[css] reset파일 만들기 귀찮을 때  (0) 2021.03.17
[css] 크로스브라우징  (0) 2021.03.17

원래 선배들부터 돌려쓰던 reset.css를 잃어버리고, 내가 일일이 작성하자니 귀찮아서 찾게 된 사이트다.

 

meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/

 

그래서 위 사이트에 적혀진 상태에서 필요한 부분 덧붙여 아래 코드는 내가 사용 중인 reset.css 코드이다.

 

@charset "utf-8";

html {
	font-family: 'Apple SD Gothic Neo', Roboto, 'Noto Sans KR', NanumGothic, 'Malgun Gothic', sans-serif;
	line-height: 1.2;
	word-wrap: break-word;
}
body {
	-webkit-font-smoothing: antialiased;
}

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
	margin: 0;
	padding: 0;
	border: 0;
	outline: 0;
	font-weight: inherit;
	font-style: inherit;
	font-size: 100%;
	font-family: inherit;
	vertical-align: baseline;
}

article, aside, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section {
	display: block;
}
div, span, article, section, header, footer, aside, 
p, ul, li, fieldset, legend, label, a, nav, form {
	box-sizing: border-box;
}
ol, ul, li {
	list-style: none;
}

:focus {
	outline: 0;
}
body {
	line-height: 1;
	color: black;
	background: white;
}

table {
	border-collapse: separate;
	border-spacing: 0;
}
caption, th, td {
	text-align: left;
	font-weight: normal;
}
blockquote:before, blockquote:after,
q:before, q:after {
	content: "";
}
blockquote, q {
	quotes: "" "";
}

img {
	max-width: 100%;
	height: auto;
	border: 0;
}
button {
	border: 0;
	background: transparent;
	cursor: pointer;
}
728x90

'css' 카테고리의 다른 글

[scss] scss 컴파일 해보기  (1) 2022.08.07
[css] 도넛 차트 그리기  (0) 2021.06.03
[css+javascript] 룰렛  (1) 2021.04.21
[css] 레이아웃 그리기  (0) 2021.03.30
[css] 크로스브라우징  (0) 2021.03.17

마이크로소프트에서도 포기한 IE를 아직도.. 우리나라는 사용하고 있기 때문에 예전에 배웠던 대로 IE8,9는 맞출 필요는 없지만 적어도 IE10+이상은 맞춰야 한다.

 

float:left의 남용이 웹브라우저 최적화를 저하시키기도 해서 지양하고 있기 때문에, 웹브라우저의 버전업과 함께 stylesheet도 점차 발전해가고 그에 맞춰 편하게 레이아웃을 조정할 수 있도록 나온 display:grid를 사용하고 싶지만 IE10에서는 지원하지 않기 때문에.. ㅜㅜ 그나마 핵사용이라도 해서 display:flex로 레이아웃 스타일을 활용하고 있다.

 

하지만 아무리 맞춰도.. 한계는 있는 법.

 

웬만하면 크롬/웨일 막 요런 거 쓰자..

 

1. css에서 IE만 반영 

/* IE10+ */
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
 /* Enter your style code */
}
 
/* IE6,7,9,10 */
@media screen and (min-width: 640px), screen\9 {
 /* Enter your style code */
}
 
/* IE6,7 */
@media screen\9 {
 /* Enter your style code */
}
 
/* IE8 */
@media \0screen {
 /* Enter your style code */
}
 
/* IE6,7,8 */
@media \0screen\,screen\9 {
 /* Enter your style code */
}
 
/* IE9,10 */
@media screen and (min-width:0\0){
 /* Enter your style code */
} 

 

2. HTML에서 IE만 반영하는 stylesheet 링크 사용

<!--[if IE]>
<link rel="stylesheet" type="text/css" href="only-ie.css" />
<![endif]-->


<!--[if IE]>
<style>
    /* Enter your style code */
    /* 몇개 수정할 경우 사용, 웬만하면 링크 걸자. 브라우저 속도를 위해 */
</style>
<![endif]--> 

 

3. 접두어사용

 -ms-      : Edge / Internet Explorer에서 지원
 -moz-    : Firefox 지원
 -webkit- : Google 크롬, Safari에서 지원
 -o-        : Opera에서 지원

 

 

 

 

 

 

 

docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/compatibility/ms537512(v% 3d vs.85)
728x90

'css' 카테고리의 다른 글

[scss] scss 컴파일 해보기  (1) 2022.08.07
[css] 도넛 차트 그리기  (0) 2021.06.03
[css+javascript] 룰렛  (1) 2021.04.21
[css] 레이아웃 그리기  (0) 2021.03.30
[css] reset파일 만들기 귀찮을 때  (0) 2021.03.17
underscorejs.org/
 

Underscore.js

Underscore is a JavaScript library that provides a whole mess of useful functional programming helpers without extending any built-in objects. It’s the answer to the question: “If I sit down in front of a blank HTML page, and want to start being produc

underscorejs.org

<script src="https://cdn.jsdelivr.net/npm/underscore@1.12.1/underscore-esm-min.js"></script>

GitHub에서도 개발자들이 많이 사용하고 있는 유명한 함수형 자바스크립트라고 참조하여 공부 중인 책에서 사용하는 것을 권장하고 있는 javascript 라이브러리다.

사용할 인자들을 더 제공하여 다양한 로직을 짤 수 있다길래 한번 사용해 봐야겠다.

 

1. 인자 늘리기

See the Pen rNWbqzY by JNoony (@jnoony) on CodePen.

 

 

2.function identity(v) {return v;}

_.identity = function(v){ return v; };
var a = 10;
console.log( _.ientity(a) ); // 10

 

Underscore.js에서 제공하는 _. identity 함수.

기본 함수에 수식이 없어  변수안에 담아놓은 10이 당연히 리턴한 값이 된다.

 

 

See the Pen eYBojQa by JNoony (@jnoony) on CodePen.

 

Truthy Values( Boolean으로 평가했을 때 true로 평가되는 값들 )만 남았다. 

책 저자는 _.identity를 자만 이용하면 유용한 함수들을 만들 수 있다고 평가하고 있다.

 

/* 참고 */
_.falsy = function(v){ return !v;}
_.truthy = function(v){ return !!v;}

 

See the Pen bGBJQWo by JNoony (@jnoony) on CodePen.

 

some은 배열중 하나라도 참이면 true를, 하나도 없다면 false를 리턴하고,  every는 모두가 참일 때 true를 리턴한다.

 

 

 

728x90

회원 목록 중 한 명 찾기

1. 재사용 할수 있는 코드 && 없는 코드

데이터 리스트를 임의로 정의해보자

var users = [
    {id:1,name:"Hoon",age:27},
    {id:2,name:"woong",age:29},
    {id:3,name:"jimin",age:26},
    {id:4,name:"K",age:32},
    {id:5,name:"Tom",age:28},

    {id:6,name:"TT",age:32},
]

 

/** 재사용 할수 없는 코드 **/
var user;
for(var i =0,len=user.length;i<len;i++){
    if(users[i].id == 3){
        user = users[i];
        break;
    }
} 
console.log( user ); // {id:3,name:"jimin",age:26}



/** 재사용 할수 있는 코드 **/
function findById(list,id){
    for(var i=0,len=list.length;i<len;i++){
        if( list[i].id == id) return list[i]
    }
}
console.log( findById(users,3) );  //{id: 3, name: "jimin", age: 26}

 

위와 같은 코드는 재사용할 수 있지만, 회원 리스트에서 아이디 값뿐 아니라, 나이, 이름으로도 찾고 싶을 수도 있는데 이럴 때마다 함수를 생성/선언해야 하기 때문에 위 코드는 함수 형적이지 않다.

 

 

2. 함수형 코드 만들기

function findBy(list,key,val){
    for(var i=0,len=list.length;i<len;i++){
        if( list[i][key] === val ) return list[i]
    }
}
console.log( findBy(users,'name','Hoon') ) //{id: 1, name: "Hoon", age: 27}

 

인자 값 key에 객체의 key값과 찾고자 하는 value값으로 찾을 수 있게 된 함수이다. 

하지만, 더 많은 예외가 있을 경우 처리가 어렵다

  • key가 아닌 메서드를 통해 값을 얻어야 할 때
  • 두 가지 이상 조건이 필요할 때
  • ===이 아닌 다른 조건으로 찾고자 할 때

filter나 map처럼 인자로 키와 값 대신 함수를 사용하여 모든 상황에 대응 가능한 find함수를 만들어보자

function User(id,name,age){
    this.getId = function(){
       return id;
    }
    this.getName = function(){
       return name;
    }
    this.getAge = function(){
       return age;
    }
}
/* 새로운 데이터 리스트 생성 */
var users2 = [
    new User(1,'ID',32),
    new User(2,'AD',25),
    new User(3,'MJ',28),
    new User(4,'BJ',29),
    new User(5,'HA',24),
    new User(6,'HO',32),
]

/* 값대신 함수를 받아 처리 */
// 인자 predicate안에 함수식
// 인자 list 는 본문 맨위에 선언한 데이터
function find(list,predicate){
    for(var i=0,len=list.length;i<len;i++){
        if(predicate(list[i])) return list[i]
    }
}

console.log(
    find( users2, function(u){return u.getAge() == 25;} ).getName()
) // AD
console.log(
    find( users, function(u){return u.name.indexOf('j') != -1;} )
) // {id: 3, name: "jimin", age: 26}
console.log(
    find( users, function(u){return u.age == 32 && u.name == 'K'} )
) // {id: 4, name: "K", age: 32}
console.log(
    find( users2, function(u){return u.getAge() > 30} ).getName()
) // ID

 

 

3. 고차 함수 만들기

고차 함수란 함수를 인자로 받거나 함수를 리턴하는 함수
- 함수를 인자로 받아 필요한 때에 실행하거나 클로저를 만들어 리턴

find의 인자 predicate를 함수로 만들어서 인자 값 고차 함수 만들기

 

function bmatch1(key,val){
    return function(obj){
        return obj[key] === val;
    }
}
console.log( find(users, bmatch1('id',3) ) )        // {id: 3, name: "jimin", age: 26}
console.log( find(users, bmatch1('name','Hoon') ) ) // {id: 1, name: "Hoon", age: 27}
console.log( find(users, bmatch1('age',32) ) )      // {id: 4, name: "K", age: 32}

/**************************
*  여러 데이터 불러오기
*  전에 만들어뒀던 filter, map 활용 예):
***************************/
function filter(list, predicate){
    var new_list = [];
    for(var i=0,len=list.length; i<len; i++){
    	if(predicate(list[i])) new_list.push(list[i]);
    }
    return new_list;
}

function map(list, iteratee){
    var new_list = [];
    for(var i =0,len=list.length;i<len;i++){
        new_list.push(iteratee(list[i]));
    }
    return new_list;
}
console.log( filter(users, bmatch1('age',32) ) ) // 0: {id: 4, name: "K", age: 32}, 
                                                 // 1: {id: 6, name: "TT", age: 32}

 

 

4. 비교하는 함수 만들기

function object(key,val){
    var obj = {};
    obj[key] = val;
    return obj;
}

function match(obj,obj2){
    for(var key in obj2){
        if(obj[key] !== obj2[key]) return false;
    }
    return true;
}

function bmatch(obj2,val){
    if(arguments.length == 2) obj2 = object(obj2,val);
    return function(obj){
       return match(obj,obj2);
    }
}

console.log(
   match( find(users, bmatch('id',3)), find(users, bmatch('name','jimin')) )
) // true

console.log(
   find(users, function(u){return u.age == 32 && u.name == 'TT'}) 
) //{id: 6, name: "TT", age: 32}

 

 

 

>> [ 위 코드들 통합 ]

See the Pen qBqGNme by JNoony (@jnoony) on CodePen.

 

[출처::책] 함수형 자바스크립트
http://book.interpark.com/product/BookDisplay.do?_method=detail&sc.prdNo=272822398&gclid=EAIaIQobChMIi739ieqR7wIVOcEWBR2CgwMxEAQYASABEgLcrvD_BwE
728x90

+ Recent posts