Further robustify trending news
- Convert back to RGB for max compat - Better variable names - Add fallback if there's no blurhash - Refactor color utils - Use alpha instead of light/dark colors
This commit is contained in:
parent
3a32cbf974
commit
5d5ab906ba
|
@ -54,10 +54,6 @@
|
|||
}
|
||||
|
||||
a {
|
||||
--other-color: var(--light-color);
|
||||
@media (prefers-color-scheme: dark) {
|
||||
--other-color: var(--dark-color);
|
||||
}
|
||||
min-width: 240px;
|
||||
flex-grow: 1;
|
||||
max-width: 320px;
|
||||
|
@ -65,14 +61,14 @@
|
|||
color: inherit;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
background-color: var(--other-color);
|
||||
background-color: var(--accent-alpha-color);
|
||||
border: 4px solid transparent;
|
||||
box-shadow: 0 4px 8px -2px var(--drop-shadow-color);
|
||||
transition: all 0.15s ease-out;
|
||||
display: flex;
|
||||
background-image: linear-gradient(
|
||||
to bottom,
|
||||
var(--accent-color) -50%,
|
||||
var(--accent-color, var(--link-text-color)) -50%,
|
||||
transparent
|
||||
);
|
||||
background-clip: border-box;
|
||||
|
@ -82,7 +78,7 @@
|
|||
max-height: 50vh;
|
||||
|
||||
&:not(:active):is(:hover, :focus-visible) {
|
||||
border-color: var(--accent-color);
|
||||
border-color: var(--accent-color, var(--link-light-color));
|
||||
box-shadow: 0 4px 8px var(--drop-shadow-color),
|
||||
0 8px 16px var(--drop-shadow-color);
|
||||
transform-origin: center bottom;
|
||||
|
@ -107,7 +103,7 @@
|
|||
background-repeat: no-repeat;
|
||||
background-image: linear-gradient(
|
||||
to bottom,
|
||||
var(--other-color) 70%,
|
||||
var(--accent-alpha-color) 70%,
|
||||
var(--bg-color) 100%
|
||||
);
|
||||
transition: background-position-y 0.15s ease-out;
|
||||
|
|
|
@ -12,6 +12,7 @@ import Menu2 from '../components/menu2';
|
|||
import RelativeTime from '../components/relative-time';
|
||||
import Timeline from '../components/timeline';
|
||||
import { api } from '../utils/api';
|
||||
import { oklab2rgb, rgb2oklab } from '../utils/color-utils';
|
||||
import { filteredItems } from '../utils/filters';
|
||||
import pmem from '../utils/pmem';
|
||||
import states from '../utils/states';
|
||||
|
@ -161,35 +162,16 @@ function Trending({ columnMode, ...props }) {
|
|||
const domain = new URL(url).hostname
|
||||
.replace(/^www\./, '')
|
||||
.replace(/\/$/, '');
|
||||
const averageColor = getBlurHashAverageColor(blurhash);
|
||||
const labAverageColor = rgb2oklab(averageColor);
|
||||
|
||||
// const lightColor = averageColor.map((c) => {
|
||||
// const v = c + 120;
|
||||
// return v > 255 ? 255 : v;
|
||||
// });
|
||||
// const darkColor = averageColor.map((c) => {
|
||||
// const v = c - 100;
|
||||
// return v < 0 ? 0 : v;
|
||||
// });
|
||||
const accentColor = labAverageColor.map((c, i) => {
|
||||
if (i === 0) {
|
||||
return 0.65;
|
||||
}
|
||||
return c;
|
||||
});
|
||||
const lightColor = labAverageColor.map((c, i) => {
|
||||
if (i === 0) {
|
||||
return 0.9;
|
||||
}
|
||||
return c;
|
||||
});
|
||||
const darkColor = labAverageColor.map((c, i) => {
|
||||
if (i === 0) {
|
||||
return 0.4;
|
||||
}
|
||||
return c;
|
||||
});
|
||||
let accentColor;
|
||||
if (blurhash) {
|
||||
const averageColor = getBlurHashAverageColor(blurhash);
|
||||
const labAverageColor = rgb2oklab(averageColor);
|
||||
accentColor = oklab2rgb([
|
||||
0.6,
|
||||
labAverageColor[1],
|
||||
labAverageColor[2],
|
||||
]);
|
||||
}
|
||||
|
||||
return (
|
||||
<a
|
||||
|
@ -197,14 +179,16 @@ function Trending({ columnMode, ...props }) {
|
|||
href={url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={{
|
||||
'--average-color': `rgb(${averageColor?.join(',')})`,
|
||||
// '--light-color': `rgb(${lightColor?.join(',')})`,
|
||||
// '--dark-color': `rgb(${darkColor?.join(',')})`,
|
||||
'--accent-color': `oklab(${accentColor?.join(' ')})`,
|
||||
'--light-color': `oklab(${lightColor?.join(' ')})`,
|
||||
'--dark-color': `oklab(${darkColor?.join(' ')})`,
|
||||
}}
|
||||
style={
|
||||
accentColor
|
||||
? {
|
||||
'--accent-color': `rgb(${accentColor.join(',')})`,
|
||||
'--accent-alpha-color': `rgba(${accentColor.join(
|
||||
',',
|
||||
)}, 0.4)`,
|
||||
}
|
||||
: {}
|
||||
}
|
||||
>
|
||||
<article>
|
||||
<figure>
|
||||
|
@ -311,24 +295,4 @@ function Trending({ columnMode, ...props }) {
|
|||
);
|
||||
}
|
||||
|
||||
// https://gist.github.com/earthbound19/e7fe15fdf8ca3ef814750a61bc75b5ce
|
||||
const gammaToLinear = (c) =>
|
||||
c >= 0.04045 ? Math.pow((c + 0.055) / 1.055, 2.4) : c / 12.92;
|
||||
function rgb2oklab([r, g, b]) {
|
||||
r = gammaToLinear(r / 255);
|
||||
g = gammaToLinear(g / 255);
|
||||
b = gammaToLinear(b / 255);
|
||||
var l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;
|
||||
var m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b;
|
||||
var s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b;
|
||||
l = Math.cbrt(l);
|
||||
m = Math.cbrt(m);
|
||||
s = Math.cbrt(s);
|
||||
return [
|
||||
l * +0.2104542553 + m * +0.793617785 + s * -0.0040720468,
|
||||
l * +1.9779984951 + m * -2.428592205 + s * +0.4505937099,
|
||||
l * +0.0259040371 + m * +0.7827717662 + s * -0.808675766,
|
||||
];
|
||||
}
|
||||
|
||||
export default Trending;
|
||||
|
|
52
src/utils/color-utils.js
Normal file
52
src/utils/color-utils.js
Normal file
|
@ -0,0 +1,52 @@
|
|||
// https://gist.github.com/earthbound19/e7fe15fdf8ca3ef814750a61bc75b5ce
|
||||
function clamp(value, min, max) {
|
||||
return Math.max(Math.min(value, max), min);
|
||||
}
|
||||
|
||||
const gammaToLinear = (c) =>
|
||||
c >= 0.04045 ? Math.pow((c + 0.055) / 1.055, 2.4) : c / 12.92;
|
||||
const linearToGamma = (c) =>
|
||||
c >= 0.0031308 ? 1.055 * Math.pow(c, 1 / 2.4) - 0.055 : 12.92 * c;
|
||||
|
||||
export function rgb2oklab([r, g, b]) {
|
||||
r = gammaToLinear(r / 255);
|
||||
g = gammaToLinear(g / 255);
|
||||
b = gammaToLinear(b / 255);
|
||||
var l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;
|
||||
var m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b;
|
||||
var s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b;
|
||||
l = Math.cbrt(l);
|
||||
m = Math.cbrt(m);
|
||||
s = Math.cbrt(s);
|
||||
return [
|
||||
l * +0.2104542553 + m * +0.793617785 + s * -0.0040720468,
|
||||
l * +1.9779984951 + m * -2.428592205 + s * +0.4505937099,
|
||||
l * +0.0259040371 + m * +0.7827717662 + s * -0.808675766,
|
||||
];
|
||||
}
|
||||
|
||||
export function oklab2rgb([L, a, b]) {
|
||||
var l = L + a * +0.3963377774 + b * +0.2158037573;
|
||||
var m = L + a * -0.1055613458 + b * -0.0638541728;
|
||||
var s = L + a * -0.0894841775 + b * -1.291485548;
|
||||
// The ** operator here cubes; same as l_*l_*l_ in the C++ example:
|
||||
l = l ** 3;
|
||||
m = m ** 3;
|
||||
s = s ** 3;
|
||||
var r = l * +4.0767416621 + m * -3.3077115913 + s * +0.2309699292;
|
||||
var g = l * -1.2684380046 + m * +2.6097574011 + s * -0.3413193965;
|
||||
var b = l * -0.0041960863 + m * -0.7034186147 + s * +1.707614701;
|
||||
// Convert linear RGB values returned from oklab math to sRGB for our use before returning them:
|
||||
r = 255 * linearToGamma(r);
|
||||
g = 255 * linearToGamma(g);
|
||||
b = 255 * linearToGamma(b);
|
||||
// OPTION: clamp r g and b values to the range 0-255; but if you use the values immediately to draw, JavaScript clamps them on use:
|
||||
r = clamp(r, 0, 255);
|
||||
g = clamp(g, 0, 255);
|
||||
b = clamp(b, 0, 255);
|
||||
// OPTION: round the values. May not be necessary if you use them immediately for rendering in JavaScript, as JavaScript (also) discards decimals on render:
|
||||
r = Math.round(r);
|
||||
g = Math.round(g);
|
||||
b = Math.round(b);
|
||||
return [r, g, b];
|
||||
}
|
Loading…
Reference in a new issue