이번에 프로젝트가 끝나가면서 rgb색상으로 그라데이션을 만드는 기능을 추가해야 할 일이 있었다.
기존 : 2가지 rgb색상으로 데이터의 개수 만큼 그라데이션을 만듦
추가 : 3가지 rgb색상으로 데이터의 개수 만큼 그라데이션을 만듦
추가 되는 기능은 기존 2가지 rgb색상에 흰색을 추가하여, 중간값은 하얀색으로 나오게 하는 것이었다.
데이터의 개수에 따라 그라데이션 개수도 달라진다.
기존: 3개의 데이터가 있다면, 흰색->빨강으로 그라데이션 생성 |
이번에 이거 만들면서 기존에 짜여진 코드 보고 이걸 어떻게 짰지.. 하면서 정리 해놓으려 한다.
자세한 내용은 아래 링크에서 확인하길 ( 자세히 적혀 있음 )
https://zzang9iu.tistory.com/31
그럼 바로 시작해보자.
============================================================================
1. 그라데이션으로 사용할 색상을 담은 배열을 하나 만들어준다.
colorList : {
red : [
[255,204,204], [255,181,181], [255,159,159], [255,136,136], [255,113,113],
[255,91,91], [255,68,68], [255,45,45], [255,23,23], [255,0,0]
]
}
red라는 연한빨강->진한빨강으로 가는 배열이다. 각 배열 안에는 rgb코드가 들어 있음.
2. 그라데이션을 입힐 데이터 객체 생성
data1 = {
'54852': {'count': 102},
'55160': {'count': 26},
'64749': {'count': 12},
'69400': {'count': 62},
'79523': {'count': 48}
};
객체가 5개 들어있는 data1이라는 객체를 하나 만들었다. 이제 이 데이터의 순서( 오름차순 또는 내림차순)으로
그라데이션을 만들고 싶다. 작은 값은 연하게, 값이 높아질수록 진하게... 5개의 데이터게 그라데이션 색상을 넣어보자.
여기서 color Mixer 홈페이지에서 사용하는 interpolateHSL라는 함수를 가져왔다.
interpolateHSL
interpolateHSL= function(color1, color2, factor) {
var hsl1 = app.util.rgb2hsl(color1); --color1 : colorList.red[0]
var hsl2 = app.util.rgb2hsl(color2); --color2 : colorList.red[9]
for (var i=0;i<3;i++) {
hsl1[i] += factor*(hsl2[i]-hsl1[i]);
}
return app.util.hsl2rgb(hsl1);
-- hsl2rgb() : hsl코드를 rgb코드로 변환
-- rgb2hsl() : rgb코드를 hsl코드로 변환
};
이 함수는 인자를 color1, color2, factor를 받는다. 여기서 color1, color2는 특정 지점을 의미한다.
( hsl2rgb함수 및 rgb2hsl함수는 아래 링크 참조 )
우선 그라데이션을 만들기 위해서는 두 지점을 선택해줘야 한다.
아래 그림은 위에서 설정한 colorList를 색상표로 그린것이다.
이제 내가 그라데이션으로 주고 싶은 선택지점을 선택해줘야 한다.
여기서 선택지점1은 colorList.red[0]이 될 것이고, 선택지점2는 colorList.red[9]가 될 것이다.
물론 그라데이션의 값을 조금 더 딱딱하게 하고 싶으면 colorList.red[3] ~ colorList.red[5] 처럼 유동적으로 변경이
가능하다.
그럼 실제로 배경색을 입혀보자..
우선 데이터 리스트(data1)을 화면에 목록으로 나타내준다.
따로 오름차순으로 정렬은 안해주었다. 이제 색 넣기 버튼을 누르면 목록에 그라데이션이 들어가도록 만들었다.
우선 색넣기 버튼을 누르면 insertColor라는 함수를 호출하여, interpolateHSL함수에 파라메터를 전달하는 역할을 한다.
설명은 나중에 코드를 보면서 하고, 저 버튼을 클릭하면 아래와 같이 된다.
물론 ColorList의 값을 바꾸면 색도 변하게 된다.
아래는 작성코드이다.
colorTest.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.12.4.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript" src="<c:url value='/js/colorTest.js' />"></script>
</head>
<style>
/*
테이블 스타일을 주기 위해 추가.
*/
div {
border: 1px solid #bcbcbc;
}
.jb-table {
display: table;
width: 100%;
}
.jb-table-row {
display: table-row;
}
td {border: solid;}
</style>
<body>
<div id="color">
<color-list></color-list> <!-- 실제 테이블이 생성되는 컴포넌트 -->
</div>
</body>
</html>
colorTest.js
$(document).ready(function() {
Vue.component('color-list',{
/*
* 화면에 표시 될 템플릿
* 데이터 목록인 data1의 배열을 돌려 화면에 뿌려주고,
* style을 데이터 바인딩하여, backgroud를 setColor에서 리턴해주는 값으로 채워주고 있다.
* 실제로 rgb등 그라데이션 작업을 한 결과를 리턴한다.
* 색넣기 버튼을 누르면 insertColor함수를 호출
* */
template : `<div>
<table class="jb-table">
<tr v-for="(data,index) in data1" class="jb-table-row">
<td class="jb-table-cell" :style="{background : setColor(index)}">{{data.count}}</td>
</tr>
</table>
<input type="button" value="색넣기" @click="insertColor">
</div>
`,
data (){
return{
/*
* colorList : 실제 그라데이션을 생성할 때 사용되며, RGB색상표에서 원하는 색을 배열로 생성한다.
* data1 : 화면에 표출 될 목록 데이터. 데이터가 많아질수록 그라데이션이 부드러워진다.
* createdColorList : data1의 길이만큼 그라데이션을 생성한 결과가 담겨지는 배열. 실제 목록의 background 컬러가 됨
* */
colorList : {
red : [
[255,204,204], [255,181,181], [255,159,159], [255,136,136], [255,113,113],
[255,91,91], [255,68,68], [255,45,45], [255,23,23], [255,0,0]
],
blue : [
[204,204,255], [181,181,255], [159,159,255], [136,136,255], [113,113,255],
[91,91,255], [68,68,255], [45,45,255], [23,23,255], [0,0,255]
],
redblue : [
[255,0,0], [227,0,28],[198,0,57] ,[170,0,85], [142,0,113],
[113,0,142], [85,0,170], [57,0,198], [28,0,227] ,[0,0,255]
],
},
data1 : [
{'count': 102},
{'count': 26},
{'count': 12},
{'count': 62},
{'count': 48}
],
createdColorList : []
}
},
methods :{
/*
* color1, color2 : data에서 설정한 colorList에서 원하는 배열의 값을 적재
* 배열 index의 차이가 커질수록 그라데이션이 부드러워짐
* factor : (1 / (rgb 컬럼을 만들 갯수(data1) - 1)) * idx;
*/
insertColor : function(){
var color1 = this.colorList.red[0];
var color2 = this.colorList.red[9];
var factor = 1/ (Object.keys(this.data1).length -1);
for(var i=0;i<Object.keys(this.data1).length;i++){// data1의 길이만큼 for문 실행
//data1의 길이 만큼 interpolateHSL를 호출하여, createdColorList배열에 push함
this.createdColorList.push(this.interpolateHSL(color1,color2,factor*i));
}
console.log(this.createdColorList);
},
interpolateHSL : function(color1, color2, factor) {
// 각 color1, color2를 hsl코드로 변환
var hsl1 = this.rgb2hsl(color1);
var hsl2 = this.rgb2hsl(color2);
for (var i=0;i<3;i++) {
hsl1[i] += factor*(hsl2[i]-hsl1[i]);
}
//hsl코드를 rgb코드로 변환하여 리턴
return this.hsl2rgb(hsl1);
},
setColor : function(index){
// 실제로 background에 들어 갈 스타일 생성후 리턴해줌
if(this.createdColorList[0]!=undefined){
return "rgb("+this.createdColorList[index].join(',')+")";
}else{
return false;
}
},
rgb2hsl : function(color) {
var r = color[0]/255;
var g = color[1]/255;
var b = color[2]/255;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if (max == min) {
h = s = 0; // achromatic
} else {
var d = max - min;
s = (l > 0.5 ? d / (2 - max - min) : d / (max + min));
switch(max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return [h, s, l];
},
hsl2rgb : function(color) {
var l = color[2];
if (color[1] == 0) {
l = Math.round(l*255);
return [l, l, l];
}
else {
function hue2rgb(p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
}
var s = color[1];
var q = (l < 0.5 ? l * (1 + s) : l + s - l * s);
var p = 2 * l - q;
var r = hue2rgb(p, q, color[0] + 1/3);
var g = hue2rgb(p, q, color[0]);
var b = hue2rgb(p, q, color[0] - 1/3);
return [Math.round(r*255), Math.round(g*255), Math.round(b*255)];
}
}
}
});
new Vue({
el : '#color'
})
});
참고로 가운데는 특정 색을 넣고 싶으면 이렇게 하면 된다.
다른 부분을 같고, 새 배열에 push하는 곳만 변경해주면 된다.
var redWhiteblue : [
[255,0,0], [255,68,68], [255,136,136], [255,204,204], [255,255,255],
[181,181,255], [204,204,255], [136,136,255], [68,68,255], [0,0,255]
]
var factor = 1/ ([갯수만큼 만들 객체 또는 배열] -1);
var factor2 = factor;
factorStep = 4/(Object.keys([객체]).length -1);
//빨강 -> 연빨강 ( 중간에서 -1개까지 )
for(var i=0;i<(Math.floor(Object.keys([객체]).length/2));i++){
this.createdColorList.push(this.interpolateHSL(this.redWhiteBlue[0], this.redWhiteBlue[1], factor*i));
}
//정가운데 흰색 넣음
this.createdColorList.push(app.util.interpolateHSL(this.redWhiteBlue[4], this.redWhiteBlue[4], factor*Math.floor(Object.keys([객체]).length/2)));
//정가운데 이상부터 연파랑 -> 파랑
for(var i=Math.floor(Object.keys([객체]).length/2);i<Object.keys([객체]).length;i++){
this.createdColorList.push(this.interpolateHSL(this.redWhiteBlue[6], this.redWhiteBlue[9], factor2*i));
}
이렇게 하면 된다. 예를 들면 50개의 데이터 목록이 있으면 그것을 반으로 나눈 뒤 -1을 해준다.
그럼 0~23까지는 빨강색이 그라데이션 된 뒤 createdColorList에 적재하고, 24에는 흰색을 넣은 뒤,
25~50번까지 그라데이션 된 파랑색을 넣는다. 결과는 아래와 같다.
이해하기 보다는 이 코드들을 가지고 필요할 때 활용할 수 있으면 좋겠다.
'FrontEnd > JavaScript' 카테고리의 다른 글
[JS] ES6문법 : import와 export에 대해서 알아보자. (0) | 2022.02.14 |
---|---|
[JS] setTimeOut 함수를 이용하여 동작 시간을 조정해보자 (0) | 2022.02.13 |
[JS] rgb코드를 hsl코드로, hsl코드를 rgb코드로 변환해보자. (0) | 2022.02.11 |
[JS] javascript에서 Object(객체)의 길이 값을 구해보자. (0) | 2022.02.11 |
[JS] javascript : push 함수와 concat 함수를 차이점을 알아보자. (0) | 2022.02.03 |