2013-03-27 44 views
7

Tôi đã tạo ra một colobar gradient với kiểu CSS3 (fiddle) và bây giờ muốn giá trị màu của một vị trí cụ thể (bằng x và y coords) trong thanh màu đó. Theo tôi biết không có cách nào trực tiếp để làm điều đó.Nhận giá trị màu của vị trí cụ thể trong colorbar với gradient

tôi thấy hai lựa chọn:

  1. Thực hiện các thuật toán gradient trong JavaScript và tính giá trị từ đầu. Có một định nghĩa chính xác làm thế nào mà thuật toán hoạt động cho nhiều màu sắc? Gradient có giống nhau trong mọi trình duyệt không?

  2. Sử dụng phương thức canvascreateLinearGradient để vẽ độ dốc và truy cập trực tiếp vào canvas để nhận giá trị màu.

Bất kỳ tùy chọn nào khác?

Trả lời

7

Tôi đã chọn triển khai giải pháp đầu tiên của bạn (tìm ra gradient bằng JavaScript). Điều đó có nghĩa là bạn không cần phải dựa vào sự hỗ trợ cho phần tử canvas, điều này có thể quan trọng tùy thuộc vào sự hỗ trợ của trình duyệt của bạn.

Sử dụng phương pháp canvas cũng sẽ rất tuyệt và dễ dàng hơn. Bạn có thể làm cho màu dừng lại từ CSS, và sau đó sử dụng getImageData() để tìm ra màu sắc con trỏ đã qua.

Bạn có thể trích xuất các màu sắc CSS với một regex, và bản đồ bất kỳ nhân người để RGB với ...

var background = window.getComputedStyle(element).getPropertyValue("background"); 

var colorStops = []; 
var matchColorStops = /,\s*(\w+)\s+(\d+)%/g; 
var match; 

var humanToHex = { 
    "red": [255, 0, 0], 
    "green": [0, 128, 0], 
    "blue": [0, 0, 255] 
}; 

while (match = matchColorStops.exec(background)) { 
    if (humanToHex[match[1]]) { 
     match[1] = humanToHex[match[1]]; 
    } 
    colorStops.push({ 
     percentage: match[2], 
     color: match[1] 
    }); 
} 

Bạn có thể sử dụng hàm JavaScript nhỏ này để suy hai màu nếu chúng được tách thành giá trị RGB của chúng.

var getStepColor = function(colorA, colorB, value) { 
    return colorA.map(function(color, i) { 
     return (color + value * (colorB[i] - color)) & 255; 
    }); 
}; 

Bạn có thể kết hợp đó để nhận được một số mã mà sẽ cho phép bạn làm điều này ...

var getStepColor = function (colorA, colorB, value) { 
    return colorA.map(function (color, i) { 
     return (color + value * (colorB[i] - color)) & 255; 
    }); 
}; 

var gradient = document.querySelector("#gradient"); 
var preview = document.querySelector("#preview"); 

var background = window.getComputedStyle(gradient).getPropertyValue("background"); 

var colorStops = []; 
var matchColorStops = /,\s*(\w+)\s+(\d+)%/g; 
var match; 

var humanToHex = { 
    "red": [255, 0, 0], 
    "green": [0, 128, 0], 
    "blue": [0, 0, 255] 
}; 

while (match = matchColorStops.exec(background)) { 
    // If colour is *human-readable*, then 
    // substitute it for a RGB value. 
    if (humanToHex[match[1]]) { 
     match[1] = humanToHex[match[1]]; 
    } 
    colorStops.push({ 
     percentage: match[2], 
     color: match[1] 
    }); 
} 

gradient.addEventListener("mousemove", function (event) { 

    var x = event.pageX - gradient.offsetTop; 
    var y = event.pageY - gradient.offsetLeft; 
    var percentage = (x/this.offsetWidth) * 100; 

    var i; 
    for (i = 0; i < colorStops.length; i++) { 
     if (colorStops[i].percentage > percentage) { 
      break; 
     }; 
    } 

    var lowerIndex = i == 1 ? 0 : i - 1; 
    var upperIndex = lowerIndex + 1; 
    var value = x/(gradient.offsetWidth/(colorStops.length - 1)) % 1; 

    color = getStepColor(colorStops[lowerIndex].color, colorStops[upperIndex].color, value); 

    preview.style.backgroundColor = "rgb(" + color.join() + ")"; 
    preview.textContent = preview.style.backgroundColor; 

}); 

jsFiddle.

Đây chỉ là một cách hack-ish nhanh chóng để đi lên với điều này, có lẽ là một phương pháp tốt hơn không rõ ràng của giải nén màu sắc, và để tìm ra nơi con trỏ có liên quan đến phân đoạn gradient.

+0

Câu trả lời rất hay và ví dụ tuyệt vời. Cảm ơn rất nhiều. – Zardoz

+0

Đừng lo lắng, cảm ơn bạn đã đặt câu hỏi hay. Bạn sẽ đi với giải pháp này dựa trên canvas hay không? – alex

+0

Tôi có hai dự án mà tôi cần. Một dự án đã sử dụng một số nội dung WebGL, vì vậy một canvas khác sẽ làm điều đó. Đối với dự án khác (không sử dụng bất kỳ canvas nào), tôi sẽ sử dụng giải pháp của bạn. – Zardoz

Các vấn đề liên quan