2013-03-27 11 views
7

Ho generato una barra del gradiente con stili CSS3 (fiddle) e ora voglio il valore del colore di una posizione specifica (per coordinate xey) in quella barra di colore. Per quanto ne so, non esiste un modo diretto per farlo.Ottieni il valore del colore della posizione specifica nella barra dei colori con sfumatura

vedo due opzioni:

  1. implementare l'algoritmo del gradiente in JavaScript e calcolare il valore da zero. Esiste una definizione esatta di come funziona questo algoritmo per più colori? La sfumatura è uguale in tutti i browser?

  2. Utilizzare un metodo canvas e createLinearGradient per disegnare la sfumatura e accedere direttamente alla tela per ottenere il valore del colore.

Altre opzioni?

risposta

7

Ho scelto di implementare la prima soluzione (calcolo del gradiente con JavaScript). Significa che non è necessario fare affidamento sul supporto per l'elemento canvas, che potrebbe essere importante in base al supporto del browser.

L'utilizzo dei metodi canvas sarebbe anche vantaggioso e più semplice. È possibile eseguire il rendering delle interruzioni di colore dal CSS e quindi utilizzare getImageData() per determinare il colore del puntatore.

È possibile estrarre i colori CSS con una regex, e mappare eventuali umani quelli a RGB con ...

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] 
    }); 
} 

È possibile utilizzare questa piccola funzione JavaScript per interpolare due colori se sono separati in i loro valori RGB.

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

È possibile combinare che per ottenere un codice che vi permetterà di fare questo ...

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.

Questo è solo un modo veloce per ottenere questo, probabilmente c'è un metodo migliore per estrarre i colori e per capire dove si trova il puntatore rispetto a quale segmento di gradiente.

+0

Risposta molto buona e ottimo esempio. Molte grazie. – Zardoz

+0

Nessun problema, grazie per aver fatto una bella domanda. Andrai con questa o una soluzione basata su tela? – alex

+0

Ho due progetti in cui ne ho bisogno. Un progetto utilizza già alcune cose WebGL, quindi un altro canvas lo farà. Per l'altro progetto (senza alcuna tela utilizzata) userò la tua soluzione. – Zardoz

Problemi correlati