summaryrefslogtreecommitdiffstats
path: root/src/types
diff options
context:
space:
mode:
authorUlrich-Matthias Schäfer <ulima.ums@googlemail.com>2018-12-01 15:29:12 +0100
committerUlrich-Matthias Schäfer <ulima.ums@googlemail.com>2018-12-01 15:29:12 +0100
commita463c31c9453e9e12242886297362ca7e5f7875d (patch)
tree2c55c88512e1b142ec4a60c9fb568656feb8c25e /src/types
parentd549b00dc9d593e121236c64ab7c8f986a0800ac (diff)
parentb5fc96a3637756e1c432464c18907f010311766e (diff)
downloadsvg.js-a463c31c9453e9e12242886297362ca7e5f7875d.tar.gz
svg.js-a463c31c9453e9e12242886297362ca7e5f7875d.zip
Merge branch '790-color-spaces' into 791-random-colors
Diffstat (limited to 'src/types')
-rw-r--r--src/types/Box.js26
-rw-r--r--src/types/Color.js75
-rw-r--r--src/types/Morphable.js246
3 files changed, 56 insertions, 291 deletions
diff --git a/src/types/Box.js b/src/types/Box.js
index c90c7e0..d2ddcdd 100644
--- a/src/types/Box.js
+++ b/src/types/Box.js
@@ -104,7 +104,7 @@ export default class Box {
}
}
-function getBox (cb) {
+function getBox (cb, retry) {
let box
try {
@@ -114,23 +114,29 @@ function getBox (cb) {
throw new Error('Element not in the dom')
}
} catch (e) {
- try {
- let clone = this.clone().addTo(parser().svg).show()
- box = cb(clone.node)
- clone.remove()
- } catch (e) {
- throw new Error('Getting a bounding box of element "' + this.node.nodeName + '" is not possible')
- }
+ box = retry(this)
}
+
return box
}
export function bbox () {
- return new Box(getBox.call(this, (node) => node.getBBox()))
+ return new Box(getBox.call(this, (node) => node.getBBox(), (el) => {
+ try {
+ let clone = el.clone().addTo(parser().svg).show()
+ let box = clone.node.getBBox()
+ clone.remove()
+ return box
+ } catch (e) {
+ throw new Error('Getting bbox of element "' + el.node.nodeName + '" is not possible')
+ }
+ }))
}
export function rbox (el) {
- let box = new Box(getBox.call(this, (node) => node.getBoundingClientRect()))
+ let box = new Box(getBox.call(this, (node) => node.getBoundingClientRect(), (el) => {
+ throw new Error('Getting rbox of element "' + el.node.nodeName + '" is not possible')
+ }))
if (el) return box.transform(el.screenCTM().inverse())
return box.addOffset()
}
diff --git a/src/types/Color.js b/src/types/Color.js
index 1f23592..a1329aa 100644
--- a/src/types/Color.js
+++ b/src/types/Color.js
@@ -19,22 +19,24 @@ function componentHex (component) {
}
function is (object, space) {
- for (const key of space) {
- if (object[key] == null) {
+ for (let i = space.length; i--;) {
+ if (object[space[i]] == null) {
return false
}
}
return true
}
-function getParameters (a) {
+function getParameters (a, b) {
const params = is(a, 'rgb') ? { _a: a.r, _b: a.g, _c: a.b, space: 'rgb' }
- : is(a, 'xyz') ? { _a: a.x, _b: a.y, _c: a.z, space: 'xyz' }
- : is(a, 'hsl') ? { _a: a.h, _b: a.s, _c: a.l, space: 'hsl' }
- : is(a, 'lab') ? { _a: a.l, _b: a.a, _c: a.b, space: 'lab' }
- : is(a, 'lch') ? { _a: a.l, _b: a.c, _c: a.h, space: 'lch' }
+ : 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' }
+
+ params.space = b || params.space
return params
}
@@ -61,31 +63,38 @@ export default class Color {
}
init (a = 0, b = 0, c = 0, d = 0, space = 'rgb') {
- // If the user gave us an array, make the color from it
+ // Reset all values in case the init function is rerun with new color space
+ if (this.space) {
+ for (let component in this.space) {
+ delete this[this.space[component]]
+ }
+ }
+
if (typeof a === 'number') {
// Allow for the case that we don't need d...
space = typeof d === 'string' ? d : space
- d = typeof d === 'string' ? undefined : d
+ d = typeof d === 'string' ? 0 : d
// 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
} else if (a instanceof Array) {
- this.space = b || 'rgb'
- Object.assign(this, { _a: a[0], _b: a[1], _c: a[2], _d: a[3] })
+ 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 })
} else if (a instanceof Object) {
// Set the object up and assign its values directly
- const values = getParameters(a)
+ const values = getParameters(a, b)
Object.assign(this, values)
} 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))
- Object.assign(this, { _a, _b, _c, space: 'rgb' })
+ 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)
- Object.assign(this, { _a, _b, _c, space: 'rgb' })
+ Object.assign(this, { _a, _b, _c, _d: 0, space: 'rgb' })
} else throw Error(`Unsupported string format, can't construct Color`)
}
@@ -101,20 +110,6 @@ export default class Color {
Object.assign(this, components)
}
- opacity (opacity = 1) {
- this.opacity = opacity
- }
-
- /*
-
- */
-
- brightness () {
- const { _a: r, _b: g, _c: b } = this.rgb()
- const value = (r / 255 * 0.30) + (g / 255 * 0.59) + (b / 255 * 0.11)
- return value
- }
-
/*
Conversion Methods
*/
@@ -174,6 +169,7 @@ export default class Color {
// If we are grey, then just make the color directly
if (s === 0) {
+ l *= 255
let color = new Color(l, l, l)
return color
}
@@ -304,6 +300,12 @@ export default class Color {
// Get the cmyk values in an unbounded format
const k = Math.min(1 - r, 1 - g, 1 - b)
+
+ if (k === 1) {
+ // Catch the black case
+ return new Color(0, 0, 0, 1, 'cmyk')
+ }
+
const c = (1 - r - k) / (1 - k)
const m = (1 - g - k) / (1 - k)
const y = (1 - b - k) / (1 - k)
@@ -317,21 +319,24 @@ export default class Color {
Input and Output methods
*/
- hex () {
+ _clamped () {
let { _a, _b, _c } = this.rgb()
- let [ r, g, b ] = [ _a, _b, _c ].map(componentHex)
+ let { max, min, round } = Math
+ let format = v => max(0, min(round(v), 255))
+ return [ _a, _b, _c ].map(format)
+ }
+
+ toHex () {
+ let [ r, g, b ] = this._clamped().map(componentHex)
return `#${r}${g}${b}`
}
toString () {
- return this.hex()
+ return this.toHex()
}
toRgb () {
- let { r, g, b } = this.rgb()
- let { max, min, round } = Math
- let format = v => max(0, min(round(v), 255))
- let [ rV, gV, bV ] = [ r, g, b ].map(format)
+ let [ rV, gV, bV ] = this._clamped()
let string = `rgb(${rV},${gV},${bV})`
return string
}
diff --git a/src/types/Morphable.js b/src/types/Morphable.js
deleted file mode 100644
index 240215b..0000000
--- a/src/types/Morphable.js
+++ /dev/null
@@ -1,246 +0,0 @@
-import { Ease } from '../animation/Controller.js'
-import {
- delimiter,
- numberAndUnit,
- pathLetters
-} from '../modules/core/regex.js'
-import { extend } from '../utils/adopter.js'
-import Color from './Color.js'
-import PathArray from './PathArray.js'
-import SVGArray from './SVGArray.js'
-import SVGNumber from './SVGNumber.js'
-
-export default class Morphable {
- constructor (stepper) {
- this._stepper = stepper || new Ease('-')
-
- this._from = null
- this._to = null
- this._type = null
- this._context = null
- this._morphObj = null
- }
-
- from (val) {
- if (val == null) {
- return this._from
- }
-
- this._from = this._set(val)
- return this
- }
-
- to (val) {
- if (val == null) {
- return this._to
- }
-
- this._to = this._set(val)
- return this
- }
-
- type (type) {
- // getter
- if (type == null) {
- return this._type
- }
-
- // setter
- this._type = type
- return this
- }
-
- _set (value) {
- if (!this._type) {
- var type = typeof value
-
- if (type === 'number') {
- this.type(SVGNumber)
- } else if (type === 'string') {
- if (Color.isColor(value)) {
- this.type(Color)
- } else if (delimiter.test(value)) {
- this.type(pathLetters.test(value)
- ? PathArray
- : SVGArray
- )
- } else if (numberAndUnit.test(value)) {
- this.type(SVGNumber)
- } else {
- this.type(NonMorphable)
- }
- } else if (morphableTypes.indexOf(value.constructor) > -1) {
- this.type(value.constructor)
- } else if (Array.isArray(value)) {
- this.type(SVGArray)
- } else if (type === 'object') {
- this.type(ObjectBag)
- } else {
- this.type(NonMorphable)
- }
- }
-
- var result = (new this._type(value)).toArray()
- this._morphObj = this._morphObj || new this._type()
- this._context = this._context
- || Array.apply(null, Array(result.length)).map(Object)
- return result
- }
-
- stepper (stepper) {
- if (stepper == null) return this._stepper
- this._stepper = stepper
- return this
- }
-
- done () {
- var complete = this._context
- .map(this._stepper.done)
- .reduce(function (last, curr) {
- return last && curr
- }, true)
- return complete
- }
-
- at (pos) {
- var _this = this
-
- return this._morphObj.fromArray(
- this._from.map(function (i, index) {
- return _this._stepper.step(i, _this._to[index], pos, _this._context[index], _this._context)
- })
- )
- }
-}
-
-export class NonMorphable {
- constructor (...args) {
- this.init(...args)
- }
-
- init (val) {
- val = Array.isArray(val) ? val[0] : val
- this.value = val
- return this
- }
-
- valueOf () {
- return this.value
- }
-
- toArray () {
- return [ this.value ]
- }
-}
-
-export class TransformBag {
- constructor (...args) {
- this.init(...args)
- }
-
- init (obj) {
- if (Array.isArray(obj)) {
- obj = {
- scaleX: obj[0],
- scaleY: obj[1],
- shear: obj[2],
- rotate: obj[3],
- translateX: obj[4],
- translateY: obj[5],
- originX: obj[6],
- originY: obj[7]
- }
- }
-
- Object.assign(this, TransformBag.defaults, obj)
- return this
- }
-
- toArray () {
- var v = this
-
- return [
- v.scaleX,
- v.scaleY,
- v.shear,
- v.rotate,
- v.translateX,
- v.translateY,
- v.originX,
- v.originY
- ]
- }
-}
-
-TransformBag.defaults = {
- scaleX: 1,
- scaleY: 1,
- shear: 0,
- rotate: 0,
- translateX: 0,
- translateY: 0,
- originX: 0,
- originY: 0
-}
-
-export class ObjectBag {
- constructor (...args) {
- this.init(...args)
- }
-
- init (objOrArr) {
- this.values = []
-
- if (Array.isArray(objOrArr)) {
- this.values = objOrArr
- return
- }
-
- var entries = Object.entries(objOrArr || {}).sort((a, b) => {
- return a[0] - b[0]
- })
-
- this.values = entries.reduce((last, curr) => last.concat(curr), [])
- return this
- }
-
- valueOf () {
- var obj = {}
- var arr = this.values
-
- for (var i = 0, len = arr.length; i < len; i += 2) {
- obj[arr[i]] = arr[i + 1]
- }
-
- return obj
- }
-
- toArray () {
- return this.values
- }
-}
-
-const morphableTypes = [
- NonMorphable,
- TransformBag,
- ObjectBag
-]
-
-export function registerMorphableType (type = []) {
- morphableTypes.push(...[].concat(type))
-}
-
-export function makeMorphable () {
- extend(morphableTypes, {
- to (val) {
- return new Morphable()
- .type(this.constructor)
- .from(this.valueOf())
- .to(val)
- },
- fromArray (arr) {
- this.init(arr)
- return this
- }
- })
-}