diff options
Diffstat (limited to 'src/types')
-rw-r--r-- | src/types/Box.js | 116 | ||||
-rw-r--r-- | src/types/Color.js | 230 | ||||
-rw-r--r-- | src/types/EventTarget.js | 18 | ||||
-rw-r--r-- | src/types/List.js | 14 | ||||
-rw-r--r-- | src/types/Matrix.js | 239 | ||||
-rw-r--r-- | src/types/PathArray.js | 13 | ||||
-rw-r--r-- | src/types/Point.js | 21 | ||||
-rw-r--r-- | src/types/PointArray.js | 34 | ||||
-rw-r--r-- | src/types/SVGArray.js | 17 | ||||
-rw-r--r-- | src/types/SVGNumber.js | 44 |
10 files changed, 398 insertions, 348 deletions
diff --git a/src/types/Box.js b/src/types/Box.js index ab19732..cd441ac 100644 --- a/src/types/Box.js +++ b/src/types/Box.js @@ -6,46 +6,55 @@ import Matrix from './Matrix.js' import Point from './Point.js' import parser from '../modules/core/parser.js' -export function isNulledBox (box) { +export function isNulledBox(box) { return !box.width && !box.height && !box.x && !box.y } -export function domContains (node) { - return node === globals.document - || (globals.document.documentElement.contains || function (node) { - // This is IE - it does not support contains() for top-level SVGs - while (node.parentNode) { - node = node.parentNode +export function domContains(node) { + return ( + node === globals.document || + ( + globals.document.documentElement.contains || + function (node) { + // This is IE - it does not support contains() for top-level SVGs + while (node.parentNode) { + node = node.parentNode + } + return node === globals.document } - return node === globals.document - }).call(globals.document.documentElement, node) + ).call(globals.document.documentElement, node) + ) } export default class Box { - constructor (...args) { + constructor(...args) { this.init(...args) } - addOffset () { + addOffset() { // offset by window scroll position, because getBoundingClientRect changes when window is scrolled this.x += globals.window.pageXOffset this.y += globals.window.pageYOffset return new Box(this) } - init (source) { - const base = [ 0, 0, 0, 0 ] - source = typeof source === 'string' - ? source.split(delimiter).map(parseFloat) - : Array.isArray(source) + init(source) { + const base = [0, 0, 0, 0] + source = + typeof source === 'string' + ? source.split(delimiter).map(parseFloat) + : Array.isArray(source) ? source : typeof source === 'object' - ? [ source.left != null - ? source.left - : source.x, source.top != null ? source.top : source.y, source.width, source.height ] - : arguments.length === 4 - ? [].slice.call(arguments) - : base + ? [ + source.left != null ? source.left : source.x, + source.top != null ? source.top : source.y, + source.width, + source.height + ] + : arguments.length === 4 + ? [].slice.call(arguments) + : base this.x = source[0] || 0 this.y = source[1] || 0 @@ -61,12 +70,12 @@ export default class Box { return this } - isNulled () { + isNulled() { return isNulledBox(this) } // Merge rect box with another, return a new instance - merge (box) { + merge(box) { const x = Math.min(this.x, box.x) const y = Math.min(this.y, box.y) const width = Math.max(this.x + this.width, box.x + box.width) - x @@ -75,15 +84,15 @@ export default class Box { return new Box(x, y, width, height) } - toArray () { - return [ this.x, this.y, this.width, this.height ] + toArray() { + return [this.x, this.y, this.width, this.height] } - toString () { + toString() { return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height } - transform (m) { + transform(m) { if (!(m instanceof Matrix)) { m = new Matrix(m) } @@ -108,16 +117,11 @@ export default class Box { yMax = Math.max(yMax, p.y) }) - return new Box( - xMin, yMin, - xMax - xMin, - yMax - yMin - ) + return new Box(xMin, yMin, xMax - xMin, yMax - yMin) } - } -function getBox (el, getBBoxFn, retry) { +function getBox(el, getBBoxFn, retry) { let box try { @@ -137,7 +141,7 @@ function getBox (el, getBBoxFn, retry) { return box } -export function bbox () { +export function bbox() { // Function to get bbox is getBBox() const getBBox = (node) => node.getBBox() @@ -151,7 +155,11 @@ export function bbox () { return box } catch (e) { // We give up... - throw new Error(`Getting bbox of element "${el.node.nodeName}" is not possible: ${e.toString()}`) + throw new Error( + `Getting bbox of element "${ + el.node.nodeName + }" is not possible: ${e.toString()}` + ) } } @@ -161,12 +169,14 @@ export function bbox () { return bbox } -export function rbox (el) { +export function rbox(el) { const getRBox = (node) => node.getBoundingClientRect() const retry = (el) => { // There is no point in trying tricks here because if we insert the element into the dom ourselves // it obviously will be at the wrong position - throw new Error(`Getting rbox of element "${el.node.nodeName}" is not possible`) + throw new Error( + `Getting rbox of element "${el.node.nodeName}" is not possible` + ) } const box = getBox(this, getRBox, retry) @@ -183,18 +193,17 @@ export function rbox (el) { } // Checks whether the given point is inside the bounding box -export function inside (x, y) { +export function inside(x, y) { const box = this.bbox() - return x > box.x - && y > box.y - && x < box.x + box.width - && y < box.y + box.height + return ( + x > box.x && y > box.y && x < box.x + box.width && y < box.y + box.height + ) } registerMethods({ viewbox: { - viewbox (x, y, width, height) { + viewbox(x, y, width, height) { // act as getter if (x == null) return new Box(this.attr('viewBox')) @@ -202,7 +211,7 @@ registerMethods({ return this.attr('viewBox', new Box(x, y, width, height)) }, - zoom (level, point) { + zoom(level, point) { // Its best to rely on the attributes here and here is why: // clientXYZ: Doesn't work on non-root svgs because they dont have a CSSBox (silly!) // getBoundingClientRect: Doesn't work because Chrome just ignores width and height of nested svgs completely @@ -210,18 +219,24 @@ registerMethods({ // Furthermore this size is incorrect if the element is further transformed by its parents // computedStyle: Only returns meaningful values if css was used with px. We dont go this route here! // getBBox: returns the bounding box of its content - that doesn't help! - let { width, height } = this.attr([ 'width', 'height' ]) + let { width, height } = this.attr(['width', 'height']) // Width and height is a string when a number with a unit is present which we can't use // So we try clientXYZ - if ((!width && !height) || (typeof width === 'string' || typeof height === 'string')) { + if ( + (!width && !height) || + typeof width === 'string' || + typeof height === 'string' + ) { width = this.node.clientWidth height = this.node.clientHeight } // Giving up... if (!width || !height) { - throw new Error('Impossible to get absolute width and height. Please provide an absolute width and height attribute on the zooming element') + throw new Error( + 'Impossible to get absolute width and height. Please provide an absolute width and height attribute on the zooming element' + ) } const v = this.viewbox() @@ -240,7 +255,8 @@ registerMethods({ // The * 100 is a bit of wiggle room for the matrix transformation if (zoomAmount === Infinity) zoomAmount = Number.MAX_SAFE_INTEGER / 100 - point = point || new Point(width / 2 / zoomX + v.x, height / 2 / zoomY + v.y) + point = + point || new Point(width / 2 / zoomX + v.x, height / 2 / zoomY + v.y) const box = new Box(v).transform( new Matrix({ scale: zoomAmount, origin: point }) diff --git a/src/types/Color.js b/src/types/Color.js index c050ecc..79fa24e 100644 --- a/src/types/Color.js +++ b/src/types/Color.js @@ -1,25 +1,28 @@ - import { hex, isHex, isRgb, rgb, whitespace } from '../modules/core/regex.js' -function sixDigitHex (hex) { +function sixDigitHex(hex) { return hex.length === 4 - ? [ '#', - hex.substring(1, 2), hex.substring(1, 2), - hex.substring(2, 3), hex.substring(2, 3), - hex.substring(3, 4), hex.substring(3, 4) - ].join('') + ? [ + '#', + hex.substring(1, 2), + hex.substring(1, 2), + hex.substring(2, 3), + hex.substring(2, 3), + hex.substring(3, 4), + hex.substring(3, 4) + ].join('') : hex } -function componentHex (component) { +function componentHex(component) { const integer = Math.round(component) const bounded = Math.max(0, Math.min(255, integer)) const hex = bounded.toString(16) return hex.length === 1 ? '0' + hex : hex } -function is (object, space) { - for (let i = space.length; i--;) { +function is(object, space) { + for (let i = space.length; i--; ) { if (object[space[i]] == null) { return false } @@ -27,26 +30,26 @@ function is (object, space) { return true } -function getParameters (a, b) { +function getParameters(a, b) { const params = is(a, 'rgb') ? { _a: a.r, _b: a.g, _c: a.b, _d: 0, space: 'rgb' } : is(a, 'xyz') - ? { _a: a.x, _b: a.y, _c: a.z, _d: 0, space: 'xyz' } - : is(a, 'hsl') - ? { _a: a.h, _b: a.s, _c: a.l, _d: 0, space: 'hsl' } - : is(a, 'lab') - ? { _a: a.l, _b: a.a, _c: a.b, _d: 0, space: 'lab' } - : is(a, 'lch') - ? { _a: a.l, _b: a.c, _c: a.h, _d: 0, space: 'lch' } - : is(a, 'cmyk') - ? { _a: a.c, _b: a.m, _c: a.y, _d: a.k, space: 'cmyk' } - : { _a: 0, _b: 0, _c: 0, space: 'rgb' } + ? { _a: a.x, _b: a.y, _c: a.z, _d: 0, space: 'xyz' } + : is(a, 'hsl') + ? { _a: a.h, _b: a.s, _c: a.l, _d: 0, space: 'hsl' } + : is(a, 'lab') + ? { _a: a.l, _b: a.a, _c: a.b, _d: 0, space: 'lab' } + : is(a, 'lch') + ? { _a: a.l, _b: a.c, _c: a.h, _d: 0, space: 'lch' } + : is(a, 'cmyk') + ? { _a: a.c, _b: a.m, _c: a.y, _d: a.k, space: 'cmyk' } + : { _a: 0, _b: 0, _c: 0, space: 'rgb' } params.space = b || params.space return params } -function cieSpace (space) { +function cieSpace(space) { if (space === 'lab' || space === 'xyz' || space === 'lch') { return true } else { @@ -54,7 +57,7 @@ function cieSpace (space) { } } -function hueToRgb (p, q, t) { +function hueToRgb(p, q, t) { if (t < 0) t += 1 if (t > 1) t -= 1 if (t < 1 / 6) return p + (q - p) * 6 * t @@ -64,108 +67,90 @@ function hueToRgb (p, q, t) { } export default class Color { - constructor (...inputs) { + constructor(...inputs) { this.init(...inputs) } // Test if given value is a color - static isColor (color) { - return color && ( - color instanceof Color - || this.isRgb(color) - || this.test(color) + static isColor(color) { + return ( + color && (color instanceof Color || this.isRgb(color) || this.test(color)) ) } // Test if given value is an rgb object - static isRgb (color) { - return color && typeof color.r === 'number' - && typeof color.g === 'number' - && typeof color.b === 'number' + static isRgb(color) { + return ( + color && + typeof color.r === 'number' && + typeof color.g === 'number' && + typeof color.b === 'number' + ) } /* Generating random colors */ - static random (mode = 'vibrant', t, u) { - + static random(mode = 'vibrant', t) { // Get the math modules const { random, round, sin, PI: pi } = Math // Run the correct generator if (mode === 'vibrant') { - const l = (81 - 57) * random() + 57 const c = (83 - 45) * random() + 45 const h = 360 * random() const color = new Color(l, c, h, 'lch') return color - } else if (mode === 'sine') { - t = t == null ? random() : t - const r = round(80 * sin(2 * pi * t / 0.5 + 0.01) + 150) - const g = round(50 * sin(2 * pi * t / 0.5 + 4.6) + 200) - const b = round(100 * sin(2 * pi * t / 0.5 + 2.3) + 150) + const r = round(80 * sin((2 * pi * t) / 0.5 + 0.01) + 150) + const g = round(50 * sin((2 * pi * t) / 0.5 + 4.6) + 200) + const b = round(100 * sin((2 * pi * t) / 0.5 + 2.3) + 150) const color = new Color(r, g, b) return color - } else if (mode === 'pastel') { - const l = (94 - 86) * random() + 86 const c = (26 - 9) * random() + 9 const h = 360 * random() const color = new Color(l, c, h, 'lch') return color - } else if (mode === 'dark') { - const l = 10 + 10 * random() const c = (125 - 75) * random() + 86 const h = 360 * random() const color = new Color(l, c, h, 'lch') return color - } else if (mode === 'rgb') { - const r = 255 * random() const g = 255 * random() const b = 255 * random() const color = new Color(r, g, b) return color - } else if (mode === 'lab') { - const l = 100 * random() const a = 256 * random() - 128 const b = 256 * random() - 128 const color = new Color(l, a, b, 'lab') return color - } else if (mode === 'grey') { - const grey = 255 * random() const color = new Color(grey, grey, grey) return color - } else { - throw new Error('Unsupported random color mode') - } } // Test if given value is a color string - static test (color) { - return (typeof color === 'string') - && (isHex.test(color) || isRgb.test(color)) + static test(color) { + return typeof color === 'string' && (isHex.test(color) || isRgb.test(color)) } - cmyk () { - + cmyk() { // Get the rgb values for the current color const { _a, _b, _c } = this.rgb() - const [ r, g, b ] = [ _a, _b, _c ].map(v => v / 255) + const [r, g, b] = [_a, _b, _c].map((v) => v / 255) // Get the cmyk values in an unbounded format const k = Math.min(1 - r, 1 - g, 1 - b) @@ -184,11 +169,10 @@ export default class Color { return color } - hsl () { - + hsl() { // Get the rgb values const { _a, _b, _c } = this.rgb() - const [ r, g, b ] = [ _a, _b, _c ].map(v => v / 255) + const [r, g, b] = [_a, _b, _c].map((v) => v / 255) // Find the maximum and minimum values to get the lightness const max = Math.max(r, g, b) @@ -203,24 +187,24 @@ export default class Color { const s = isGrey ? 0 : l > 0.5 - ? delta / (2 - max - min) - : delta / (max + min) + ? delta / (2 - max - min) + : delta / (max + min) const h = isGrey ? 0 : max === r - ? ((g - b) / delta + (g < b ? 6 : 0)) / 6 - : max === g - ? ((b - r) / delta + 2) / 6 - : max === b - ? ((r - g) / delta + 4) / 6 - : 0 + ? ((g - b) / delta + (g < b ? 6 : 0)) / 6 + : max === g + ? ((b - r) / delta + 2) / 6 + : max === b + ? ((r - g) / delta + 4) / 6 + : 0 // Construct and return the new color const color = new Color(360 * h, 100 * s, 100 * l, 'hsl') return color } - init (a = 0, b = 0, c = 0, d = 0, space = 'rgb') { + init(a = 0, b = 0, c = 0, d = 0, space = 'rgb') { // This catches the case when a falsy value is passed like '' a = !a ? 0 : a @@ -238,7 +222,7 @@ export default class Color { // Assign the values straight to the color Object.assign(this, { _a: a, _b: b, _c: c, _d: d, space }) - // If the user gave us an array, make the color from it + // If the user gave us an array, make the color from it } else if (a instanceof Array) { this.space = b || (typeof a[3] === 'string' ? a[3] : a[4]) || 'rgb' Object.assign(this, { _a: a[0], _b: a[1], _c: a[2], _d: a[3] || 0 }) @@ -249,40 +233,43 @@ export default class Color { } else if (typeof a === 'string') { if (isRgb.test(a)) { const noWhitespace = a.replace(whitespace, '') - const [ _a, _b, _c ] = rgb.exec(noWhitespace) - .slice(1, 4).map(v => parseInt(v)) + const [_a, _b, _c] = rgb + .exec(noWhitespace) + .slice(1, 4) + .map((v) => parseInt(v)) Object.assign(this, { _a, _b, _c, _d: 0, space: 'rgb' }) } else if (isHex.test(a)) { - const hexParse = v => parseInt(v, 16) - const [ , _a, _b, _c ] = hex.exec(sixDigitHex(a)).map(hexParse) + const hexParse = (v) => parseInt(v, 16) + const [, _a, _b, _c] = hex.exec(sixDigitHex(a)).map(hexParse) Object.assign(this, { _a, _b, _c, _d: 0, space: 'rgb' }) - } else throw Error('Unsupported string format, can\'t construct Color') + } else throw Error("Unsupported string format, can't construct Color") } // Now add the components as a convenience const { _a, _b, _c, _d } = this - const components = this.space === 'rgb' - ? { r: _a, g: _b, b: _c } - : this.space === 'xyz' + const components = + this.space === 'rgb' + ? { r: _a, g: _b, b: _c } + : this.space === 'xyz' ? { x: _a, y: _b, z: _c } : this.space === 'hsl' - ? { h: _a, s: _b, l: _c } - : this.space === 'lab' - ? { l: _a, a: _b, b: _c } - : this.space === 'lch' - ? { l: _a, c: _b, h: _c } - : this.space === 'cmyk' - ? { c: _a, m: _b, y: _c, k: _d } - : {} + ? { h: _a, s: _b, l: _c } + : this.space === 'lab' + ? { l: _a, a: _b, b: _c } + : this.space === 'lch' + ? { l: _a, c: _b, h: _c } + : this.space === 'cmyk' + ? { c: _a, m: _b, y: _c, k: _d } + : {} Object.assign(this, components) } - lab () { + lab() { // Get the xyz color const { x, y, z } = this.xyz() // Get the lab components - const l = (116 * y) - 16 + const l = 116 * y - 16 const a = 500 * (x - y) const b = 200 * (y - z) @@ -291,14 +278,13 @@ export default class Color { return color } - lch () { - + lch() { // Get the lab color directly const { l, a, b } = this.lab() // Get the chromaticity and the hue using polar coordinates const c = Math.sqrt(a ** 2 + b ** 2) - let h = 180 * Math.atan2(b, a) / Math.PI + let h = (180 * Math.atan2(b, a)) / Math.PI if (h < 0) { h *= -1 h = 360 - h @@ -312,7 +298,7 @@ export default class Color { Conversion Methods */ - rgb () { + rgb() { if (this.space === 'rgb') { return this } else if (cieSpace(this.space)) { @@ -337,22 +323,22 @@ export default class Color { const ct = 16 / 116 const mx = 0.008856 const nm = 7.787 - x = 0.95047 * ((xL ** 3 > mx) ? xL ** 3 : (xL - ct) / nm) - y = 1.00000 * ((yL ** 3 > mx) ? yL ** 3 : (yL - ct) / nm) - z = 1.08883 * ((zL ** 3 > mx) ? zL ** 3 : (zL - ct) / nm) + x = 0.95047 * (xL ** 3 > mx ? xL ** 3 : (xL - ct) / nm) + y = 1.0 * (yL ** 3 > mx ? yL ** 3 : (yL - ct) / nm) + z = 1.08883 * (zL ** 3 > mx ? zL ** 3 : (zL - ct) / nm) } // Convert xyz to unbounded rgb values const rU = x * 3.2406 + y * -1.5372 + z * -0.4986 const gU = x * -0.9689 + y * 1.8758 + z * 0.0415 - const bU = x * 0.0557 + y * -0.2040 + z * 1.0570 + const bU = x * 0.0557 + y * -0.204 + z * 1.057 // Convert the values to true rgb values const pow = Math.pow const bd = 0.0031308 - const r = (rU > bd) ? (1.055 * pow(rU, 1 / 2.4) - 0.055) : 12.92 * rU - const g = (gU > bd) ? (1.055 * pow(gU, 1 / 2.4) - 0.055) : 12.92 * gU - const b = (bU > bd) ? (1.055 * pow(bU, 1 / 2.4) - 0.055) : 12.92 * bU + const r = rU > bd ? 1.055 * pow(rU, 1 / 2.4) - 0.055 : 12.92 * rU + const g = gU > bd ? 1.055 * pow(gU, 1 / 2.4) - 0.055 : 12.92 * gU + const b = bU > bd ? 1.055 * pow(bU, 1 / 2.4) - 0.055 : 12.92 * bU // Make and return the color const color = new Color(255 * r, 255 * g, 255 * b) @@ -402,46 +388,45 @@ export default class Color { } } - toArray () { + toArray() { const { _a, _b, _c, _d, space } = this - return [ _a, _b, _c, _d, space ] + return [_a, _b, _c, _d, space] } - toHex () { - const [ r, g, b ] = this._clamped().map(componentHex) + toHex() { + const [r, g, b] = this._clamped().map(componentHex) return `#${r}${g}${b}` } - toRgb () { - const [ rV, gV, bV ] = this._clamped() + toRgb() { + const [rV, gV, bV] = this._clamped() const string = `rgb(${rV},${gV},${bV})` return string } - toString () { + toString() { return this.toHex() } - xyz () { - + xyz() { // Normalise the red, green and blue values const { _a: r255, _b: g255, _c: b255 } = this.rgb() - const [ r, g, b ] = [ r255, g255, b255 ].map(v => v / 255) + const [r, g, b] = [r255, g255, b255].map((v) => v / 255) // Convert to the lab rgb space - const rL = (r > 0.04045) ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92 - const gL = (g > 0.04045) ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92 - const bL = (b > 0.04045) ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92 + const rL = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92 + const gL = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92 + const bL = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92 // Convert to the xyz color space without bounding the values const xU = (rL * 0.4124 + gL * 0.3576 + bL * 0.1805) / 0.95047 - const yU = (rL * 0.2126 + gL * 0.7152 + bL * 0.0722) / 1.00000 + const yU = (rL * 0.2126 + gL * 0.7152 + bL * 0.0722) / 1.0 const zU = (rL * 0.0193 + gL * 0.1192 + bL * 0.9505) / 1.08883 // Get the proper xyz values by applying the bounding - const x = (xU > 0.008856) ? Math.pow(xU, 1 / 3) : (7.787 * xU) + 16 / 116 - const y = (yU > 0.008856) ? Math.pow(yU, 1 / 3) : (7.787 * yU) + 16 / 116 - const z = (zU > 0.008856) ? Math.pow(zU, 1 / 3) : (7.787 * zU) + 16 / 116 + const x = xU > 0.008856 ? Math.pow(xU, 1 / 3) : 7.787 * xU + 16 / 116 + const y = yU > 0.008856 ? Math.pow(yU, 1 / 3) : 7.787 * yU + 16 / 116 + const z = zU > 0.008856 ? Math.pow(zU, 1 / 3) : 7.787 * zU + 16 / 116 // Make and return the color const color = new Color(x, y, z, 'xyz') @@ -452,15 +437,14 @@ export default class Color { Input and Output methods */ - _clamped () { + _clamped() { const { _a, _b, _c } = this.rgb() const { max, min, round } = Math - const format = v => max(0, min(round(v), 255)) - return [ _a, _b, _c ].map(format) + const format = (v) => max(0, min(round(v), 255)) + return [_a, _b, _c].map(format) } /* Constructing colors */ - } diff --git a/src/types/EventTarget.js b/src/types/EventTarget.js index 58f5d5c..de13a5f 100644 --- a/src/types/EventTarget.js +++ b/src/types/EventTarget.js @@ -3,13 +3,13 @@ import { register } from '../utils/adopter.js' import Base from './Base.js' export default class EventTarget extends Base { - addEventListener () {} + addEventListener() {} - dispatch (event, data, options) { + dispatch(event, data, options) { return dispatch(this, event, data, options) } - dispatchEvent (event) { + dispatchEvent(event) { const bag = this.getEventHolder().events if (!bag) return true @@ -25,32 +25,32 @@ export default class EventTarget extends Base { } // Fire given event - fire (event, data, options) { + fire(event, data, options) { this.dispatch(event, data, options) return this } - getEventHolder () { + getEventHolder() { return this } - getEventTarget () { + getEventTarget() { return this } // Unbind event from listener - off (event, listener, options) { + off(event, listener, options) { off(this, event, listener, options) return this } // Bind given event to listener - on (event, listener, binding, options) { + on(event, listener, binding, options) { on(this, event, listener, binding, options) return this } - removeEventListener () {} + removeEventListener() {} } register(EventTarget, 'EventTarget') diff --git a/src/types/List.js b/src/types/List.js index 197a155..bdeb766 100644 --- a/src/types/List.js +++ b/src/types/List.js @@ -2,7 +2,7 @@ import { extend } from '../utils/adopter.js' // import { subClassArray } from './ArrayPolyfill.js' class List extends Array { - constructor (arr = [], ...args) { + constructor(arr = [], ...args) { super(arr, ...args) if (typeof arr === 'number') return this this.length = 0 @@ -19,25 +19,25 @@ class List extends Array { export default List -extend([ List ], { - each (fnOrMethodName, ...args) { +extend([List], { + each(fnOrMethodName, ...args) { if (typeof fnOrMethodName === 'function') { return this.map((el, i, arr) => { return fnOrMethodName.call(el, el, i, arr) }) } else { - return this.map(el => { + return this.map((el) => { return el[fnOrMethodName](...args) }) } }, - toArray () { + toArray() { return Array.prototype.concat.apply([], this) } }) -const reserved = [ 'toArray', 'constructor', 'each' ] +const reserved = ['toArray', 'constructor', 'each'] List.extend = function (methods) { methods = methods.reduce((obj, name) => { @@ -54,5 +54,5 @@ List.extend = function (methods) { return obj }, {}) - extend([ List ], methods) + extend([List], methods) } diff --git a/src/types/Matrix.js b/src/types/Matrix.js index c329df4..760f002 100644 --- a/src/types/Matrix.js +++ b/src/types/Matrix.js @@ -4,87 +4,116 @@ import { register } from '../utils/adopter.js' import Element from '../elements/Element.js' import Point from './Point.js' -function closeEnough (a, b, threshold) { +function closeEnough(a, b, threshold) { return Math.abs(b - a) < (threshold || 1e-6) } export default class Matrix { - constructor (...args) { + constructor(...args) { this.init(...args) } - static formatTransforms (o) { + static formatTransforms(o) { // Get all of the parameters required to form the matrix const flipBoth = o.flip === 'both' || o.flip === true const flipX = o.flip && (flipBoth || o.flip === 'x') ? -1 : 1 const flipY = o.flip && (flipBoth || o.flip === 'y') ? -1 : 1 - const skewX = o.skew && o.skew.length - ? o.skew[0] - : isFinite(o.skew) + const skewX = + o.skew && o.skew.length + ? o.skew[0] + : isFinite(o.skew) ? o.skew : isFinite(o.skewX) - ? o.skewX - : 0 - const skewY = o.skew && o.skew.length - ? o.skew[1] - : isFinite(o.skew) + ? o.skewX + : 0 + const skewY = + o.skew && o.skew.length + ? o.skew[1] + : isFinite(o.skew) ? o.skew : isFinite(o.skewY) - ? o.skewY - : 0 - const scaleX = o.scale && o.scale.length - ? o.scale[0] * flipX - : isFinite(o.scale) + ? o.skewY + : 0 + const scaleX = + o.scale && o.scale.length + ? o.scale[0] * flipX + : isFinite(o.scale) ? o.scale * flipX : isFinite(o.scaleX) - ? o.scaleX * flipX - : flipX - const scaleY = o.scale && o.scale.length - ? o.scale[1] * flipY - : isFinite(o.scale) + ? o.scaleX * flipX + : flipX + const scaleY = + o.scale && o.scale.length + ? o.scale[1] * flipY + : isFinite(o.scale) ? o.scale * flipY : isFinite(o.scaleY) - ? o.scaleY * flipY - : flipY + ? o.scaleY * flipY + : flipY const shear = o.shear || 0 const theta = o.rotate || o.theta || 0 - const origin = new Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY) + const origin = new Point( + o.origin || o.around || o.ox || o.originX, + o.oy || o.originY + ) const ox = origin.x const oy = origin.y // We need Point to be invalid if nothing was passed because we cannot default to 0 here. That is why NaN - const position = new Point(o.position || o.px || o.positionX || NaN, o.py || o.positionY || NaN) + const position = new Point( + o.position || o.px || o.positionX || NaN, + o.py || o.positionY || NaN + ) const px = position.x const py = position.y - const translate = new Point(o.translate || o.tx || o.translateX, o.ty || o.translateY) + const translate = new Point( + o.translate || o.tx || o.translateX, + o.ty || o.translateY + ) const tx = translate.x const ty = translate.y - const relative = new Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY) + const relative = new Point( + o.relative || o.rx || o.relativeX, + o.ry || o.relativeY + ) const rx = relative.x const ry = relative.y // Populate all of the values return { - scaleX, scaleY, skewX, skewY, shear, theta, rx, ry, tx, ty, ox, oy, px, py + scaleX, + scaleY, + skewX, + skewY, + shear, + theta, + rx, + ry, + tx, + ty, + ox, + oy, + px, + py } } - static fromArray (a) { + static fromArray(a) { return { a: a[0], b: a[1], c: a[2], d: a[3], e: a[4], f: a[5] } } - static isMatrixLike (o) { + static isMatrixLike(o) { return ( - o.a != null - || o.b != null - || o.c != null - || o.d != null - || o.e != null - || o.f != null + o.a != null || + o.b != null || + o.c != null || + o.d != null || + o.e != null || + o.f != null ) } // left matrix, right matrix, target matrix which is overwritten - static matrixMultiply (l, r, o) { + static matrixMultiply(l, r, o) { // Work out the product directly const a = l.a * r.a + l.c * r.b const b = l.b * r.a + l.d * r.b @@ -104,24 +133,24 @@ export default class Matrix { return o } - around (cx, cy, matrix) { + around(cx, cy, matrix) { return this.clone().aroundO(cx, cy, matrix) } // Transform around a center point - aroundO (cx, cy, matrix) { + aroundO(cx, cy, matrix) { const dx = cx || 0 const dy = cy || 0 return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy) } // Clones this matrix - clone () { + clone() { return new Matrix(this) } // Decomposes this matrix into its affine parameters - decompose (cx = 0, cy = 0) { + decompose(cx = 0, cy = 0) { // Get the parameters from the matrix const a = this.a const b = this.b @@ -138,14 +167,14 @@ export default class Matrix { // and the rotation of the resulting matrix const sx = ccw * Math.sqrt(a * a + b * b) const thetaRad = Math.atan2(ccw * b, ccw * a) - const theta = 180 / Math.PI * thetaRad + const theta = (180 / Math.PI) * thetaRad const ct = Math.cos(thetaRad) const st = Math.sin(thetaRad) // We can then solve the y basis vector simultaneously to get the other // two affine parameters directly from these parameters const lam = (a * c + b * d) / determinant - const sy = ((c * sx) / (lam * a - b)) || ((d * sx) / (lam * b + a)) + const sy = (c * sx) / (lam * a - b) || (d * sx) / (lam * b + a) // Use the translations const tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy) @@ -174,45 +203,51 @@ export default class Matrix { } // Check if two matrices are equal - equals (other) { + equals(other) { if (other === this) return true const comp = new Matrix(other) - return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b) - && closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d) - && closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f) + return ( + closeEnough(this.a, comp.a) && + closeEnough(this.b, comp.b) && + closeEnough(this.c, comp.c) && + closeEnough(this.d, comp.d) && + closeEnough(this.e, comp.e) && + closeEnough(this.f, comp.f) + ) } // Flip matrix on x or y, at a given offset - flip (axis, around) { + flip(axis, around) { return this.clone().flipO(axis, around) } - flipO (axis, around) { + flipO(axis, around) { return axis === 'x' ? this.scaleO(-1, 1, around, 0) : axis === 'y' - ? this.scaleO(1, -1, 0, around) - : this.scaleO(-1, -1, axis, around || axis) // Define an x, y flip point + ? this.scaleO(1, -1, 0, around) + : this.scaleO(-1, -1, axis, around || axis) // Define an x, y flip point } // Initialize - init (source) { - const base = Matrix.fromArray([ 1, 0, 0, 1, 0, 0 ]) + init(source) { + const base = Matrix.fromArray([1, 0, 0, 1, 0, 0]) // ensure source as object - source = source instanceof Element - ? source.matrixify() - : typeof source === 'string' + source = + source instanceof Element + ? source.matrixify() + : typeof source === 'string' ? Matrix.fromArray(source.split(delimiter).map(parseFloat)) : Array.isArray(source) - ? Matrix.fromArray(source) - : (typeof source === 'object' && Matrix.isMatrixLike(source)) - ? source - : (typeof source === 'object') - ? new Matrix().transform(source) - : arguments.length === 6 - ? Matrix.fromArray([].slice.call(arguments)) - : base + ? Matrix.fromArray(source) + : typeof source === 'object' && Matrix.isMatrixLike(source) + ? source + : typeof source === 'object' + ? new Matrix().transform(source) + : arguments.length === 6 + ? Matrix.fromArray([].slice.call(arguments)) + : base // Merge the source matrix with the base matrix this.a = source.a != null ? source.a : base.a @@ -225,12 +260,12 @@ export default class Matrix { return this } - inverse () { + inverse() { return this.clone().inverseO() } // Inverses matrix - inverseO () { + inverseO() { // Get the current parameters out of the matrix const a = this.a const b = this.b @@ -264,40 +299,36 @@ export default class Matrix { return this } - lmultiply (matrix) { + lmultiply(matrix) { return this.clone().lmultiplyO(matrix) } - lmultiplyO (matrix) { + lmultiplyO(matrix) { const r = this - const l = matrix instanceof Matrix - ? matrix - : new Matrix(matrix) + const l = matrix instanceof Matrix ? matrix : new Matrix(matrix) return Matrix.matrixMultiply(l, r, this) } // Left multiplies by the given matrix - multiply (matrix) { + multiply(matrix) { return this.clone().multiplyO(matrix) } - multiplyO (matrix) { + multiplyO(matrix) { // Get the matrices const l = this - const r = matrix instanceof Matrix - ? matrix - : new Matrix(matrix) + const r = matrix instanceof Matrix ? matrix : new Matrix(matrix) return Matrix.matrixMultiply(l, r, this) } // Rotate matrix - rotate (r, cx, cy) { + rotate(r, cx, cy) { return this.clone().rotateO(r, cx, cy) } - rotateO (r, cx = 0, cy = 0) { + rotateO(r, cx = 0, cy = 0) { // Convert degrees to radians r = radians(r) @@ -317,11 +348,11 @@ export default class Matrix { } // Scale matrix - scale (x, y, cx, cy) { + scale() { return this.clone().scaleO(...arguments) } - scaleO (x, y = x, cx = 0, cy = 0) { + scaleO(x, y = x, cx = 0, cy = 0) { // Support uniform scaling if (arguments.length === 3) { cy = cx @@ -342,11 +373,12 @@ export default class Matrix { } // Shear matrix - shear (a, cx, cy) { + shear(a, cx, cy) { return this.clone().shearO(a, cx, cy) } - shearO (lx, cx = 0, cy = 0) { + // eslint-disable-next-line no-unused-vars + shearO(lx, cx = 0, cy = 0) { const { a, b, c, d, e, f } = this this.a = a + b * lx @@ -357,11 +389,11 @@ export default class Matrix { } // Skew Matrix - skew (x, y, cx, cy) { + skew() { return this.clone().skewO(...arguments) } - skewO (x, y = x, cx = 0, cy = 0) { + skewO(x, y = x, cx = 0, cy = 0) { // support uniformal skew if (arguments.length === 3) { cy = cx @@ -389,26 +421,40 @@ export default class Matrix { } // SkewX - skewX (x, cx, cy) { + skewX(x, cx, cy) { return this.skew(x, 0, cx, cy) } // SkewY - skewY (y, cx, cy) { + skewY(y, cx, cy) { return this.skew(0, y, cx, cy) } - toArray () { - return [ this.a, this.b, this.c, this.d, this.e, this.f ] + toArray() { + return [this.a, this.b, this.c, this.d, this.e, this.f] } // Convert matrix to string - toString () { - return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')' + toString() { + return ( + 'matrix(' + + this.a + + ',' + + this.b + + ',' + + this.c + + ',' + + this.d + + ',' + + this.e + + ',' + + this.f + + ')' + ) } // Transform a matrix into another matrix by manipulating the space - transform (o) { + transform(o) { // Check if o is a matrix and then left multiply it directly if (Matrix.isMatrixLike(o)) { const matrix = new Matrix(o) @@ -447,17 +493,17 @@ export default class Matrix { } // Translate matrix - translate (x, y) { + translate(x, y) { return this.clone().translateO(x, y) } - translateO (x, y) { + translateO(x, y) { this.e += x || 0 this.f += y || 0 return this } - valueOf () { + valueOf() { return { a: this.a, b: this.b, @@ -467,14 +513,13 @@ export default class Matrix { f: this.f } } - } -export function ctm () { +export function ctm() { return new Matrix(this.node.getCTM()) } -export function screenCTM () { +export function screenCTM() { /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537 This is needed because FF does not return the transformation matrix for the inner coordinate system when getScreenCTM() is called on nested svgs. diff --git a/src/types/PathArray.js b/src/types/PathArray.js index 8a37ac4..9e59ed7 100644 --- a/src/types/PathArray.js +++ b/src/types/PathArray.js @@ -3,7 +3,7 @@ import parser from '../modules/core/parser.js' import Box from './Box.js' import { pathParser } from '../utils/pathParser.js' -function arrayToString (a) { +function arrayToString(a) { let s = '' for (let i = 0, il = a.length; i < il; i++) { s += a[i][0] @@ -42,13 +42,13 @@ function arrayToString (a) { export default class PathArray extends SVGArray { // Get bounding box of path - bbox () { + bbox() { parser().path.setAttribute('d', this.toString()) return new Box(parser.nodes.path.getBBox()) } // Move path string - move (x, y) { + move(x, y) { // get bounding box of current situation const box = this.bbox() @@ -89,7 +89,7 @@ export default class PathArray extends SVGArray { } // Absolutize and parse path to array - parse (d = 'M0 0') { + parse(d = 'M0 0') { if (Array.isArray(d)) { d = Array.prototype.concat.apply([], d).toString() } @@ -98,7 +98,7 @@ export default class PathArray extends SVGArray { } // Resize path string - size (width, height) { + size(width, height) { // get bounding box of current situation const box = this.bbox() let i, l @@ -144,8 +144,7 @@ export default class PathArray extends SVGArray { } // Convert array to string - toString () { + toString() { return arrayToString(this) } - } diff --git a/src/types/Point.js b/src/types/Point.js index 76fd985..5d44733 100644 --- a/src/types/Point.js +++ b/src/types/Point.js @@ -2,24 +2,24 @@ import Matrix from './Matrix.js' export default class Point { // Initialize - constructor (...args) { + constructor(...args) { this.init(...args) } // Clone point - clone () { + clone() { return new Point(this) } - init (x, y) { + init(x, y) { const base = { x: 0, y: 0 } // ensure source as object const source = Array.isArray(x) ? { x: x[0], y: x[1] } : typeof x === 'object' - ? { x: x.x, y: x.y } - : { x: x, y: y } + ? { x: x.x, y: x.y } + : { x: x, y: y } // merge source this.x = source.x == null ? base.x : source.x @@ -28,16 +28,16 @@ export default class Point { return this } - toArray () { - return [ this.x, this.y ] + toArray() { + return [this.x, this.y] } - transform (m) { + transform(m) { return this.clone().transformO(m) } // Transform point with matrix - transformO (m) { + transformO(m) { if (!Matrix.isMatrixLike(m)) { m = new Matrix(m) } @@ -50,9 +50,8 @@ export default class Point { return this } - } -export function point (x, y) { +export function point(x, y) { return new Point(x, y).transformO(this.screenCTM().inverseO()) } diff --git a/src/types/PointArray.js b/src/types/PointArray.js index 69d0cd6..f72c2bc 100644 --- a/src/types/PointArray.js +++ b/src/types/PointArray.js @@ -5,7 +5,7 @@ import Matrix from './Matrix.js' export default class PointArray extends SVGArray { // Get bounding box of points - bbox () { + bbox() { let maxX = -Infinity let maxY = -Infinity let minX = Infinity @@ -20,7 +20,7 @@ export default class PointArray extends SVGArray { } // Move point string - move (x, y) { + move(x, y) { const box = this.bbox() // get relative offset @@ -30,7 +30,7 @@ export default class PointArray extends SVGArray { // move every point if (!isNaN(x) && !isNaN(y)) { for (let i = this.length - 1; i >= 0; i--) { - this[i] = [ this[i][0] + x, this[i][1] + y ] + this[i] = [this[i][0] + x, this[i][1] + y] } } @@ -38,13 +38,14 @@ export default class PointArray extends SVGArray { } // Parse point string and flat array - parse (array = [ 0, 0 ]) { + parse(array = [0, 0]) { const points = [] // if it is an array, we flatten it and therefore clone it to 1 depths if (array instanceof Array) { array = Array.prototype.concat.apply([], array) - } else { // Else, it is considered as a string + } else { + // Else, it is considered as a string // parse points array = array.trim().split(delimiter).map(parseFloat) } @@ -55,28 +56,30 @@ export default class PointArray extends SVGArray { // wrap points in two-tuples for (let i = 0, len = array.length; i < len; i = i + 2) { - points.push([ array[i], array[i + 1] ]) + points.push([array[i], array[i + 1]]) } return points } // Resize poly string - size (width, height) { + size(width, height) { let i const box = this.bbox() // recalculate position of all points according to new size for (i = this.length - 1; i >= 0; i--) { - if (box.width) this[i][0] = ((this[i][0] - box.x) * width) / box.width + box.x - if (box.height) this[i][1] = ((this[i][1] - box.y) * height) / box.height + box.y + if (box.width) + this[i][0] = ((this[i][0] - box.x) * width) / box.width + box.x + if (box.height) + this[i][1] = ((this[i][1] - box.y) * height) / box.height + box.y } return this } // Convert array to line object - toLine () { + toLine() { return { x1: this[0][0], y1: this[0][1], @@ -86,7 +89,7 @@ export default class PointArray extends SVGArray { } // Convert array to string - toString () { + toString() { const array = [] // convert to a poly point string for (let i = 0, il = this.length; i < il; i++) { @@ -96,24 +99,23 @@ export default class PointArray extends SVGArray { return array.join(' ') } - transform (m) { + transform(m) { return this.clone().transformO(m) } // transform points with matrix (similar to Point.transform) - transformO (m) { + transformO(m) { if (!Matrix.isMatrixLike(m)) { m = new Matrix(m) } - for (let i = this.length; i--;) { + for (let i = this.length; i--; ) { // Perform the matrix multiplication - const [ x, y ] = this[i] + const [x, y] = this[i] this[i][0] = m.a * x + m.c * y + m.e this[i][1] = m.b * x + m.d * y + m.f } return this } - } diff --git a/src/types/SVGArray.js b/src/types/SVGArray.js index 6ce024a..5826406 100644 --- a/src/types/SVGArray.js +++ b/src/types/SVGArray.js @@ -1,16 +1,16 @@ import { delimiter } from '../modules/core/regex.js' export default class SVGArray extends Array { - constructor (...args) { + constructor(...args) { super(...args) this.init(...args) } - clone () { + clone() { return new this.constructor(this) } - init (arr) { + init(arr) { // This catches the case, that native map tries to create an array with new Array(1) if (typeof arr === 'number') return this this.length = 0 @@ -19,30 +19,29 @@ export default class SVGArray extends Array { } // Parse whitespace separated string - parse (array = []) { + parse(array = []) { // If already is an array, no need to parse it if (array instanceof Array) return array return array.trim().split(delimiter).map(parseFloat) } - toArray () { + toArray() { return Array.prototype.concat.apply([], this) } - toSet () { + toSet() { return new Set(this) } - toString () { + toString() { return this.join(' ') } // Flattens the array if needed - valueOf () { + valueOf() { const ret = [] ret.push(...this) return ret } - } diff --git a/src/types/SVGNumber.js b/src/types/SVGNumber.js index 25c87c1..5945341 100644 --- a/src/types/SVGNumber.js +++ b/src/types/SVGNumber.js @@ -3,21 +3,21 @@ import { numberAndUnit } from '../modules/core/regex.js' // Module for unit conversions export default class SVGNumber { // Initialize - constructor (...args) { + constructor(...args) { this.init(...args) } - convert (unit) { + convert(unit) { return new SVGNumber(this.value, unit) } // Divide number - divide (number) { + divide(number) { number = new SVGNumber(number) return new SVGNumber(this / number, this.unit || number.unit) } - init (value, unit) { + init(value, unit) { unit = Array.isArray(value) ? value[1] : unit value = Array.isArray(value) ? value[0] : value @@ -28,7 +28,13 @@ export default class SVGNumber { // parse value if (typeof value === 'number') { // ensure a valid numeric value - this.value = isNaN(value) ? 0 : !isFinite(value) ? (value < 0 ? -3.4e+38 : +3.4e+38) : value + this.value = isNaN(value) + ? 0 + : !isFinite(value) + ? value < 0 + ? -3.4e38 + : +3.4e38 + : value } else if (typeof value === 'string') { unit = value.match(numberAndUnit) @@ -57,42 +63,42 @@ export default class SVGNumber { } // Subtract number - minus (number) { + minus(number) { number = new SVGNumber(number) return new SVGNumber(this - number, this.unit || number.unit) } // Add number - plus (number) { + plus(number) { number = new SVGNumber(number) return new SVGNumber(this + number, this.unit || number.unit) } // Multiply number - times (number) { + times(number) { number = new SVGNumber(number) return new SVGNumber(this * number, this.unit || number.unit) } - toArray () { - return [ this.value, this.unit ] + toArray() { + return [this.value, this.unit] } - toJSON () { + toJSON() { return this.toString() } - toString () { - return (this.unit === '%' - ? ~~(this.value * 1e8) / 1e6 - : this.unit === 's' + toString() { + return ( + (this.unit === '%' + ? ~~(this.value * 1e8) / 1e6 + : this.unit === 's' ? this.value / 1e3 - : this.value - ) + this.unit + : this.value) + this.unit + ) } - valueOf () { + valueOf() { return this.value } - } |