深入学习D3JS:d3-color

d3color对颜色进行操作,比如

根据名字设置颜色,steelblue

var c = d3.color("steelblue"); // {r: 70, g: 130, b: 180, opacity: 1}

转化为hsl格式

var c = d3.hsl("steelblue"); // {h: 207.27…, s: 0.44, l: 0.4902…, opacity: 1}

还可以旋转色调,(旋转的意思就是改变色调的颜色,因为hsl模型是个锥形),增加一点对比度,然后将改颜色转化为字符串(rgb)

c.h += 90;
c.s += 0.2;
c + ""; // rgb(198, 45, 205)

稍微的淡化颜色,改变透明度

c.opacity = 0.8;
c + ""; // rgba(198, 45, 205, 0.8)

当然除了机器比较喜欢的颜色模型rgb和hsl,d3color同样支持对人友好的两个颜色模型

对于其他传统的颜色空间:

 d3.color(specifier

可以解析CSS3字符串转化为rgb或者hsl,输入不合法返回null。

  • rgb(255, 255, 255)
  • rgb(10%, 20%, 30%)
  • rgba(255, 255, 255, 0.4)
  • rgba(10%, 20%, 30%, 0.4)
  • hsl(120, 50%, 20%)
  • hsla(120, 50%, 20%, 0.4)
  • #ffeeaa
  • #fea
  • steelblue

可以与instanceof来测试该实例是否为颜色实例。

color.opacity

设置透明度

color.rgb()

返回rgb颜色

color.brighter([k])

返回一个更亮的颜色拷贝,可选参数k控制亮度,默认为0.

color.darker([k])

同理返回一个暗的拷贝。

color.displayable()

返回真如果该颜色不可见,即rgb都小于255,或者透明底不在[0,1]范围内

 color.hex() 

返回RGB空间16进制字符串,如果可不现实,转化为可显示的,例如大于255转化为255.

color.toString()

返回rgb(x,x,x)的字符串表示

d3.rgb(rgb[, opacity]) 
d3.rgb(specifier)
d3.rgb(color)

构建一个rgb空间的颜色实例

 d3.hsl(hsl[, opacity]) 
d3.hsl(specifier)
d3.hsl(color)

构建一个hsl空间的颜色实例

d3.lab(lab[, opacity]) 
d3.lab(specifier)
d3.lab(color)

lab空间

 d3.gray(l[, opacity])

lab空间的a=b=0

d3.hcl(hcl[, opacity]) 
d3.hcl(specifier)
d3.hcl(color)

d3.lch(lch[, opacity]) 
d3.lch(specifier)
d3.lch(color)

hcl颜色空间,lch知识改变了参数顺序。

d3.cubehelix(hsl[, opacity]) 
d3.cubehelix(specifier)
d3.cubehelix(color)

define.js

export default function(constructor, factory, prototype) {
    constructor.prototype = factory.prototype = prototype;
    prototype.constructor = constructor;//define的一个构造函数,这里将看不懂?
}

export function extend(parent, definition) {
    var prototype = Object.create(parent.prototype);
    for (var key in definition) prototype[key] = definition[key];
    return prototype;
}

colorjs中利用defined定义了2个对象rgb和hsl,对Rgb和rgb区别我还没搞懂

color.js

import define, {extend} from "./define";

export function Color() {}

export var darker = 0.7;//默认变亮和变暗参数
export var brighter = 1 / darker;

//这是一些正则表达式,用来匹配颜色字符串
var reI = "\\s*([+-]?\\d+)\\s*",
    reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",
    reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",
    reHex3 = /^#([0-9a-f]{3})$/,
    reHex6 = /^#([0-9a-f]{6})$/,
    reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"),
    reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"),
    reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"),
    reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"),
    reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"),
    reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$");

var named = {
    aliceblue: 0xf0f8ff,
    antiquewhite: 0xfaebd7,
    aqua: 0x00ffff,
    aquamarine: 0x7fffd4,
    azure: 0xf0ffff,
    beige: 0xf5f5dc,
    bisque: 0xffe4c4,
    black: 0x000000,
    blanchedalmond: 0xffebcd,
    blue: 0x0000ff,
    blueviolet: 0x8a2be2,
    brown: 0xa52a2a,
    burlywood: 0xdeb887,
    cadetblue: 0x5f9ea0,
    chartreuse: 0x7fff00,
    chocolate: 0xd2691e,
    coral: 0xff7f50,
    cornflowerblue: 0x6495ed,
    cornsilk: 0xfff8dc,
    crimson: 0xdc143c,
    cyan: 0x00ffff,
    darkblue: 0x00008b,
    darkcyan: 0x008b8b,
    darkgoldenrod: 0xb8860b,
    darkgray: 0xa9a9a9,
    darkgreen: 0x006400,
    darkgrey: 0xa9a9a9,
    darkkhaki: 0xbdb76b,
    darkmagenta: 0x8b008b,
    darkolivegreen: 0x556b2f,
    darkorange: 0xff8c00,
    darkorchid: 0x9932cc,
    darkred: 0x8b0000,
    darksalmon: 0xe9967a,
    darkseagreen: 0x8fbc8f,
    darkslateblue: 0x483d8b,
    darkslategray: 0x2f4f4f,
    darkslategrey: 0x2f4f4f,
    darkturquoise: 0x00ced1,
    darkviolet: 0x9400d3,
    deeppink: 0xff1493,
    deepskyblue: 0x00bfff,
    dimgray: 0x696969,
    dimgrey: 0x696969,
    dodgerblue: 0x1e90ff,
    firebrick: 0xb22222,
    floralwhite: 0xfffaf0,
    forestgreen: 0x228b22,
    fuchsia: 0xff00ff,
    gainsboro: 0xdcdcdc,
    ghostwhite: 0xf8f8ff,
    gold: 0xffd700,
    goldenrod: 0xdaa520,
    gray: 0x808080,
    green: 0x008000,
    greenyellow: 0xadff2f,
    grey: 0x808080,
    honeydew: 0xf0fff0,
    hotpink: 0xff69b4,
    indianred: 0xcd5c5c,
    indigo: 0x4b0082,
    ivory: 0xfffff0,
    khaki: 0xf0e68c,
    lavender: 0xe6e6fa,
    lavenderblush: 0xfff0f5,
    lawngreen: 0x7cfc00,
    lemonchiffon: 0xfffacd,
    lightblue: 0xadd8e6,
    lightcoral: 0xf08080,
    lightcyan: 0xe0ffff,
    lightgoldenrodyellow: 0xfafad2,
    lightgray: 0xd3d3d3,
    lightgreen: 0x90ee90,
    lightgrey: 0xd3d3d3,
    lightpink: 0xffb6c1,
    lightsalmon: 0xffa07a,
    lightseagreen: 0x20b2aa,
    lightskyblue: 0x87cefa,
    lightslategray: 0x778899,
    lightslategrey: 0x778899,
    lightsteelblue: 0xb0c4de,
    lightyellow: 0xffffe0,
    lime: 0x00ff00,
    limegreen: 0x32cd32,
    linen: 0xfaf0e6,
    magenta: 0xff00ff,
    maroon: 0x800000,
    mediumaquamarine: 0x66cdaa,
    mediumblue: 0x0000cd,
    mediumorchid: 0xba55d3,
    mediumpurple: 0x9370db,
    mediumseagreen: 0x3cb371,
    mediumslateblue: 0x7b68ee,
    mediumspringgreen: 0x00fa9a,
    mediumturquoise: 0x48d1cc,
    mediumvioletred: 0xc71585,
    midnightblue: 0x191970,
    mintcream: 0xf5fffa,
    mistyrose: 0xffe4e1,
    moccasin: 0xffe4b5,
    navajowhite: 0xffdead,
    navy: 0x000080,
    oldlace: 0xfdf5e6,
    olive: 0x808000,
    olivedrab: 0x6b8e23,
    orange: 0xffa500,
    orangered: 0xff4500,
    orchid: 0xda70d6,
    palegoldenrod: 0xeee8aa,
    palegreen: 0x98fb98,
    paleturquoise: 0xafeeee,
    palevioletred: 0xdb7093,
    papayawhip: 0xffefd5,
    peachpuff: 0xffdab9,
    peru: 0xcd853f,
    pink: 0xffc0cb,
    plum: 0xdda0dd,
    powderblue: 0xb0e0e6,
    purple: 0x800080,
    rebeccapurple: 0x663399,
    red: 0xff0000,
    rosybrown: 0xbc8f8f,
    royalblue: 0x4169e1,
    saddlebrown: 0x8b4513,
    salmon: 0xfa8072,
    sandybrown: 0xf4a460,
    seagreen: 0x2e8b57,
    seashell: 0xfff5ee,
    sienna: 0xa0522d,
    silver: 0xc0c0c0,
    skyblue: 0x87ceeb,
    slateblue: 0x6a5acd,
    slategray: 0x708090,
    slategrey: 0x708090,
    snow: 0xfffafa,
    springgreen: 0x00ff7f,
    steelblue: 0x4682b4,
    tan: 0xd2b48c,
    teal: 0x008080,
    thistle: 0xd8bfd8,
    tomato: 0xff6347,
    turquoise: 0x40e0d0,
    violet: 0xee82ee,
    wheat: 0xf5deb3,
    white: 0xffffff,
    whitesmoke: 0xf5f5f5,
    yellow: 0xffff00,
    yellowgreen: 0x9acd32
};

define(Color, color, {
    displayable: function() {
        return this.rgb().displayable();
    },
    hex: function() {
        return this.rgb().hex();
    },
    toString: function() {
        return this.rgb() + "";
    }
});

export default function color(format) {
    var m;
    format = (format + "").trim().toLowerCase();//trim()从字符串移除前导空格,尾随空格,行终止符
    return (m = reHex3.exec(format)) ? (m = parseInt(m[1], 16), new Rgb((m >> 8 & 0xf) | (m >> 4 & 0x0f0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1)) // #f00
        : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000
            : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
                : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
                    : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
                        : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
                            : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
                                : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
                                    : named.hasOwnProperty(format) ? rgbn(named[format])
                                        : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0)
                                            : null;
    //利用:?表达式,返回匹配到的颜色字符串
}

function rgbn(n) {
    return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);//利用二进制右
}

function rgba(r, g, b, a) {
    if (a <= 0) r = g = b = NaN;
    return new Rgb(r, g, b, a);
}

export function rgbConvert(o) {
    if (!(o instanceof Color)) o = color(o);
    if (!o) return new Rgb;
    o = o.rgb();
    return new Rgb(o.r, o.g, o.b, o.opacity);
}

export function rgb(r, g, b, opacity) {
    return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
}

export function Rgb(r, g, b, opacity) {
    this.r = +r;
    this.g = +g;
    this.b = +b;
    this.opacity = +opacity;
}

define(Rgb, rgb, extend(Color, {
    brighter: function(k) {
        k = k == null ? brighter : Math.pow(brighter, k);
        return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
    },
    darker: function(k) {
        k = k == null ? darker : Math.pow(darker, k);
        return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
    },
    rgb: function() {
        return this;
    },
    displayable: function() {
        return (0 <= this.r && this.r <= 255)
            && (0 <= this.g && this.g <= 255)
            && (0 <= this.b && this.b <= 255)
            && (0 <= this.opacity && this.opacity <= 1);
    },
    hex: function() {
        return "#" + hex(this.r) + hex(this.g) + hex(this.b);
    },
    toString: function() {
        var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
        return (a === 1 ? "rgb(" : "rgba(")
            + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", "
            + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", "
            + Math.max(0, Math.min(255, Math.round(this.b) || 0))
            + (a === 1 ? ")" : ", " + a + ")");
    }
}));

function hex(value) {
    value = Math.max(0, Math.min(255, Math.round(value) || 0));
    return (value < 16 ? "0" : "") + value.toString(16);
}

function hsla(h, s, l, a) {
    if (a <= 0) h = s = l = NaN;
    else if (l <= 0 || l >= 1) h = s = NaN;
    else if (s <= 0) h = NaN;
    return new Hsl(h, s, l, a);
}

export function hslConvert(o) {
    if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
    if (!(o instanceof Color)) o = color(o);
    if (!o) return new Hsl;
    if (o instanceof Hsl) return o;
    o = o.rgb();
    var r = o.r / 255,
        g = o.g / 255,
        b = o.b / 255,
        min = Math.min(r, g, b),
        max = Math.max(r, g, b),
        h = NaN,
        s = max - min,
        l = (max + min) / 2;
    if (s) {
        if (r === max) h = (g - b) / s + (g < b) * 6;
        else if (g === max) h = (b - r) / s + 2;
        else h = (r - g) / s + 4;
        s /= l < 0.5 ? max + min : 2 - max - min;
        h *= 60;
    } else {
        s = l > 0 && l < 1 ? 0 : h;
    }
    return new Hsl(h, s, l, o.opacity);
}

export function hsl(h, s, l, opacity) {
    return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
}

function Hsl(h, s, l, opacity) {
    this.h = +h;
    this.s = +s;
    this.l = +l;
    this.opacity = +opacity;
}

define(Hsl, hsl, extend(Color, {
    brighter: function(k) {
        k = k == null ? brighter : Math.pow(brighter, k);
        return new Hsl(this.h, this.s, this.l * k, this.opacity);
    },
    darker: function(k) {
        k = k == null ? darker : Math.pow(darker, k);
        return new Hsl(this.h, this.s, this.l * k, this.opacity);
    },
    rgb: function() {
        var h = this.h % 360 + (this.h < 0) * 360,
            s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
            l = this.l,
            m2 = l + (l < 0.5 ? l : 1 - l) * s,
            m1 = 2 * l - m2;
        return new Rgb(
            hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),
            hsl2rgb(h, m1, m2),
            hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),
            this.opacity
        );
    },
    displayable: function() {
        return (0 <= this.s && this.s <= 1 || isNaN(this.s))
            && (0 <= this.l && this.l <= 1)
            && (0 <= this.opacity && this.opacity <= 1);
    }
}));

