plotboilerplate 1.12.8 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/changelog.md +26 -0
- package/dist/index.esm.js +292 -51
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/dist/plotboilerplate.browser.min.js +1 -1
- package/dist/plotboilerplate.browser.min.js.map +1 -1
- package/dist/plotboilerplate.js +306 -50
- package/dist/plotboilerplate.min.js +1 -1
- package/package.json +1 -1
- package/src/cjs/BezierPath.d.ts +12 -1
- package/src/cjs/BezierPath.js +34 -5
- package/src/cjs/BezierPath.js.map +1 -1
- package/src/cjs/PBText.d.ts +116 -0
- package/src/cjs/PBText.js +66 -0
- package/src/cjs/PBText.js.map +1 -0
- package/src/cjs/PlotBoilerplate.d.ts +2 -1
- package/src/cjs/PlotBoilerplate.js +41 -14
- package/src/cjs/PlotBoilerplate.js.map +1 -1
- package/src/cjs/Vertex.d.ts +18 -4
- package/src/cjs/Vertex.js +24 -7
- package/src/cjs/Vertex.js.map +1 -1
- package/src/cjs/draw.d.ts +30 -2
- package/src/cjs/draw.js +51 -6
- package/src/cjs/draw.js.map +1 -1
- package/src/cjs/drawgl.d.ts +29 -2
- package/src/cjs/drawgl.js +21 -4
- package/src/cjs/drawgl.js.map +1 -1
- package/src/cjs/drawutilssvg.d.ts +25 -7
- package/src/cjs/drawutilssvg.js +62 -14
- package/src/cjs/drawutilssvg.js.map +1 -1
- package/src/cjs/entry.js +1 -0
- package/src/cjs/index.d.ts +1 -0
- package/src/cjs/index.js +1 -0
- package/src/cjs/index.js.map +1 -1
- package/src/cjs/interfaces/DrawLib.d.ts +27 -6
- package/src/cjs/interfaces/DrawLib.js +3 -0
- package/src/cjs/interfaces/DrawLib.js.map +1 -1
- package/src/cjs/interfaces/core.d.ts +9 -1
- package/src/cjs/interfaces/core.js +1 -0
- package/src/cjs/interfaces/core.js.map +1 -1
- package/src/cjs/utils/datastructures/Color.d.ts +28 -15
- package/src/cjs/utils/datastructures/Color.js +276 -88
- package/src/cjs/utils/datastructures/Color.js.map +1 -1
- package/src/esm/BezierPath.d.ts +12 -1
- package/src/esm/BezierPath.js +34 -5
- package/src/esm/BezierPath.js.map +1 -1
- package/src/esm/PBText.d.ts +116 -0
- package/src/esm/PBText.js +61 -0
- package/src/esm/PBText.js.map +1 -0
- package/src/esm/PlotBoilerplate.d.ts +2 -1
- package/src/esm/PlotBoilerplate.js +41 -14
- package/src/esm/PlotBoilerplate.js.map +1 -1
- package/src/esm/Vertex.d.ts +18 -4
- package/src/esm/Vertex.js +24 -7
- package/src/esm/Vertex.js.map +1 -1
- package/src/esm/draw.d.ts +30 -2
- package/src/esm/draw.js +51 -6
- package/src/esm/draw.js.map +1 -1
- package/src/esm/drawgl.d.ts +29 -2
- package/src/esm/drawgl.js +21 -4
- package/src/esm/drawgl.js.map +1 -1
- package/src/esm/drawutilssvg.d.ts +25 -7
- package/src/esm/drawutilssvg.js +62 -14
- package/src/esm/drawutilssvg.js.map +1 -1
- package/src/esm/entry.js +1 -0
- package/src/esm/index.d.ts +1 -0
- package/src/esm/index.js +1 -0
- package/src/esm/index.js.map +1 -1
- package/src/esm/interfaces/DrawLib.d.ts +27 -6
- package/src/esm/interfaces/DrawLib.js +3 -0
- package/src/esm/interfaces/DrawLib.js.map +1 -1
- package/src/esm/interfaces/core.d.ts +9 -1
- package/src/esm/interfaces/core.js +1 -0
- package/src/esm/interfaces/core.js.map +1 -1
- package/src/esm/utils/datastructures/Color.d.ts +28 -15
- package/src/esm/utils/datastructures/Color.js +277 -89
- package/src/esm/utils/datastructures/Color.js.map +1 -1
- package/src/ts/BezierPath.ts +37 -5
- package/src/ts/PBText.ts +147 -0
- package/src/ts/PlotBoilerplate.ts +44 -18
- package/src/ts/Vertex.ts +26 -7
- package/src/ts/draw.ts +71 -8
- package/src/ts/drawgl.ts +48 -8
- package/src/ts/drawutilssvg.ts +94 -17
- package/src/ts/index.ts +1 -0
- package/src/ts/interfaces/DrawLib.ts +30 -4
- package/src/ts/interfaces/core.ts +9 -0
- package/src/ts/utils/datastructures/Color.ts +695 -508
- package/dist/plotboilerplate.browser.min.js.LICENSE.txt +0 -8
- package/src/ts/utils/algorithms/clearPolygonDuplicateVertices.ts~ +0 -5
- package/src/ts/utils/algorithms/findPolygonSelfIntersections.ts~ +0 -45
- package/src/ts/utils/algorithms/splitPolygonToNonIntersecting.ts~ +0 -113
- package/src/ts/utils/algorithms/sutherlandHodgman.ts~ +0 -88
- package/src/ts/utils/datastructures/Color.ts~ +0 -331
- package/src/ts/utils/datastructures/Girih.ts~ +0 -151
- package/src/ts/utils/datastructures/GirihTile.ts~ +0 -419
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @requires Line
|
|
3
|
-
* @requires Vertex
|
|
4
|
-
*
|
|
5
|
-
* @author Ikaros Kappler
|
|
6
|
-
* @date 2020-12-04
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Collect all self-intersection points of the given polygon.
|
|
12
|
-
*
|
|
13
|
-
* @name findPolygonSelfIntersections
|
|
14
|
-
* @param {Array<Vertex>} polygon
|
|
15
|
-
* @return Array<Vertex>
|
|
16
|
-
*/
|
|
17
|
-
var findPolygonSelfIntersections = function( polygon ) {
|
|
18
|
-
var pointList = [];
|
|
19
|
-
var lineA = new Line( new Vertex(), new Vertex() );
|
|
20
|
-
var lineB = new Line( new Vertex(), new Vertex() );
|
|
21
|
-
for( var a = 0; a < polygon.vertices.length; a++ ) {
|
|
22
|
-
lineA.a.set( polygon.getVertexAt(a) );
|
|
23
|
-
lineA.b.set( polygon.getVertexAt(a+1) );
|
|
24
|
-
for( var b = 0; b < polygon.vertices.length; b++ ) {
|
|
25
|
-
// Same edge or neighbour edges intersect by definition.
|
|
26
|
-
// Skip them.
|
|
27
|
-
if( a == b || a+1 == b || a == b+1
|
|
28
|
-
|| (a==0&&b+1==polygon.vertices.length) || (b==0&&a+1==polygon.vertices.length) )
|
|
29
|
-
continue;
|
|
30
|
-
lineB.a.set( polygon.getVertexAt(b) );
|
|
31
|
-
lineB.b.set( polygon.getVertexAt(b+1) );
|
|
32
|
-
|
|
33
|
-
// Commpute the intersection point of the (infinite) lines.
|
|
34
|
-
// The point is undefined if and only if both line are parallel (co-linear).
|
|
35
|
-
const intersectionPoint = lineA.intersection(lineB);
|
|
36
|
-
|
|
37
|
-
// Check if the intersection point is on both (finite) edges of the polygon.
|
|
38
|
-
if( intersectionPoint
|
|
39
|
-
&& lineA.hasPoint(intersectionPoint) && lineB.hasPoint(intersectionPoint) ) {
|
|
40
|
-
pointList.push( intersectionPoint );
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return pointList;
|
|
45
|
-
};
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This function cuts a given self-intersecting polygon into non-self-intersecting
|
|
3
|
-
* sub polygons.
|
|
4
|
-
*
|
|
5
|
-
* The algorithm only works for non-self-overlapping polygons.
|
|
6
|
-
* Please note that the union set of the sub polygons themselves will _not_ be disjunct if
|
|
7
|
-
* the input polyon overlaps with itself!
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* @requires Line
|
|
11
|
-
* @requires Vertex
|
|
12
|
-
* @requires greinerHormann
|
|
13
|
-
*
|
|
14
|
-
* @date 2020-12-04
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
(function(_context) {
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @param {Array<Vertex>} vertices
|
|
21
|
-
* @param {number=10} maxDepth
|
|
22
|
-
*/
|
|
23
|
-
var splitToNonIntersectingPolygons = function( vertices, maxDepth ) {
|
|
24
|
-
if( typeof maxDepth === "undefined" )
|
|
25
|
-
maxDepth = 10;
|
|
26
|
-
return _splitToNonIntersectingPolygons( vertices, maxDepth );
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
var _splitToNonIntersectingPolygons = function( vertices, maxDepth ) {
|
|
31
|
-
|
|
32
|
-
if( maxDepth <= 0 ) {
|
|
33
|
-
console.log('aborting at max depth');
|
|
34
|
-
return [ vertices ];
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if( vertices.length <= 3 ) {
|
|
38
|
-
// No intersections possible
|
|
39
|
-
return [ vertices ];
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// var pointList = [];
|
|
43
|
-
var n = vertices.length;
|
|
44
|
-
var lineA = new Line( new Vertex(), new Vertex() );
|
|
45
|
-
var lineB = new Line( new Vertex(), new Vertex() );
|
|
46
|
-
for( var a = 0; a < vertices.length; a++ ) {
|
|
47
|
-
lineA.a.set( vertices[a] );
|
|
48
|
-
lineA.b.set( vertices[(a+1) % n] );
|
|
49
|
-
for( var b = 0; b < vertices.length; b++ ) {
|
|
50
|
-
// Equal or neighbour edges intersect by definition.
|
|
51
|
-
// We ignore them.
|
|
52
|
-
if( a == b || a+1 == b || a == b+1 || (a==0&&b+1==vertices.length) || (b==0&&a+1==vertices.length) )
|
|
53
|
-
continue;
|
|
54
|
-
lineB.a.set( vertices[b] );
|
|
55
|
-
lineB.b.set( vertices[(b+1) % n] );
|
|
56
|
-
|
|
57
|
-
const intersectionPoint = lineA.intersection(lineB);
|
|
58
|
-
// console.log( 'intersectionPoint', intersectionPoint );
|
|
59
|
-
if( intersectionPoint && lineA.hasPoint(intersectionPoint) && lineB.hasPoint(intersectionPoint) ) {
|
|
60
|
-
// console.log( 'intersection found' );
|
|
61
|
-
// pointList.push( intersectionPoint );
|
|
62
|
-
// Cut polygon into two here
|
|
63
|
-
var split = splitPolygonAt( vertices, a, b, intersectionPoint );
|
|
64
|
-
|
|
65
|
-
// Split has 2 elements.
|
|
66
|
-
var leftCleaned = _splitToNonIntersectingPolygons( split[0], maxDepth-1 );
|
|
67
|
-
var rightCleaned = _splitToNonIntersectingPolygons( split[1], maxDepth-1 );
|
|
68
|
-
|
|
69
|
-
return leftCleaned.concat( rightCleaned );
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
// console.log( 'intersectionPoints', pointList );
|
|
74
|
-
|
|
75
|
-
// No intersection found:
|
|
76
|
-
// just return a list with the original
|
|
77
|
-
// polygon as its only element.
|
|
78
|
-
return [ vertices ];
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
// Pre: edgeIndexA < edgeIndexB && vertices.length >= 4
|
|
83
|
-
var splitPolygonAt = function( vertices, edgeIndexA, edgeIndexB, intersectionPoint ) {
|
|
84
|
-
|
|
85
|
-
// console.log( 'split', edgeIndexA, edgeIndexB );
|
|
86
|
-
|
|
87
|
-
var first = [];
|
|
88
|
-
var second = [];
|
|
89
|
-
for( var i = 0; i < vertices.length; i++ ) {
|
|
90
|
-
if( i <= edgeIndexA )
|
|
91
|
-
first.push( vertices[i] );
|
|
92
|
-
|
|
93
|
-
if( i == edgeIndexA ) {
|
|
94
|
-
first.push( intersectionPoint );
|
|
95
|
-
second.push( intersectionPoint ); // clone???
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if( i > edgeIndexA && i <= edgeIndexB )
|
|
99
|
-
second.push( vertices[i] );
|
|
100
|
-
|
|
101
|
-
if( i > edgeIndexB )
|
|
102
|
-
first.push( vertices[i] );
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// console.log( 'split', first, second );
|
|
107
|
-
|
|
108
|
-
return [ first, second ];
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
_context.splitToNonIntersectingPolygons = splitToNonIntersectingPolygons;
|
|
112
|
-
|
|
113
|
-
})(globalThis || window);
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The Sutherland-Hodgman convex polygon clipping algorithm.
|
|
5
|
-
*
|
|
6
|
-
* Converted to Vertex variant {x:number,y:number} by Ikaros Kappler.
|
|
7
|
-
*
|
|
8
|
-
* @date 2021-01-29
|
|
9
|
-
* @version 1.0.0
|
|
10
|
-
*
|
|
11
|
-
* Original version:
|
|
12
|
-
* https://rosettacode.org/wiki/Sutherland-Hodgman_polygon_clipping#JavaScript
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
(function() {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* @param {Vertex}
|
|
22
|
-
* @param {Vertex}
|
|
23
|
-
**/
|
|
24
|
-
var inside = function (_cp1,_cp2,p) {
|
|
25
|
-
// console.log('x', _cp1);
|
|
26
|
-
return (_cp2.x-_cp1.x)*(p.y-_cp1.y) > (_cp2.y-_cp1.y)*(p.x-_cp1.x);
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @param {Vertex}
|
|
31
|
-
* @param {Vertex}
|
|
32
|
-
* @param {Vertex}
|
|
33
|
-
* @param {Vertex}
|
|
34
|
-
*/
|
|
35
|
-
var intersection = function (_cp1,_cp2,_s,_e) {
|
|
36
|
-
var
|
|
37
|
-
dc = { x: _cp1.x - _cp2.x,
|
|
38
|
-
y : _cp1.y - _cp2.y
|
|
39
|
-
},
|
|
40
|
-
dp = { x: _s.x - _e.x,
|
|
41
|
-
y : _s.y - _e.y
|
|
42
|
-
},
|
|
43
|
-
n1 = _cp1.x * _cp2.y - _cp1.y * _cp2.x,
|
|
44
|
-
n2 = _s.x * _e.y - _s.y * _e.x,
|
|
45
|
-
n3 = 1.0 / (dc.x * dp.y - dc.y * dp.x);
|
|
46
|
-
return { x : (n1*dp.x - n2*dc.x) * n3,
|
|
47
|
-
y : (n1*dp.y - n2*dc.y) * n3
|
|
48
|
-
};
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* @param {Array<Vertex>} subjectPolygon
|
|
54
|
-
* @param {Array<Vertex>} clipPolygon - Must be convex.
|
|
55
|
-
*/
|
|
56
|
-
var sutherlandHodgman = function(subjectPolygon, clipPolygon) {
|
|
57
|
-
|
|
58
|
-
var cp1, cp2, s, e;
|
|
59
|
-
|
|
60
|
-
var outputList = subjectPolygon;
|
|
61
|
-
cp1 = clipPolygon[clipPolygon.length-1];
|
|
62
|
-
|
|
63
|
-
for (var j in clipPolygon) {
|
|
64
|
-
var cp2 = clipPolygon[j];
|
|
65
|
-
var inputList = outputList;
|
|
66
|
-
outputList = [];
|
|
67
|
-
s = inputList[inputList.length - 1]; // last on the input list
|
|
68
|
-
for (var i in inputList) {
|
|
69
|
-
var e = inputList[i];
|
|
70
|
-
if (inside(cp1,cp2,e)) {
|
|
71
|
-
if (!inside(cp1,cp2,s)) {
|
|
72
|
-
outputList.push(intersection(cp1,cp2,s,e));
|
|
73
|
-
}
|
|
74
|
-
outputList.push(e);
|
|
75
|
-
}
|
|
76
|
-
else if (inside(cp1,cp2,s)) {
|
|
77
|
-
outputList.push(intersection(cp1,cp2,s,e));
|
|
78
|
-
}
|
|
79
|
-
s = e;
|
|
80
|
-
}
|
|
81
|
-
cp1 = cp2;
|
|
82
|
-
}
|
|
83
|
-
return outputList
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
globalThis.sutherlandHodgman = sutherlandHodgman;
|
|
87
|
-
|
|
88
|
-
})();
|
|
@@ -1,331 +0,0 @@
|
|
|
1
|
-
// Found at
|
|
2
|
-
// https://gist.github.com/neolitec/1344610
|
|
3
|
-
// Thanks to neolitec
|
|
4
|
-
//
|
|
5
|
-
// @modified 2018-xx-xx Added a clone() function.
|
|
6
|
-
// @modified 2018-xx-xx Allowing leading '#' in the makeHEX() function.
|
|
7
|
-
// @modified 2018-11-28 Fixed the checkHEX() function to accept 000000.
|
|
8
|
-
// @modified 2019-11-18 Added a generic parse(string) function that detects the format.
|
|
9
|
-
// @modified 2020-01-09 Fixed a bug in the parse(string) function. Hex colors with only three elements were considered faulty.
|
|
10
|
-
// @modified 2020-10-23 TS
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export class Color {
|
|
14
|
-
|
|
15
|
-
r : number;
|
|
16
|
-
g : number;
|
|
17
|
-
b : number;
|
|
18
|
-
|
|
19
|
-
h : number;
|
|
20
|
-
s : number;
|
|
21
|
-
l : number;
|
|
22
|
-
|
|
23
|
-
a : number;
|
|
24
|
-
|
|
25
|
-
constructor() {
|
|
26
|
-
this.r = this.g = this.b = 0;
|
|
27
|
-
this.h = this.s = this.l = 0;
|
|
28
|
-
this.a = 1;
|
|
29
|
-
};
|
|
30
|
-
/** RGB */
|
|
31
|
-
Color.prototype.cssRGB = function() {
|
|
32
|
-
return "rgb("+Math.round(255*this.r)+","+Math.round(255*this.g)+","+Math.round(255*this.b)+")";
|
|
33
|
-
};
|
|
34
|
-
Color.prototype.cssRGBA = function() {
|
|
35
|
-
return "rgba("+Math.round(255*this.r)+","+Math.round(255*this.g)+","+Math.round(255*this.b)+","+this.a+")";
|
|
36
|
-
};
|
|
37
|
-
Color.prototype.red = function() { return this.r; };
|
|
38
|
-
Color.prototype.green = function() { return this.g; };
|
|
39
|
-
Color.prototype.blue = function() { return this.b; };
|
|
40
|
-
/** HSL */
|
|
41
|
-
Color.prototype.cssHSL = function() {
|
|
42
|
-
return "hsl("+Math.round(360*this.h)+","+Math.round(100*this.s)+"%,"+Math.round(100*this.l)+"%)";
|
|
43
|
-
};
|
|
44
|
-
Color.prototype.cssHSLA = function() {
|
|
45
|
-
return "hsla("+Math.round(360*this.h)+","+Math.round(100*this.s)+"%,"+Math.round(100*this.l)+"%,"+Math.round(this.a)+")";
|
|
46
|
-
};
|
|
47
|
-
Color.prototype.hue = function() { return this.h; };
|
|
48
|
-
Color.prototype.saturation = function() { return this.s; };
|
|
49
|
-
Color.prototype.lightness = function() { return this.l; };
|
|
50
|
-
/** HEX */
|
|
51
|
-
Color.prototype.cssHEX = function() {
|
|
52
|
-
return "#" +
|
|
53
|
-
(255*this.r < 16 ? "0" : "") + Math.round(255*this.r).toString(16) +
|
|
54
|
-
(255*this.g < 16 ? "0" : "") + Math.round(255*this.g).toString(16) +
|
|
55
|
-
(255*this.b < 16 ? "0" : "") + Math.round(255*this.b).toString(16);
|
|
56
|
-
}
|
|
57
|
-
/** Transparency */
|
|
58
|
-
Color.prototype.alpha = function() { return this.a; };
|
|
59
|
-
/** Modifiers */
|
|
60
|
-
Color.prototype.saturate = function(v) {
|
|
61
|
-
if("string" == typeof v && v.indexOf("%") > -1 && (v = parseInt(v)) != 'NaN')
|
|
62
|
-
this.s += v/100;
|
|
63
|
-
else if("number" == typeof v) // range 255
|
|
64
|
-
this.s += v/255;
|
|
65
|
-
else throw new Error("error: bad modifier format (percent or number)");
|
|
66
|
-
if(this.s > 1) this.s = 1; else if(this.s < 0) this.s = 0;
|
|
67
|
-
Color.Convertor.HSLToRGB.apply(this);
|
|
68
|
-
};
|
|
69
|
-
Color.prototype.desaturate = function(v) {
|
|
70
|
-
this.saturate("-" + v);
|
|
71
|
-
};
|
|
72
|
-
Color.prototype.lighten = function(v) {
|
|
73
|
-
if("string" == typeof v && v.indexOf("%") > -1 && (v = parseInt(v)) != 'NaN')
|
|
74
|
-
this.l += v/100;
|
|
75
|
-
else if("number" == typeof v) // range 255
|
|
76
|
-
this.l += v/255;
|
|
77
|
-
else throw new Error("error: bad modifier format (percent or number)");
|
|
78
|
-
if(this.l > 1) this.l = 1; else if(this.l < 0) this.l = 0;
|
|
79
|
-
Color.Convertor.HSLToRGB.apply(this);
|
|
80
|
-
};
|
|
81
|
-
Color.prototype.darken = function(v) {
|
|
82
|
-
this.ligthen("-" + v);
|
|
83
|
-
};
|
|
84
|
-
Color.prototype.fadein = function(v) {
|
|
85
|
-
if("string" == typeof v && v.indexOf("%") > -1 && (v = parseInt(v)) != 'NaN')
|
|
86
|
-
this.a += v/100;
|
|
87
|
-
else if("number" == typeof v) // range 255
|
|
88
|
-
this.a += v/255;
|
|
89
|
-
else throw new Error("error: bad modifier format (percent or number)");
|
|
90
|
-
if(this.a > 1) this.a = 1; else if(this.a < 0) this.a = 0;
|
|
91
|
-
Color.Convertor.HSLToRGB.apply(this);
|
|
92
|
-
};
|
|
93
|
-
Color.prototype.fadeout = function(v) {
|
|
94
|
-
this.fadein("-" + v);
|
|
95
|
-
};
|
|
96
|
-
Color.prototype.spin = function(v) {
|
|
97
|
-
if("string" == typeof v && v.indexOf("%") > -1 && (v = parseInt(v)) != 'NaN')
|
|
98
|
-
this.h += v/100;
|
|
99
|
-
else if("number" == typeof v) // range 360
|
|
100
|
-
this.h += v/360;
|
|
101
|
-
else throw new Error("error: bad modifier format (percent or number)");
|
|
102
|
-
if(this.h > 1) this.h = 1; else if(this.h < 0) this.h = 0;
|
|
103
|
-
Color.Convertor.HSLToRGB.apply(this);
|
|
104
|
-
};
|
|
105
|
-
/** Debug */
|
|
106
|
-
Color.prototype.toString = function() {
|
|
107
|
-
return "<span style=\"color: "+this.cssRGB()+"\">"+this.cssRGB()+"</span> / <span style=\"color: "+this.cssHSL()+"\">"+this.cssHSL()+"</span> / <span style=\"color: "+this.cssHEX()+"\">"+this.cssHEX()+"</span> / alpha: "+this.a+"";
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
Color.makeRGB = function() {
|
|
111
|
-
var c = new Color(),
|
|
112
|
-
sanitized;
|
|
113
|
-
if(arguments.length < 3 || arguments.length > 4)
|
|
114
|
-
throw new Error("error: 3 or 4 arguments");
|
|
115
|
-
sanitized = Color.Sanitizer.RGB(arguments[0], arguments[1], arguments[2]);
|
|
116
|
-
c.r = sanitized[0];
|
|
117
|
-
c.g = sanitized[1];
|
|
118
|
-
c.b = sanitized[2];
|
|
119
|
-
if(arguments.length == 4) c.a = arguments[3];
|
|
120
|
-
Color.Convertor.RGBToHSL.apply(c);
|
|
121
|
-
return c;
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
Color.makeHSL = function() {
|
|
125
|
-
var c = new Color(),
|
|
126
|
-
sanitized;
|
|
127
|
-
if(arguments.length < 3 || arguments.length > 4)
|
|
128
|
-
throw new Error("error: 3 or 4 arguments");
|
|
129
|
-
sanitized = Color.Sanitizer.HSL(arguments[0], arguments[1], arguments[2]);
|
|
130
|
-
c.h = sanitized[0];
|
|
131
|
-
c.s = sanitized[1];
|
|
132
|
-
c.l = sanitized[2];
|
|
133
|
-
if(arguments.length == 4) c.a = arguments[3];
|
|
134
|
-
Color.Convertor.HSLToRGB.apply(c);
|
|
135
|
-
return c;
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
Color.makeHEX = function(value) {
|
|
139
|
-
var c = new Color(),
|
|
140
|
-
sanitized;
|
|
141
|
-
// Edit Ika 2018-0308
|
|
142
|
-
// Allow leading '#'
|
|
143
|
-
if( value && value.startsWith('#') )
|
|
144
|
-
value = value.substr(1);
|
|
145
|
-
Color.Validator.checkHEX(value);
|
|
146
|
-
if(value.length == 3) {
|
|
147
|
-
sanitized = Color.Sanitizer.RGB(
|
|
148
|
-
parseInt(value.substr(0, 1) + value.substr(0, 1), 16),
|
|
149
|
-
parseInt(value.substr(1, 1) + value.substr(1, 1), 16),
|
|
150
|
-
parseInt(value.substr(2, 1) + value.substr(2, 1), 16)
|
|
151
|
-
);
|
|
152
|
-
} else if(value.length == 6) {
|
|
153
|
-
sanitized = Color.Sanitizer.RGB(
|
|
154
|
-
parseInt(value.substr(0, 2), 16),
|
|
155
|
-
parseInt(value.substr(2, 2), 16),
|
|
156
|
-
parseInt(value.substr(4, 2), 16)
|
|
157
|
-
);
|
|
158
|
-
} else throw new Error("error: 3 or 6 arguments");
|
|
159
|
-
c.r = sanitized[0];
|
|
160
|
-
c.g = sanitized[1];
|
|
161
|
-
c.b = sanitized[2];
|
|
162
|
-
Color.Convertor.RGBToHSL.apply(c);
|
|
163
|
-
return c;
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
Color.parse = function( str ) {
|
|
167
|
-
if( typeof str == 'undefined' )
|
|
168
|
-
return null;
|
|
169
|
-
if( (str = str.trim().toLowerCase()).length == 0 )
|
|
170
|
-
return null;
|
|
171
|
-
if( str.startsWith('#') )
|
|
172
|
-
return Color.makeHEX(str.substring(1,str.length));
|
|
173
|
-
if( str.startsWith('rgb') ) {
|
|
174
|
-
var open = str.indexOf('(');
|
|
175
|
-
var close = str.indexOf(')');
|
|
176
|
-
|
|
177
|
-
var parts = /^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(0\.\d+))?\)$/.exec(str);
|
|
178
|
-
// [ str, r, g, b, a|undefined ]
|
|
179
|
-
if( typeof parts[4] == 'undefined' )
|
|
180
|
-
return Color.makeRGB(parts[1],parts[2],parts[3]);
|
|
181
|
-
else
|
|
182
|
-
return Color.makeRGB(parts[1],parts[2],parts[3],parts[4]);
|
|
183
|
-
}
|
|
184
|
-
else
|
|
185
|
-
throw "Unrecognized color format: " + str;
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
// Test parser
|
|
189
|
-
// Color.parse('rgba(28,192,255,0.5)');
|
|
190
|
-
// Color.parse('rgb(28,192,255)');
|
|
191
|
-
// Color.parse('Xrgb(28,192,255)'); // Should throw exception
|
|
192
|
-
|
|
193
|
-
Color.Sanitizer = {
|
|
194
|
-
RGB: function() {
|
|
195
|
-
var o = [];
|
|
196
|
-
if(arguments.length == 0) return;
|
|
197
|
-
for(var i = 0 ; i < arguments.length ; i++) {
|
|
198
|
-
var c = arguments[i];
|
|
199
|
-
if("string" == typeof c && c.indexOf("%") > -1) {
|
|
200
|
-
if((c = parseInt(c)) == 'NaN')
|
|
201
|
-
throw new Error("Bad format");
|
|
202
|
-
if(c < 0 || c > 100)
|
|
203
|
-
throw new Error("Bad format");
|
|
204
|
-
o[i] = c/100;
|
|
205
|
-
} else {
|
|
206
|
-
if("string" == typeof c && (c = parseInt(c)) == 'NaN') throw new Error("Bad format");
|
|
207
|
-
if(c < 0) throw new Error("Bad format");
|
|
208
|
-
else if(c >= 0 && c < 1) o[i] = c;
|
|
209
|
-
else if(c >= 1 && c < 256) o[i] = c/255;
|
|
210
|
-
else throw new Error("Bad format ("+c+")");
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
return o;
|
|
214
|
-
},
|
|
215
|
-
HSL: function() {
|
|
216
|
-
if(arguments.length < 3 || arguments.length > 4) throw new Error("3 or 4 arguments required");
|
|
217
|
-
var h = arguments[0],
|
|
218
|
-
s = arguments[1],
|
|
219
|
-
l = arguments[2];
|
|
220
|
-
if("string" == typeof h && (h = parseFloat(h)) == 'NaN') throw new Error("Bad format for hue");
|
|
221
|
-
if(h < 0 || h > 360) throw new Error("Hue out of range (0..360)");
|
|
222
|
-
else if(((""+h).indexOf(".") > -1 && h > 1) || (""+h).indexOf(".") == -1) h /= 360;
|
|
223
|
-
if("string" == typeof s && s.indexOf("%") > -1) {
|
|
224
|
-
if((s = parseInt(s)) == 'NaN')
|
|
225
|
-
throw new Error("Bad format for saturation");
|
|
226
|
-
if(s < 0 || s > 100)
|
|
227
|
-
throw new Error("Bad format for saturation");
|
|
228
|
-
s /= 100;
|
|
229
|
-
} else if(s < 0 || s > 1) throw new Error("Bad format for saturation");
|
|
230
|
-
if("string" == typeof l && l.indexOf("%") > -1) {
|
|
231
|
-
if((l = parseInt(l)) == 'NaN')
|
|
232
|
-
throw new Error("Bad format for lightness");
|
|
233
|
-
if(l < 0 || l > 100)
|
|
234
|
-
throw new Error("Bad format for lightness");
|
|
235
|
-
l /= 100;
|
|
236
|
-
} else if(l < 0 || l > 1) throw new Error("Bad format for lightness");
|
|
237
|
-
return [h, s, l];
|
|
238
|
-
},
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
Color.Validator = {
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* Check a hexa color (without #)
|
|
245
|
-
*/
|
|
246
|
-
checkHEX: function(value) {
|
|
247
|
-
|
|
248
|
-
if(value.length != 6 && value.length != 3)
|
|
249
|
-
throw new Error("Hexa color: bad length ("+value.length+")," + value);
|
|
250
|
-
value = value.toLowerCase();
|
|
251
|
-
for(i in value) {
|
|
252
|
-
var c = value.charCodeAt(i);
|
|
253
|
-
if( !((c>=48 && c<=57) || (c>=97 && c<=102)) )
|
|
254
|
-
throw new Error("Hexa color: out of range for " + value + " at position " + i);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
Color.Convertor = {
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Calculates HSL Color
|
|
263
|
-
* RGB must be normalized
|
|
264
|
-
* Must be executed in a Color object context
|
|
265
|
-
* http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
|
|
266
|
-
*/
|
|
267
|
-
RGBToHSL: function() {
|
|
268
|
-
//
|
|
269
|
-
var r = this.r,
|
|
270
|
-
g = this.g,
|
|
271
|
-
b = this.b,
|
|
272
|
-
max = Math.max(r, g, b), min = Math.min(r, g, b);
|
|
273
|
-
this.l = (max + min) / 2;
|
|
274
|
-
if(max == min){
|
|
275
|
-
this.h = this.s = 0; // achromatic
|
|
276
|
-
} else {
|
|
277
|
-
var d = max - min;
|
|
278
|
-
this.s = this.l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
279
|
-
switch(max){
|
|
280
|
-
case r: this.h = (g - b) / d + (g < b ? 6 : 0); break;
|
|
281
|
-
case g: this.h = (b - r) / d + 2; break;
|
|
282
|
-
case b: this.h = (r - g) / d + 4; break;
|
|
283
|
-
}
|
|
284
|
-
this.h /= 6;
|
|
285
|
-
}
|
|
286
|
-
},
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* Calculates RGB color (nomalized)
|
|
290
|
-
* HSL must be normalized
|
|
291
|
-
* Must be executed in a Color object context
|
|
292
|
-
* http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
|
|
293
|
-
*/
|
|
294
|
-
HSLToRGB: function() {
|
|
295
|
-
var h = this.h,
|
|
296
|
-
s = this.s,
|
|
297
|
-
l = this.l,
|
|
298
|
-
hue2rgb = function(p, q, t){
|
|
299
|
-
if(t < 0) t += 1;
|
|
300
|
-
if(t > 1) t -= 1;
|
|
301
|
-
if(t < 1/6) return p + (q - p) * 6 * t;
|
|
302
|
-
if(t < 1/2) return q;
|
|
303
|
-
if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
|
|
304
|
-
return p;
|
|
305
|
-
};
|
|
306
|
-
if(s == 0) {
|
|
307
|
-
this.r = this.g = this.b = l; // achromatic
|
|
308
|
-
} else {
|
|
309
|
-
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
310
|
-
var p = 2 * l - q;
|
|
311
|
-
this.r = hue2rgb(p, q, h + 1/3);
|
|
312
|
-
this.g = hue2rgb(p, q, h);
|
|
313
|
-
this.b = hue2rgb(p, q, h - 1/3);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
// Added by Ika 2017-0-19
|
|
321
|
-
Color.prototype.clone = function() {
|
|
322
|
-
return Color.makeRGB(this.r, this.g, this.b, this.a);
|
|
323
|
-
};
|
|
324
|
-
// Added by Ika 2018-12-30
|
|
325
|
-
Color.prototype.interpolate = function( c, t ) {
|
|
326
|
-
this.r += (c.r-c.r)*t;
|
|
327
|
-
this.g += (c.g-c.g)*t;
|
|
328
|
-
this.b += (c.b-c.b)*t;
|
|
329
|
-
this.a += (c.a-c.a)*t;
|
|
330
|
-
return this;
|
|
331
|
-
};
|