JavaScript HSL 픽업 실현

14508 단어 jsHSL주 색 기
HSL 과 HSV 는 수학 적 으로 RGB 공간 에 있 는 색상 의 R,G,B 의 좌표 변환 으로 정의 된다.
RGB 에서 HSL 또는 HSV 로 의 전환
설정(r,g,b)은 각각 색깔 의 빨간색,녹색,파란색 좌표 이 고 그들의 값 은 0 에서 1 사이 의 실수 이다.max 등가 r,g,b 의 최대 자 를 설정 합 니 다.min 을 설정 하면 이 값 중 가장 작은 것 입 니 다.HSL 공간 에서(h,s,l)값 을 찾 으 려 면 여기 h*8712°0,360)은 각도 의 색상 각 이 고 s,l*8712°0,1]은 포화 도와 밝기 로 계산 합 니 다.

h 의 값 은 보통 0 에서 360°사이 로 규범화 된다.h=0 은 max=min(회색)에 사 용 될 때 h 가 정의 되 지 않 은 것 이 아 닙 니 다.
HSL 과 HSV 는 같은 색상 으로 정의 되 지만 다른 분량 은 다르다.HSV 색상 의 s 와 v 의 값 정 의 는 다음 과 같 습 니 다.

HSL 에서 RGB 로 의 전환
HSL 공간 에 있 는(h,s,l)값 을 정의 하 는 색상 입 니 다.h 가 색상 각 도 를 표시 하 는 값 영역[0,360)에서 포화 도와 밝 기 를 나타 내 는 s 와 l 은 값 영역[0,1]에서 RGB 공간 에 해당 하 는(r,g,b)3 원색 으로 빨간색,녹색 과 파란색 에 대응 하 는 r,g 와 b 도 값 영역[0,1]에서 계산 할 수 있 습 니 다.
우선,s=0 이면 결 과 는 비 컬러 또는 회색 입 니 다.이 특수 한 상황 에서 r,g,b 는 모두 l 과 같다.이 경우 h 의 값 이 정의 되 지 않 았 음 을 주의 하 십시오.
s≠0 일 때 다음 과정 을 사용 할 수 있다.

색상 별 벡터 색상=(ColorR,ColorG,ColorB)=(r,g,b),

HSV 에서 RGB 로 의 전환
이와 유사 한 것 은 HSV 에서(h,s,v)값 을 정의 하 는 색상 입 니 다.위의 h 와 포화 도와 밝 기 를 나타 내 는 s 와 v 는 0 에서 1 사이 로 변화 하고 RGB 공간 에서 대응 하 는(r,g,b)삼원 색 은 다음 과 같이 계산 할 수 있 습 니 다.

색상 별 벡터(r,g,b),

