jsdk-offical
Version:
JSDK is the most comprehensive TypeScript framework, like JDK.
333 lines (293 loc) • 11.7 kB
text/typescript
/**
* @project JSDK
* @license MIT
* @website https://github.com/fengboyue/jsdk
*
* @version 2.7.0
* @update Based on old Colors helper.
* @author Frank.Feng
*/
module JS {
export namespace util {
/**
* Hex color notations:<br>
* #RRGGBBAA
* #RRGGBB
* #RGBA
* #RGB
* RRGGBBAA
* RRGGBB
* RGBA
* RGB
*
* <pre>
* Opacity % 255 Step 2 digit HEX prefix
* 0% 0.00 00
* 5% 12.75 0C
* 10% 25.50 19
* 15% 38.25 26
* 20% 51.00 33
* 25% 63.75 3F
* 30% 76.50 4C
* 35% 89.25 59
* 40% 102.00 66
* 45% 114.75 72
* 50% 127.50 7F
* 55% 140.25 8C
* 60% 153.00 99
* 65% 165.75 A5
* 70% 178.50 B2
* 75% 191.25 BF
* 80% 204.00 CC
* 85% 216.75 D8
* 90% 229.50 E5
* 95% 242.25 F2
* 100% 255.00 FF
* </pre>
*/
export type HEX = string;
export type RGBA = string;
export type TRGBA = {
/** red value: 0~255 */
r: number; //红色值
/** green value: 0~255 */
g: number; //绿色值
/** blue value: 0~255 */
b: number; //蓝色值
/** alpha value: 0~1 */
a?: number; //Alpha透明度。取值0~1
}
export type HSLA = string;
export type THSLA = {
/** Hue(色调): 0~360 */
h: number;
/** Saturation(饱和度): 0~1 */
s: number;
/** Lightness(亮度): 0~1 */
l: number;
/** alpha value: 0~1 */
a?: number;
}
export type CssColor = HEX | RGBA | HSLA;
export type CssUnit = '%' | 'px' | 'pt' | 'em' | 'rem' | 'in' | 'cm' | 'mm' | 'ex' | 'ch' | 'pc' | 'vw' | 'vh' | 'vmin' | 'vmax' | 'deg' | 'rad' | 'turn';
/**
* The css value string is a normal value string or a string starting with += or -= or or *= to increment or decrement or multiple the current value.
* For example, if an element's padding-left was 10px, .css( "padding-left", "+=15" ) would result in a total padding-left of 25px.
*/
export type CssValueString = string;
let _num = (s: string) => {
let n = parseFloat(s);
return n.isNaN() ? 0 : n
};
/**
* Css Helper.
*/
export class CssTool {
static isHEX(a: string): boolean {
return /^#[0-9A-F]{3,8}$/i.test(a)
}
static isRGB(a: string): boolean {
return /^rgb/.test(a)
}
static isHSL(a: string): boolean {
return /^hsl/.test(a)
}
static isColor(a: string): boolean {
return this.isHEX(a) || this.isRGB(a) || this.isHSL(a)
}
/**
* Converts RGBA to Hex color.
*
* @param r red value: 0~255
* @param g green value: 0~255
* @param b blue value: 0~255
* @param a alpha value: 0~1
*/
static rgb2hex(r: number, g: number, b: number, a?: number): HEX {
let s = [r, g, b];
if (a != void 0) s.push(Number((a * 255).integralPart()));
return '#' + s.map(x => {
let h = x.toString(16);
return h.length === 1 ? '0' + h : h
}).join('')
}
/**
* Converts Hex color string to RGBA.
*
* @param hex
*/
static hex2rgb(hex: HEX): TRGBA {
if (!this.isHEX(hex)) return null;
let a = false,
h = hex.slice(hex.startsWith('#') ? 1 : 0),
l = h.length;
if (l == 4 || l == 8) a = true;
if (l == 3 || l == 4) h = [...h].map(x => x + x).join('');
let n = parseInt(h, 16);
return {
r: (n >>> (a ? 24 : 16)),
g: ((n & (a ? 0x00ff0000 : 0x00ff00)) >>> (a ? 16 : 8)),
b: ((n & (a ? 0x0000ff00 : 0x0000ff)) >>> (a ? 8 : 0)),
a: a ? Number((n & 0x000000ff) / 255).round(2) : 1
}
}
/**
* Converts RGBA to css string.
*/
static rgbString(c: TRGBA): RGBA {
if (!c) return '';
let has = c.a != void 0;
return `rgb${has ? 'a' : ''}(${c.r},${c.g},${c.b}${has ? `,${c.a}` : ''})`
}
static toTRGB(s: RGBA): TRGBA {
if (s.startsWith('rgba(')) {
let r = /^rgba\((.+),(.+),(.+),(.+)\)$/.exec(s);
if (r) return {
r: Number(r[1]),
g: Number(r[2]),
b: Number(r[3]),
a: Number(r[4])
}
} else if (s.startsWith('rgb(')) {
let r = /^rgb\((.+),(.+),(.+)\)$/.exec(s);
if (r) return {
r: Number(r[1]),
g: Number(r[2]),
b: Number(r[3])
}
}
return null
}
static convertToRGB(val: string): TRGBA {
if (this.isHEX(val)) return this.hex2rgb(val);
if (this.isHSL(val)) return this.hsl2rgb(val);
return this.toTRGB(val)
}
/**
* Converts HSLA to css string.
*/
static hslString(c: THSLA): HSLA {
if (!c) return '';
let has = c.a != void 0;
return `hsl(${c.h},${(c.s * 100).round(2)}%,${(c.l * 100).round(2)}%${has ? `,${c.a}` : ''})`
}
static toTHSL = (h: HSLA): THSLA => {
var hsl = /hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.exec(h) || /hsla\((\d+),\s*([\d.]+)%,\s*([\d.]+)%,\s*([\d.]+)\)/g.exec(h);
return {
h: parseInt(hsl[1], 10) / 360,
s: parseInt(hsl[2], 10) / 100,
l: parseInt(hsl[3], 10) / 100,
a: parseFloat(hsl[4]) || 1
}
}
/**
* Converts HSLA to RGBA.
*/
static hsl2rgb(hsl: HSLA): TRGBA {
if (!this.isHSL(hsl)) return null;
let hsla = this.toTHSL(hsl),
h = hsla.h, s = hsla.s, l = hsla.l,
r, g, b;
if (s == 0) {
r = g = b = l; // achromatic
} else {
var hue2rgb = (p, q, t) => {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
var q = l < 0.5 ? l * (1 + s) : l + s - l * s,
p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return {
r: Math.round(r * 255),
g: Math.round(g * 255),
b: Math.round(b * 255),
a: hsla.a
}
}
/**
* Converts RGBA to HSLA.
*/
static rgb2hsl(rgb: TRGBA): THSLA {
if (!rgb) return null;
let r = rgb.r, g = rgb.g, b = rgb.b;
r /= 255, g /= 255, b /= 255;
var max = Math.max(r, g, b), min = Math.min(r, g, b),
h, s, l = (max + min) / 2;
if (max == min) {
h = s = 0; // achromatic
} else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return {
h: h,
s: s,
l: l,
a: rgb.a
}
}
/**
* Convert 'backgroundColor' to 'background-color'.
* @param name
*/
static hyphenCase(name: string) {
return name.replace(/([A-Z])/g, (a, b: string) => { return '-' + b.toLowerCase() })
}
static numberOf(val: string|number) {
return Types.isNumber(val)?<number>val:_num(<string>val)
}
static unitOf(val: string|number) {
if(val==void 0||Types.isNumber(val)) return '';
let split = /[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?(%|px|pt|em|rem|in|cm|mm|ex|ch|pc|vw|vh|vmin|vmax|deg|rad|turn)?$/.exec(<string>val);
return split ? split[1] : ''
}
static calcValue(v: CssValueString, baseVal: string|number): string {
if(!v) return baseVal+'';
if(v.indexOf(',')>0 || v.indexOf(' ')>0) return v;//不能含有逗号、空格
let u = this.unitOf(v)||this.unitOf(baseVal)||'px';
if (v.startsWith('+=') || v.startsWith('-=')) {
let ov = this.numberOf(baseVal), nv = _num(v.replace('=', ''));
return ov + nv + u
} else if (v.startsWith('*=')) {
let ov = this.numberOf(baseVal), nv = _num(v.replace('*=', ''));
return ov * nv + u
}
return parseFloat(v).isNaN()?v:(_num(v) + u)
}
/**
* Returns a normalized value string with default value or defaule unit.
* @param v
* @param defaultVal
* @param defaultUnit If is undefined then default unit is px
*/
static normValue(v: string | number, defaultVal: string, defaultUnit?: string): string
static normValue(v: string | number, df: string, du?: string): string {
if (v == void 0) return df;
return Types.isNumber(v)?(v+(du===undefined?'px':(du||''))):<string>v
}
}
}
}
import HEX = JS.util.HEX;
import RGBA = JS.util.RGBA;
import TRGBA = JS.util.TRGBA;
import HSLA = JS.util.HSLA;
import THSLA = JS.util.THSLA;
import CssUnit = JS.util.CssUnit;
import CssColor = JS.util.CssColor;
import CssValueString = JS.util.CssValueString;
import CssTool = JS.util.CssTool;