개발공작소
article thumbnail
728x90
반응형

이번에 프로젝트가 끝나가면서 rgb색상으로 그라데이션을 만드는 기능을 추가해야 할 일이 있었다.

 

기존 : 2가지 rgb색상으로 데이터의 개수 만큼 그라데이션을 만듦

추가 : 3가지 rgb색상으로 데이터의 개수 만큼 그라데이션을 만듦

 

추가 되는 기능은 기존 2가지 rgb색상에 흰색을 추가하여, 중간값은 하얀색으로 나오게 하는 것이었다.

데이터의 개수에 따라 그라데이션 개수도 달라진다.


기존: 3개의 데이터가 있다면, 흰색->빨강으로 그라데이션 생성

이번에 이거 만들면서 기존에 짜여진 코드 보고 이걸 어떻게 짰지.. 하면서 정리 해놓으려 한다.

자세한 내용은 아래 링크에서 확인하길 ( 자세히 적혀 있음 )

https://zzang9iu.tistory.com/31

 

내가 원하는 갯수 만큼 rgb색상을 그라데이션으로 만들기.

프로젝트를 하던 중 rgb컬럼을 데이터의 양만큼 만들일이 있었다. 랜덤색상일 경우 랜덤함수를 돌려 rgb컬러를 생성하면 되지만 예를 들어 빨강색부터 파랑색까지 100개의 rgb컬러를 그라데이션으

zzang9iu.tistory.com

그럼 바로 시작해보자.

============================================================================

 

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함수는 아래 링크 참조 )

https://bongra.tistory.com/96

 

[JS] rgb코드를 hsl코드로, hsl코드를 rgb코드로 변환해보자.

이번에 그라데이션을 정리할 때 쓴 코드인데, 외울 필요도 없고 왜 이렇게 되는 지 이해 할 필요도 없다. 그냥 아래거 갖다쓰면 된다. 물론 공부하고 싶은 사람은 공부해도 상관 없지만.. 여기서

bongra.tistory.com

 

우선 그라데이션을 만들기 위해서는 두 지점을 선택해줘야 한다.

아래 그림은 위에서 설정한 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번까지 그라데이션 된 파랑색을 넣는다. 결과는 아래와 같다.

 

이해하기 보다는 이 코드들을 가지고 필요할 때 활용할 수 있으면 좋겠다.

 

728x90
반응형
profile

개발공작소

@모찌바라기

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!