<html>
  <style>
    .childDiv {
      display:inline-block;  
      vertical-align:middle;
      margin-left: 30px;
      margin-top: 10px;
      margin-bottom: 10px;
    }
    #colorPickDiv {
      background-color: WhiteSmoke;
      border: 1px solid LightGrey;
      padding-top: 20px;
      padding-bottom: 20px;
      padding-right: 30px;
    }
    #hueTipDiv {
      margin: 0 0 10px 70px;
    }
    #luminanceTipDiv {
      margin-top: 20px
    }
    #colorDiv {
      width: 100px;
      height: 100px;
      background-color: black;
    }
    #valueDiv {
      box-shadow: 0px -5px 10px LightGrey;
      background-color: WhiteSmoke;
      border: 1px solid LightGrey;
      border-top-width: 0;
      padding-right: 10px;
      padding-bottom: 10px;
    }
  </style>
  <body>
    <div>
      <div id="colorPickDiv">
        <div class="childDiv">
          <div id="hueTipDiv">Hue:0</div>
          <canvas id="canvas" width="200" height="200">Your browser does not support canvas</canvas>
        </div>
        <div class="childDiv">
          <div id="saturationTipDiv" class="divMarginBottom">Saturation:0%</div>
          <input id="saturationRange" onChange="onHSLRangeChange()" type="range" min="0" max="100" step="1" value="100"/>
          <div id="luminanceTipDiv" class="divMarginBottom">Luminance:0%</div>
          <input id="luminanceRange" onChange="onHSLRangeChange()" type="range" min="0" max="100" step="1" value="50"/>
        </div>
        <div id="colorDiv" class="childDiv"></div>
      </div>
      <div id="valueDiv">
        <div class="childDiv">
          <div id="hexadecimalTipDiv" class="divMarginBottom">Hexadecimal:</div>
          <input id="hexadecimalValueDiv" type="text" disabled="disabled"/>
        </div>
        <div class="childDiv">
          <div id="rgbTipDiv" class="divMarginBottom">RGB:</div>
          <input id="rgbValueDiv" type="text" readonly="readonly"/>
        </div>
        <div class="childDiv">
          <div id="hslTipDiv" class="divMarginBottom">HSL:</div>
          <input id="hslValueDiv" type="text" readonly="readonly"/>
        </div>
      </div>
    </div>
    <script>
      var c = document.getElementById("canvas");
      var ctx = c.getContext("2d");
      var colorDiv = document.getElementById("colorDiv");
      var hexadecimalValueDiv = document.getElementById("hexadecimalValueDiv");
      var rgbValueDiv = document.getElementById("rgbValueDiv");
      var hslValueDiv = document.getElementById("hslValueDiv");
      var hexadecimalTipDiv = document.getElementById("hexadecimalTipDiv");
      var saturationTipDiv = document.getElementById("saturationTipDiv");
      var saturationRange = document.getElementById("saturationRange");
      var luminanceTipDiv = document.getElementById("luminanceTipDiv");
      var luminanceRange = document.getElementById("luminanceRange");

      //      
      var crossCursorColor = "black";
      //      
      var crossCursorLineWidth = 2;
      //          
      var crossCursorHalfLineLen = 5;
      //           
      var crossCursorHalfBreakLineLen = 2;

      //     X  
      var centerX = c.width / 2;
      //     Y  
      var centerY = c.height / 2;
      //      
      var scaleRate = 10;
      //        (                      )
      var innerRadius = Math.min(centerX, centerY) - crossCursorHalfLineLen - crossCursorHalfBreakLineLen;
      //        
      var pow2InnerRadius = Math.pow(innerRadius, 2);
      //          ,            
      var scaledRadius = Math.sqrt(Math.pow(c.width / 2, 2) + Math.pow(c.height / 2, 2)) / scaleRate;
      //                ,           
      var count = 360;
      //        
      var doublePI = Math.PI * 2;
      //              ,Composite source-over  ,                。           ,  
      var deprecatedRadius = innerRadius * 0.3;
      //        
      var pow2DeprecatedRadius = Math.pow(deprecatedRadius, 2);

      //  (0-360)
      var hue;
      //   (0%-100%)
      var saturation; 
      //  luminance   lightness(0%-100%)
      var luminance;

      //      X  
      var currentHuePosX = centerX + innerRadius - 1;
      //      Y  
      var currentHuePosY = centerY;

      //   
      function fillCircle(cx, cy, r, color) {
        ctx.fillStyle = color;
        ctx.beginPath();
        ctx.arc(cx, cy, r, 0, doublePI);
        ctx.fill();
      }

      //    
      function strokeLine(x1, y1, x2, y2) {
        ctx.beginPath();
        ctx.moveTo(x1, y1);
        ctx.lineTo(x2, y2);
        ctx.stroke();
      }

      //     16  ,    2 
      function toHexString(intValue) {
        var str = intValue.toString(16);
        if(str.length == 1) {
          str = "0" + str;
        }
        return str;
      }

      //    (x,y)         
      function isInValidRange(x, y) {
        var pow2Distance = Math.pow(x-centerX, 2) + Math.pow(y-centerY, 2);
        return pow2Distance >= pow2DeprecatedRadius && pow2Distance <= pow2InnerRadius;
      }

      //      
      function strokeCrossCursor(x, y) {
        ctx.globalCompositeOperation = "source-over";
        ctx.strokeColor = crossCursorColor;
        ctx.lineWidth = crossCursorLineWidth;
        strokeLine(x, y-crossCursorHalfBreakLineLen, x, y-crossCursorHalfBreakLineLen-crossCursorHalfLineLen);
        strokeLine(x, y+crossCursorHalfBreakLineLen, x, y+crossCursorHalfBreakLineLen+crossCursorHalfLineLen);
        strokeLine(x-crossCursorHalfBreakLineLen, y, x-crossCursorHalfBreakLineLen-crossCursorHalfLineLen, y);
        strokeLine(x+crossCursorHalfBreakLineLen, y, x+crossCursorHalfBreakLineLen+crossCursorHalfLineLen, y);
      }

      //     hsl      hsl  (h 0 360  ,s l  0 1  )
      function formHslColor(obj) {
        return "hsl(" + obj.h + "," + Math.round(obj.s * 1000)/10 + "%," + Math.round(obj.l * 1000)/10 + "%)"; 
      }

      //     rgb      rgb  (r,g,b 0 255  )
      function formRgbColor(obj) {
        return "rgb(" + [obj.r, obj.g, obj.b].join(",") + ")";
      }

      //          RGB   
      function getRgbObj(x, y) {
        var w = 1;
        var h = 1;
        var imgData = ctx.getImageData(x,y,w,h);
        var obj = {
          r: imgData.data[0],
          g: imgData.data[1],
          b: imgData.data[2],
          a: imgData.data[3]
        }
        return obj;
      }

      // rgb   hsl  ()
      function rgbToHslObj(r, g, b) {
        r /= 255;
        g /= 255;
        b /= 255;
        var max = Math.max(r, g, b);
        var min = Math.min(r, g, b);
        var diff = max - min;
        var twoValue = max + min;
        var obj = {h:0, s:0, l:0};
        if(max == min) {
          obj.h = 0;
        } else if(max == r && g >= b) {
          obj.h = 60 * (g - b) / diff;
        } else if(max == r && g < b) {
          obj.h = 60 * (g - b) / diff + 360;
        } else if(max == g) {
          obj.h = 60 * (b - r) / diff + 120;
        } else if(max == b) {
          obj.h = 60 * (r - g) / diff + 240;
        }
        obj.l = twoValue / 2;
        if(obj.l == 0 || max == min) {
          obj.s = 0;
        } else if(0 < obj.l && obj.l <= 0.5) {
          obj.s = diff / twoValue;
          //obj.s = diff / (2 * obj.l);
        } else {
          obj.s = diff / (2 - twoValue);
          //obj.s = diff / (2 - 2 * obj.l);
        }
        obj.h = Math.round(obj.h);
        return obj;
      }

      //  Hue    
      function createHueRing() {
        ctx.globalCompositeOperation = "source-over";
        ctx.clearRect(0,0,c.width,c.height);
        ctx.save();
        //            
        ctx.translate(centerX, centerY);
        //         ,restore ,       
        ctx.scale(scaleRate, scaleRate);
        for(var i=0; i<count; i++) {
          var degree = i / count * 360;
          var radian = Math.PI * degree / 180;
          var x = scaledRadius * Math.cos(radian);
          var y = scaledRadius * Math.sin(radian);
          ctx.lineWidth=1;
          ctx.strokeStyle = "hsl(" + degree +"," + saturation + "," + luminance + ")";
          ctx.beginPath();
          ctx.moveTo(x, y);
          ctx.lineTo(0,0);
          ctx.stroke();
        }
        ctx.restore();
        ctx.globalCompositeOperation = "destination-out";
        fillCircle(centerX, centerY, deprecatedRadius, "black");

        ctx.globalCompositeOperation = "destination-in";
        fillCircle(centerX, centerY, innerRadius, "black");
      }

      //  canvas  Hue   
      function onCanvasClick() {
        var x = event.offsetX;
        var y = event.offsetY;
        if(!isInValidRange(x, y)) {
          return;
        }
        currentHuePosX = x;
        currentHuePosY = y;
        //  hue    
        createHueRing();
        setColorValue(x, y);
        strokeCrossCursor(x, y);
      }

      function setColorValue(x, y) {
        //    rgb     
        var rgbObj = getRgbObj(x, y);
        var rgbColor = formRgbColor(rgbObj);
        colorDiv.style.backgroundColor = rgbColor;
        rgbValueDiv.value = rgbColor;
        var hex = "#" + toHexString(rgbObj.r) + toHexString(rgbObj.g) + toHexString(rgbObj.b);
        hexadecimalValueDiv.value = hex;

        var hslObj = rgbToHslObj(rgbObj.r, rgbObj.g, rgbObj.b);
        hslValueDiv.value = formHslColor(hslObj);
        hueTipDiv.innerHTML = ("Hue:" + hslObj.h);
      }

      function onHSLRangeChange() {
        //event.target.value;
        saturation = saturationRange.value + "%";
        luminance = luminanceRange.value + "%";
        saturationTipDiv.innerHTML = ("Saturation:" + saturation);
        luminanceTipDiv.innerHTML = ("Luminance:" + luminance);
        createHueRing();
        setColorValue(currentHuePosX, currentHuePosY)
        strokeCrossCursor(currentHuePosX, currentHuePosY);
      }

      function init() {
        c.addEventListener("click", onCanvasClick);
        onHSLRangeChange();
      }

      init();

    </script>
  </body>
</html>


몇 가지 결함 이 있 습 니 다.
-색상 값 에 따라 HSL 을 설정 할 수 없습니다.
-HSL 의 값 은 Hue 링 팔레트 에서 꺼 낸 RGB 색상 값 에 따라 HSL 로 환산 되 므 로 슬라이더 의 값 과 차이 가 있 을 수 있 음(5 사 6 입 이면 마찬가지)
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기