Skip to content

Instantly share code, notes, and snippets.

@flpms
Created July 5, 2020 06:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save flpms/ea41319c723a22d68a77550c2a00a33b to your computer and use it in GitHub Desktop.
Save flpms/ea41319c723a22d68a77550c2a00a33b to your computer and use it in GitHub Desktop.
import React from 'react';
const getPercent = (percent, value) =>
(value * percent) / 100;
const colorTypes = new Map([
['r', 'rgb'],
['#', 'hex'],
['h', 'hsla']
]);
const getColorType = color => colorTypes.get(color[0]);
const getArrayValuesFromString = color =>
color.replace(/\W/gi, '').split('');
const reverseHexShort = color =>
color.reduce((acc, num) => {
acc.push(num);
acc.push(num);
return acc;
}, []);
const transformHexValues = color =>
color.reduce((acc, value, index) => {
if (!(index % 2)) return acc;
const decimalValue =
parseInt(`${color[index - 1]}${value}`, 16);
return (acc.push(decimalValue), acc);
}, []);
const convertColorHexToRGBArray = color => {
let normalizedHexColor;
const hexColorArray = getArrayValuesFromString(color);
if (hexColorArray.length <= 4) {
normalizedHexColor = reverseHexShort(hexColorArray);
}
return transformHexValues(normalizedHexColor || hexColorArray);
}
const isOpacityTransparent = opacity => {
if (!opacity) return false;
let opacityValue = opacity;
if (Math.floor(opacity) === 0) {
opacityValue = Math.floor(opacity * 254);
}
return opacityValue > 70;
}
const getContrastRatio = rgbColorArray => Math.round((
(parseInt(rgbColorArray[0]) * 299) +
(parseInt(rgbColorArray[1]) * 587) +
(parseInt(rgbColorArray[2]) * 114)
) / 1000);
const getTextColor = color => {
let rgbColorArray;
const colorType = getColorType(color);
if (!colorType || colorType === 'hsla') {
console.warn(new Error(`Unssuported color:
if you are using a hsla color, is not supported due contrast ratio.
also be careful with gradient background not suported by svgs.
`));
return 'black';
}
if (colorType === 'hex') {
rgbColorArray = convertColorHexToRGBArray(color);
}
if (colorType === 'rgb') {
rgbColorArray = color.replace(/((rgb|a)|(\(|\)))/g, '')
.split(',')
.map(str => +str.trim());
}
if (isOpacityTransparent(rgbColorArray[3])) {
return 'black';
}
return (getContrastRatio(rgbColorArray) > 128) ? 'black' : 'white';
}
export default props => {
const size = getPercent(48, props.size);
const textColor = getTextColor(props.bgColor);
return (
<svg height={props.size} width={props.size}>
<circle cx={size} cy={size} r={size} fill={props.bgColor} />
<text
fontFamily="Arial, Helvetica, sans-serif"
fontSize={size}
textAnchor="middle"
fill={textColor || props.textColor}
x={size}
y={getPercent(66, props.size)}
>
{props.children}
</text>
</svg>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment