UNPKG

4.54 kBJavaScriptView Raw
1
2/*!
3 * Stylus - HSLA
4 * Copyright (c) Automattic <developer.wordpress.com>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
12var Node = require('./node')
13 , nodes = require('./');
14
15/**
16 * Initialize a new `HSLA` with the given h,s,l,a component values.
17 *
18 * @param {Number} h
19 * @param {Number} s
20 * @param {Number} l
21 * @param {Number} a
22 * @api public
23 */
24
25var HSLA = exports = module.exports = function HSLA(h,s,l,a){
26 Node.call(this);
27 this.h = clampDegrees(h);
28 this.s = clampPercentage(s);
29 this.l = clampPercentage(l);
30 this.a = clampAlpha(a);
31 this.hsla = this;
32};
33
34/**
35 * Inherit from `Node.prototype`.
36 */
37
38HSLA.prototype.__proto__ = Node.prototype;
39
40/**
41 * Return hsla(n,n,n,n).
42 *
43 * @return {String}
44 * @api public
45 */
46
47HSLA.prototype.toString = function(){
48 return 'hsla('
49 + this.h + ','
50 + this.s.toFixed(0) + '%,'
51 + this.l.toFixed(0) + '%,'
52 + this.a + ')';
53};
54
55/**
56 * Return a clone of this node.
57 *
58 * @return {Node}
59 * @api public
60 */
61
62HSLA.prototype.clone = function(parent){
63 var clone = new HSLA(
64 this.h
65 , this.s
66 , this.l
67 , this.a);
68 clone.lineno = this.lineno;
69 clone.column = this.column;
70 clone.filename = this.filename;
71 return clone;
72};
73
74/**
75 * Return a JSON representation of this node.
76 *
77 * @return {Object}
78 * @api public
79 */
80
81HSLA.prototype.toJSON = function(){
82 return {
83 __type: 'HSLA',
84 h: this.h,
85 s: this.s,
86 l: this.l,
87 a: this.a,
88 lineno: this.lineno,
89 column: this.column,
90 filename: this.filename
91 };
92};
93
94/**
95 * Return rgba `RGBA` representation.
96 *
97 * @return {RGBA}
98 * @api public
99 */
100
101HSLA.prototype.__defineGetter__('rgba', function(){
102 return nodes.RGBA.fromHSLA(this);
103});
104
105/**
106 * Return hash.
107 *
108 * @return {String}
109 * @api public
110 */
111
112HSLA.prototype.__defineGetter__('hash', function(){
113 return this.rgba.toString();
114});
115
116/**
117 * Add h,s,l to the current component values.
118 *
119 * @param {Number} h
120 * @param {Number} s
121 * @param {Number} l
122 * @return {HSLA} new node
123 * @api public
124 */
125
126HSLA.prototype.add = function(h,s,l){
127 return new HSLA(
128 this.h + h
129 , this.s + s
130 , this.l + l
131 , this.a);
132};
133
134/**
135 * Subtract h,s,l from the current component values.
136 *
137 * @param {Number} h
138 * @param {Number} s
139 * @param {Number} l
140 * @return {HSLA} new node
141 * @api public
142 */
143
144HSLA.prototype.sub = function(h,s,l){
145 return this.add(-h, -s, -l);
146};
147
148/**
149 * Operate on `right` with the given `op`.
150 *
151 * @param {String} op
152 * @param {Node} right
153 * @return {Node}
154 * @api public
155 */
156
157HSLA.prototype.operate = function(op, right){
158 switch (op) {
159 case '==':
160 case '!=':
161 case '<=':
162 case '>=':
163 case '<':
164 case '>':
165 case 'is a':
166 case '||':
167 case '&&':
168 return this.rgba.operate(op, right);
169 default:
170 return this.rgba.operate(op, right).hsla;
171 }
172};
173
174/**
175 * Return `HSLA` representation of the given `color`.
176 *
177 * @param {RGBA} color
178 * @return {HSLA}
179 * @api public
180 */
181
182exports.fromRGBA = function(rgba){
183 var r = rgba.r / 255
184 , g = rgba.g / 255
185 , b = rgba.b / 255
186 , a = rgba.a;
187
188 var min = Math.min(r,g,b)
189 , max = Math.max(r,g,b)
190 , l = (max + min) / 2
191 , d = max - min
192 , h, s;
193
194 switch (max) {
195 case min: h = 0; break;
196 case r: h = 60 * (g-b) / d; break;
197 case g: h = 60 * (b-r) / d + 120; break;
198 case b: h = 60 * (r-g) / d + 240; break;
199 }
200
201 if (max == min) {
202 s = 0;
203 } else if (l < .5) {
204 s = d / (2 * l);
205 } else {
206 s = d / (2 - 2 * l);
207 }
208
209 h %= 360;
210 s *= 100;
211 l *= 100;
212
213 return new HSLA(h,s,l,a);
214};
215
216/**
217 * Adjust lightness by `percent`.
218 *
219 * @param {Number} percent
220 * @return {HSLA} for chaining
221 * @api public
222 */
223
224HSLA.prototype.adjustLightness = function(percent){
225 this.l = clampPercentage(this.l + this.l * (percent / 100));
226 return this;
227};
228
229/**
230 * Adjust hue by `deg`.
231 *
232 * @param {Number} deg
233 * @return {HSLA} for chaining
234 * @api public
235 */
236
237HSLA.prototype.adjustHue = function(deg){
238 this.h = clampDegrees(this.h + deg);
239 return this;
240};
241
242/**
243 * Clamp degree `n` >= 0 and <= 360.
244 *
245 * @param {Number} n
246 * @return {Number}
247 * @api private
248 */
249
250function clampDegrees(n) {
251 n = n % 360;
252 return n >= 0 ? n : 360 + n;
253}
254
255/**
256 * Clamp percentage `n` >= 0 and <= 100.
257 *
258 * @param {Number} n
259 * @return {Number}
260 * @api private
261 */
262
263function clampPercentage(n) {
264 return Math.max(0, Math.min(n, 100));
265}
266
267/**
268 * Clamp alpha `n` >= 0 and <= 1.
269 *
270 * @param {Number} n
271 * @return {Number}
272 * @api private
273 */
274
275function clampAlpha(n) {
276 return Math.max(0, Math.min(n, 1));
277}