마우스 아래에서 RGB 값 픽셀을 얻을 수 있습니까? 이것에 대한 완전한 예가 있습니까? 지금까지 내가 가진 내용은 다음과 같습니다.
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.src = 'Your URL';
img.onload = function(){
ctx.drawImage(img,0,0);
};
canvas.onmousemove = function(e) {
var mouseX, mouseY;
if(e.offsetX) {
mouseX = e.offsetX;
mouseY = e.offsetY;
}
else if(e.layerX) {
mouseX = e.layerX;
mouseY = e.layerY;
}
var c = ctx.getImageData(mouseX, mouseY, 1, 1).data;
$('#ttip').css({'left':mouseX+20, 'top':mouseY+20}).html(c[0]+'-'+c[1]+'-'+c[2]);
};
}
답변
다음은 완전한 독립형 예제입니다. 먼저 다음 HTML을 사용하십시오.
<canvas id="example" width="200" height="60"></canvas>
<div id="status"></div>
그런 다음 캔버스에 임의의 배경색으로 사각형을 배치합니다.
var example = document.getElementById('example');
var context = example.getContext('2d');
context.fillStyle = randomColor();
context.fillRect(0, 0, 50, 50);
context.fillStyle = randomColor();
context.fillRect(55, 0, 50, 50);
context.fillStyle = randomColor();
context.fillRect(110, 0, 50, 50);
마우스 오버시 각 색상을 인쇄합니다.
$('#example').mousemove(function(e) {
var pos = findPos(this);
var x = e.pageX - pos.x;
var y = e.pageY - pos.y;
var coord = "x=" + x + ", y=" + y;
var c = this.getContext('2d');
var p = c.getImageData(x, y, 1, 1).data;
var hex = "#" + ("000000" + rgbToHex(p[0], p[1], p[2])).slice(-6);
$('#status').html(coord + "<br>" + hex);
});
위 코드는 jQuery와 다음 유틸리티 함수가 있다고 가정합니다.
function findPos(obj) {
var curleft = 0, curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
return { x: curleft, y: curtop };
}
return undefined;
}
function rgbToHex(r, g, b) {
if (r > 255 || g > 255 || b > 255)
throw "Invalid color component";
return ((r << 16) | (g << 8) | b).toString(16);
}
function randomInt(max) {
return Math.floor(Math.random() * max);
}
function randomColor() {
return `rgb(${randomInt(256)}, ${randomInt(256)}, ${randomInt(256)})`
}
여기에서 실제로 확인하십시오.
답변
나는 이것이 오래된 질문이라는 것을 알고 있지만 여기에 대안이 있습니다. 이미지 데이터를 배열에 저장 한 다음 캔버스 위로 마우스 이동 이벤트를 수행합니다.
var index = (Math.floor(y) * canvasWidth + Math.floor(x)) * 4
var r = data[index]
var g = data[index + 1]
var b = data[index + 2]
var a = data[index + 3]
매번 imageData를 얻는 것보다 훨씬 쉽습니다.
답변
여기 StackOverflow (위의 기사 포함)와 다른 사이트에서 찾은 다양한 참조를 병합하여 javascript와 JQuery를 사용했습니다.
<html>
<body>
<canvas id="myCanvas" width="400" height="400" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<script src="jquery.js"></script>
<script type="text/javascript">
window.onload = function(){
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var img = new Image();
img.src = 'photo_apple.jpg';
context.drawImage(img, 0, 0);
};
function findPos(obj){
var current_left = 0, current_top = 0;
if (obj.offsetParent){
do{
current_left += obj.offsetLeft;
current_top += obj.offsetTop;
}while(obj = obj.offsetParent);
return {x: current_left, y: current_top};
}
return undefined;
}
function rgbToHex(r, g, b){
if (r > 255 || g > 255 || b > 255)
throw "Invalid color component";
return ((r << 16) | (g << 8) | b).toString(16);
}
$('#myCanvas').click(function(e){
var position = findPos(this);
var x = e.pageX - position.x;
var y = e.pageY - position.y;
var coordinate = "x=" + x + ", y=" + y;
var canvas = this.getContext('2d');
var p = canvas.getImageData(x, y, 1, 1).data;
var hex = "#" + ("000000" + rgbToHex(p[0], p[1], p[2])).slice(-6);
alert("HEX: " + hex);
});
</script>
<img src="photo_apple.jpg"/>
</body>
</html>
이것이 나의 완전한 솔루션입니다. 여기서는 캔버스와 하나의 이미지 만 사용했지만 <map>
이미지 위에 사용해야 하는 경우에도 가능합니다.
답변
매번 getImageData를 호출하면 프로세스 속도가 느려집니다 … 이미지 데이터 저장을 권장하는 속도를 높이면 pix 값을 쉽고 빠르게 얻을 수 있으므로 성능 향상을 위해 이와 같은 작업을 수행하십시오.
// keep it global
let imgData = false; // initially no image data we have
// create some function block
if(imgData === false){
// fetch once canvas data
var ctx = canvas.getContext("2d");
imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
}
// Prepare your X Y coordinates which you will be fetching from your mouse loc
let x = 100; //
let y = 100;
// locate index of current pixel
let index = (y * imgData.width + x) * 4;
let red = imgData.data[index];
let green = imgData.data[index+1];
let blue = imgData.data[index+2];
let alpha = imgData.data[index+3];
// Output
console.log('pix x ' + x +' y '+y+ ' index '+index +' COLOR '+red+','+green+','+blue+','+alpha);
답변
빠른 답변
context.getImageData(x, y, 1, 1).data;
rgba 배열을 반환합니다. 예 :[50, 50, 50, 255]
다음은 rgba 배열을 인수로 사용하는 @lwburk의 rgbToHex 함수 버전입니다.
function rgbToHex(rgb){
return '#' + ((rgb[0] << 16) | (rgb[1] << 8) | rgb[2]).toString(16);
};
답변
단일 픽셀의 색상이 아닌 직사각형 영역의 평균 색상을 얻으려면 다음 다른 질문을 살펴보십시오.
? JavaScript-이미지의 특정 영역에서 평균 색상 가져 오기
어쨌든 둘 다 매우 비슷한 방식으로 수행됩니다.
? 이미지 또는 캔버스에서 단일 픽셀의 색상 / 값 가져 오기
단일 픽셀의 색상을 얻으려면 먼저 해당 이미지를 이미 수행 한 캔버스에 그립니다.
const image = document.getElementById('image');
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const width = image.width;
const height = image.height;
canvas.width = width;
canvas.height = height;
context.drawImage(image, 0, 0, width, height);
그런 다음 다음과 같이 단일 픽셀의 값을 얻습니다.
const data = context.getImageData(X, Y, 1, 1).data;
// RED = data[0]
// GREEN = data[1]
// BLUE = data[2]
// ALPHA = data[3]
? 모든 이미지 데이터를 한 번에 가져옴으로써 속도 향상
이 동일한 CanvasRenderingContext2D.getImageData () 를 사용 하여 전체 이미지의 값을 가져와야 합니다.이 작업은 세 번째 및 네 번째 매개 변수를 변경하여 수행합니다. 해당 기능의 시그니처는 다음과 같습니다.
ImageData ctx.getImageData(sx, sy, sw, sh);
sx
: ImageData를 추출 할 직사각형의 왼쪽 상단 모서리의 x 좌표입니다.sy
: ImageData를 추출 할 사각형의 왼쪽 위 모서리의 y 좌표입니다.sw
: ImageData를 추출 할 사각형의 너비입니다.sh
: ImageData를 추출 할 사각형의 높이입니다.
그것이 무엇이든간에ImageData
객체를 반환하는 것을 볼 수 있습니다 . 여기서 중요한 부분은 해당 객체가 모든 픽셀 값을 포함 하는 속성을 가지고 있다는 것입니다 ..data
그러나 .data
속성은 1 차원 Uint8ClampedArray
이므로 모든 픽셀의 구성 요소가 평평 해 졌으므로 다음과 같은 결과를 얻게됩니다.
다음과 같은 2×2 이미지가 있다고 가정 해 보겠습니다.
RED PIXEL | GREEN PIXEL
BLUE PIXEL | TRANSPARENT PIXEL
그러면 다음과 같이 표시됩니다.
[ 255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255, 0, 0, 0, 0 ]
| RED PIXEL | GREEN PIXEL | BLUE PIXEL | TRANSPAERENT PIXEL |
| 1ST PIXEL | 2ND PIXEL | 3RD PIXEL | 4TH PIXEL |
호출 getImageData
은 느린 작업이므로 한 번만 호출하여 모든 이미지의 데이터를 가져올 수 있습니다 ( sw
= 이미지 너비, sh
= 이미지 높이).
그런 다음 위의 예에서의 구성 요소 TRANSPARENT PIXEL
, 즉 x = 1, y = 1
이 가상 이미지의 위치 에 있는 구성 요소에 액세스하려면 의 속성에서 다음과 같이 첫 번째 인덱스 i
를 찾습니다 .ImageData
data
const i = (y * imageData.width + x) * 4;
✨ 실제로 살펴 보자
const solidColor = document.getElementById('solidColor');
const alphaColor = document.getElementById('alphaColor');
const solidWeighted = document.getElementById('solidWeighted');
const solidColorCode = document.getElementById('solidColorCode');
const alphaColorCode = document.getElementById('alphaColorCode');
const solidWeightedCOde = document.getElementById('solidWeightedCode');
const brush = document.getElementById('brush');
const image = document.getElementById('image');
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const width = image.width;
const height = image.height;
const BRUSH_SIZE = brush.offsetWidth;
const BRUSH_CENTER = BRUSH_SIZE / 2;
const MIN_X = image.offsetLeft + 4;
const MAX_X = MIN_X + width - 1;
const MIN_Y = image.offsetTop + 4;
const MAX_Y = MIN_Y + height - 1;
canvas.width = width;
canvas.height = height;
context.drawImage(image, 0, 0, width, height);
const imageDataData = context.getImageData(0, 0, width, height).data;
function sampleColor(clientX, clientY) {
if (clientX < MIN_X || clientX > MAX_X || clientY < MIN_Y || clientY > MAX_Y) {
requestAnimationFrame(() => {
brush.style.transform = `translate(${ clientX }px, ${ clientY }px)`;
solidColorCode.innerText = solidColor.style.background = 'rgb(0, 0, 0)';
alphaColorCode.innerText = alphaColor.style.background = 'rgba(0, 0, 0, 0.00)';
solidWeightedCode.innerText = solidWeighted.style.background = 'rgb(0, 0, 0)';
});
return;
}
const imageX = clientX - MIN_X;
const imageY = clientY - MIN_Y;
const i = (imageY * width + imageX) * 4;
// A single pixel (R, G, B, A) will take 4 positions in the array:
const R = imageDataData[i];
const G = imageDataData[i + 1];
const B = imageDataData[i + 2];
const A = imageDataData[i + 3] / 255;
const iA = 1 - A;
// Alpha-weighted color:
const wR = (R * A + 255 * iA) | 0;
const wG = (G * A + 255 * iA) | 0;
const wB = (B * A + 255 * iA) | 0;
// Update UI:
requestAnimationFrame(() => {
brush.style.transform = `translate(${ clientX }px, ${ clientY }px)`;
solidColorCode.innerText = solidColor.style.background
= `rgb(${ R }, ${ G }, ${ B })`;
alphaColorCode.innerText = alphaColor.style.background
= `rgba(${ R }, ${ G }, ${ B }, ${ A.toFixed(2) })`;
solidWeightedCode.innerText = solidWeighted.style.background
= `rgb(${ wR }, ${ wG }, ${ wB })`;
});
}
document.onmousemove = (e) => sampleColor(e.clientX, e.clientY);
sampleColor(MIN_X, MIN_Y);
body {
margin: 0;
height: 100vh;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
cursor: none;
font-family: monospace;
overflow: hidden;
}
#image {
border: 4px solid white;
border-radius: 2px;
box-shadow: 0 0 32px 0 rgba(0, 0, 0, .25);
width: 150px;
box-sizing: border-box;
}
#brush {
position: absolute;
top: 0;
left: 0;
pointer-events: none;
width: 1px;
height: 1px;
mix-blend-mode: exclusion;
border-radius: 100%;
}
#brush::before,
#brush::after {
content: '';
position: absolute;
background: magenta;
}
#brush::before {
top: -16px;
left: 0;
height: 33px;
width: 100%;
}
#brush::after {
left: -16px;
top: 0;
width: 33px;
height: 100%;
}
#samples {
position: relative;
list-style: none;
padding: 0;
width: 250px;
}
#samples::before {
content: '';
position: absolute;
top: 0;
left: 27px;
width: 2px;
height: 100%;
background: black;
border-radius: 1px;
}
#samples > li {
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
padding-left: 56px;
}
#samples > li + li {
margin-top: 8px;
}
.sample {
position: absolute;
top: 50%;
left: 16px;
transform: translate(0, -50%);
display: block;
width: 24px;
height: 24px;
border-radius: 100%;
box-shadow: 0 0 16px 4px rgba(0, 0, 0, .25);
margin-right: 8px;
}
.sampleLabel {
font-weight: bold;
margin-bottom: 8px;
}
.sampleCode {
}
<img id="image" src="data:image/gif;base64,R0lGODlhSwBLAPEAACMfIO0cJAAAAAAAACH/C0ltYWdlTWFnaWNrDWdhbW1hPTAuNDU0NTUAIf4jUmVzaXplZCBvbiBodHRwczovL2V6Z2lmLmNvbS9yZXNpemUAIfkEBQAAAgAsAAAAAEsASwAAAv+Uj6mb4A+QY7TaKxvch+MPKpC0eeUUptdomOzJqnLUvnFcl7J6Pzn9I+l2IdfII8DZiCnYsYdK4qRTptAZwQKRVK71CusOgx2nFRrlhMu+33o2NEalC6S9zQvfi3Mlnm9WxeQ396F2+HcQsMjYGEBRVbhy5yOp6OgIeVIHpEnZyYCZ6cklKBJX+Kgg2riqKoayOWl2+VrLmtDqBptIOjZ6K4qAeSrL8PcmHExsgMs2dpyIxPpKvdhM/YxaTMW2PGr9GP76BN3VHTMurh7eoU14jsc+P845Vn6OTb/P/I68iYOfwGv+JOmRNHBfsV5ujA1LqM4eKDoNvXyDqItTxYX/DC9irKBlIhkKGPtFw1JDiMeS7CqWqySPZcKGHH/JHGgIpb6bCl1O0LmT57yCOqoI5UcU0YKjPXmFjMm0ZQ4NIVdGBdZRi9WrjLxJNMY1Yr4dYeuNxWApl1ALHb+KDHrTV1owlriedJgSr4Cybu/9dFiWYAagsqAGVkkzaZTAuqD9ywKWMUG9dCO3u2zWpVzIhpW122utZlrHnTN+Bq2Mqrlnqh8CQ+0Mrq3Kc++q7eo6dlB3rLuh3abPVbbbI2mxBdhWdsZhid8cr0oy9F08q0k5FXSadiyL1mF5z51a8VsQOp3/LlodkBfzmzWf2bOrtfzr48k/1hupDaLa9rUbO+zlwndfaOCURAXRNaCBqBT2BncJakWfTzSYkmCEFr60RX0V8sKaHOltCBJ1tAAFYhHaVVbig3jxp0IBADs=" >
<div id="brush"></div>
<ul id="samples">
<li>
<span class="sample" id="solidColor"></span>
<div class="sampleLabel">solidColor</div>
<div class="sampleCode" id="solidColorCode">rgb(0, 0, 0)</div>
</li>
<li>
<span class="sample" id="alphaColor"></span>
<div class="sampleLabel">alphaColor</div>
<div class="sampleCode" id="alphaColorCode">rgba(0, 0, 0, 0.00)</div>
</li>
<li>
<span class="sample" id="solidWeighted"></span>
<div class="sampleLabel">solidWeighted (with white)</div>
<div class="sampleCode" id="solidWeightedCode">rgb(0, 0, 0)</div>
</li>
</ul>
⚠️ 참고 Cross-Origin
외부 이미지를 포함하거나 더 긴 데이터 URI를 사용하려고 할 때 허용되는 것보다 큰 답변을 포함하는 경우 문제 를 피하기 위해 작은 데이터 URI 를 사용하고 있습니다.
?️이 색상은 이상해 보이지 않습니까?
별표 모양의 테두리 주위로 커서를 이동하면 때때로 avgSolidColor
빨간색으로 표시되지만 샘플링하는 픽셀은 흰색으로 보입니다. R
해당 픽셀 의 구성 요소가 높 더라도 알파 채널이 낮기 때문에 색상은 실제로 거의 투명한 빨간색 음영이지만이를 avgSolidColor
무시하기 때문입니다.
반면에 avgAlphaColor
분홍색으로 보입니다. 사실은 사실이 아닙니다. 이제 알파 채널을 사용하고 있기 때문에 분홍색으로 보입니다. 이 채널은 반투명하게 만들고이 경우에는 흰색 인 페이지의 배경을 볼 수 있습니다.
? 알파 가중치 색상
그렇다면이 문제를 해결하려면 어떻게해야합니까? 글쎄, 우리는 새로운 샘플의 구성 요소를 계산하기 위해 알파 채널과 그 역을 가중치로 사용하기 만하면됩니다.이 경우에는 우리가 배경으로 사용하는 색상이므로 흰색과 병합합니다.
즉, 픽셀이 R, G, B, A
인 경우 A
,이 구간 [0, 1]
에있는 경우 알파 채널의 역수 iA
및 가중치가 적용된 샘플의 구성 요소를 다음과 같이 계산합니다 .
const iA = 1 - A;
const wR = (R * A + 255 * iA) | 0;
const wG = (G * A + 255 * iA) | 0;
const wB = (B * A + 255 * iA) | 0;
픽셀이 더 투명할수록 ( A
0에 가까울수록) 색상이 더 밝아집니다.