/* From FvD 13.37, CSS Color Module Level 3 */
function hsl2rgb(h, m1, m2) {
    return (h < 60 ? m1 + (m2 - m1) * h / 60
        : h < 180 ? m2
            : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60
                : m1) * 255;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要让iOS富文本支持该样式,你可以使用Core Text框架来实现。下面是一个示例代码: ```swift import UIKit import CoreText extension NSMutableAttributedString { func applyLinearGradient(colors: [CGColor], startPoint: CGPoint, endPoint: CGPoint) { let gradient = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: colors as CFArray, locations: nil)! let stringRange = NSRange(location: 0, length: self.length) let line = CTLineCreateWithAttributedString(self) let runs = CTLineGetGlyphRuns(line) for runIndex in 0..<CFArrayGetCount(runs) { let run = CFArrayGetValueAtIndex(runs, runIndex)! let runRange = CTRunGetStringRange(run) var runRect = CGRect.zero CTRunGetTypographicBounds(run, CFRangeMake(0, 0), &runRect.origin, &runRect.size, nil) let glyphCount = CTRunGetGlyphCount(run) var glyphPositions = Array<CGPoint>(repeating: .zero, count: glyphCount) CTRunGetPositions(run, CFRangeMake(0, 0), &glyphPositions) for glyphIndex in 0..<glyphCount { let glyphRange = CFRangeMake(glyphIndex, 1) let position = glyphPositions[glyphIndex] let glyphRect = CGRect(x: runRect.origin.x + position.x, y: runRect.origin.y + position.y, width: runRect.size.width, height: runRect.size.height) let glyphLocation = runRange.location + glyphRange.location let characterRange = CFRangeMake(glyphLocation, glyphRange.length) let tokenRange = CTLineGetStringRange(line) let adjustedRange = CFRangeMake(characterRange.location - tokenRange.location, characterRange.length) self.enumerateAttribute(.font, in: adjustedRange, options: []) { (value, range, stop) in let font = value as! UIFont let fontSize = font.pointSize let glyphPath = CTFontCreatePathForGlyph(font, glyphRange.location, nil)! let glyphBoundingBox = glyphPath.boundingBox let textMatrix = CGAffineTransform(scaleX: 1, y: -1).translatedBy(x: 0, y: -runRect.size.height) let glyphTransform = glyphBoundingBox.applying(textMatrix) let startPoint = CGPoint(x: startPoint.x + glyphRect.origin.x, y: startPoint.y + glyphRect.origin.y) let endPoint = CGPoint(x: endPoint.x + glyphRect.origin.x, y: endPoint.y + glyphRect.origin.y) let gradientTransform = CGAffineTransform(translationX: startPoint.x, y: startPoint.y).scaledBy(x: (endPoint.x - startPoint.x) / glyphBoundingBox.width, y: (endPoint.y - startPoint.y) / glyphBoundingBox.height) let gradientPath = glyphPath.copy(using: &gradientTransform)! let gradientBoundingBox = gradientPath.boundingBox let boundingBoxTransform = CGAffineTransform(translationX: -gradientBoundingBox.origin.x, y: -gradientBoundingBox.origin.y) let transformedGradientPath = gradientPath.copy(using: &boundingBoxTransform)! let context = UIGraphicsGetCurrentContext()! context.addPath(transformedGradientPath) context.clip() context.drawLinearGradient(gradient, start: startPoint, end: endPoint, options: [.drawsBeforeStartLocation, .drawsAfterEndLocation]) } } } } } // 使用示例 let label = UILabel() let attributedText = NSMutableAttributedString(string: "Your text here") let colors = [UIColor.black.cgColor, UIColor(red: 211/255, green: 211/255, blue: 211/255, alpha: 1).cgColor] let startPoint = CGPoint(x: 0, y: 0) let endPoint = CGPoint(x: label.bounds.width, y: 0) attributedText.addAttribute(.foregroundColor, value: UIColor.clear, range: NSRange(location: 0, length: attributedText.length)) label.attributedText = attributedText label.applyLinearGradient(colors: colors, startPoint: startPoint, endPoint: endPoint) ``` 通过上述代码,你可以将UILabel的文本设置为富文本,并应用线性渐变背景效果。请注意,这个代码示例是使用Swift编写的,所以你需要在你的iOS项目中创建一个适当的代码文件,并将其添加到你的项目中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值