UNPKG

vc-popup

Version:

vue popup components with power position and animation support and back key support as well

1,673 lines (1,655 loc) 268 kB
// Snap.svg 0.5.1 // // Copyright (c) 2013 – 2017 Adobe Systems Incorporated. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // build: 2017-02-07 // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ┌────────────────────────────────────────────────────────────┐ \\ // │ Eve 0.5.0 - JavaScript Events Library │ \\ // ├────────────────────────────────────────────────────────────┤ \\ // │ Author Dmitry Baranovskiy (http://dmitry.baranovskiy.com/) │ \\ // └────────────────────────────────────────────────────────────┘ \\ (function (glob, factory) { // AMD support if (typeof define == "function" && define.amd) { // Define as an anonymous module define(["eve"], function (eve) { return factory(glob, eve); }); } else if (typeof exports != "undefined") { // Next for Node.js or CommonJS var eve = require("eve"); module.exports = factory(glob, eve); } else { // Browser globals (glob is window) // Snap adds itself to window factory(glob, glob.eve); } }(window || this, function (window, eve) { // Copyright (c) 2017 Adobe Systems Incorporated. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. var mina = (function (eve) { var animations = {}, requestAnimFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) { setTimeout(callback, 16, new Date().getTime()); return true; }, requestID, isArray = Array.isArray || function (a) { return a instanceof Array || Object.prototype.toString.call(a) == "[object Array]"; }, idgen = 0, idprefix = "M" + (+new Date).toString(36), ID = function () { return idprefix + (idgen++).toString(36); }, diff = function (a, b, A, B) { if (isArray(a)) { res = []; for (var i = 0, ii = a.length; i < ii; i++) { res[i] = diff(a[i], b, A[i], B); } return res; } var dif = (A - a) / (B - b); return function (bb) { return a + dif * (bb - b); }; }, timer = Date.now || function () { return +new Date; }, sta = function (val) { var a = this; if (val == null) { return a.s; } var ds = a.s - val; a.b += a.dur * ds; a.B += a.dur * ds; a.s = val; }, speed = function (val) { var a = this; if (val == null) { return a.spd; } a.spd = val; }, duration = function (val) { var a = this; if (val == null) { return a.dur; } a.s = a.s * val / a.dur; a.dur = val; }, stopit = function () { var a = this; delete animations[a.id]; a.update(); eve("mina.stop." + a.id, a); }, pause = function () { var a = this; if (a.pdif) { return; } delete animations[a.id]; a.update(); a.pdif = a.get() - a.b; }, resume = function () { var a = this; if (!a.pdif) { return; } a.b = a.get() - a.pdif; delete a.pdif; animations[a.id] = a; frame(); }, update = function () { var a = this, res; if (isArray(a.start)) { res = []; for (var j = 0, jj = a.start.length; j < jj; j++) { res[j] = +a.start[j] + (a.end[j] - a.start[j]) * a.easing(a.s); } } else { res = +a.start + (a.end - a.start) * a.easing(a.s); } a.set(res); }, frame = function (timeStamp) { // Manual invokation? if (!timeStamp) { // Frame loop stopped? if (!requestID) { // Start frame loop... requestID = requestAnimFrame(frame); } return; } var len = 0; for (var i in animations) if (animations.hasOwnProperty(i)) { var a = animations[i], b = a.get(), res; len++; a.s = (b - a.b) / (a.dur / a.spd); if (a.s >= 1) { delete animations[i]; a.s = 1; len--; (function (a) { setTimeout(function () { eve("mina.finish." + a.id, a); }); }(a)); } a.update(); } requestID = len ? requestAnimFrame(frame) : false; }, /*\ * mina [ method ] ** * Generic animation of numbers ** - a (number) start _slave_ number - A (number) end _slave_ number - b (number) start _master_ number (start time in general case) - B (number) end _master_ number (end time in general case) - get (function) getter of _master_ number (see @mina.time) - set (function) setter of _slave_ number - easing (function) #optional easing function, default is @mina.linear = (object) animation descriptor o { o id (string) animation id, o start (number) start _slave_ number, o end (number) end _slave_ number, o b (number) start _master_ number, o s (number) animation status (0..1), o dur (number) animation duration, o spd (number) animation speed, o get (function) getter of _master_ number (see @mina.time), o set (function) setter of _slave_ number, o easing (function) easing function, default is @mina.linear, o status (function) status getter/setter, o speed (function) speed getter/setter, o duration (function) duration getter/setter, o stop (function) animation stopper o pause (function) pauses the animation o resume (function) resumes the animation o update (function) calles setter with the right value of the animation o } \*/ mina = function (a, A, b, B, get, set, easing) { var anim = { id: ID(), start: a, end: A, b: b, s: 0, dur: B - b, spd: 1, get: get, set: set, easing: easing || mina.linear, status: sta, speed: speed, duration: duration, stop: stopit, pause: pause, resume: resume, update: update }; animations[anim.id] = anim; var len = 0, i; for (i in animations) if (animations.hasOwnProperty(i)) { len++; if (len == 2) { break; } } len == 1 && frame(); return anim; }; /*\ * mina.time [ method ] ** * Returns the current time. Equivalent to: | function () { | return (new Date).getTime(); | } \*/ mina.time = timer; /*\ * mina.getById [ method ] ** * Returns an animation by its id - id (string) animation's id = (object) See @mina \*/ mina.getById = function (id) { return animations[id] || null; }; /*\ * mina.linear [ method ] ** * Default linear easing - n (number) input 0..1 = (number) output 0..1 \*/ mina.linear = function (n) { return n; }; /*\ * mina.easeout [ method ] ** * Easeout easing - n (number) input 0..1 = (number) output 0..1 \*/ mina.easeout = function (n) { return Math.pow(n, 1.7); }; /*\ * mina.easein [ method ] ** * Easein easing - n (number) input 0..1 = (number) output 0..1 \*/ mina.easein = function (n) { return Math.pow(n, .48); }; /*\ * mina.easeinout [ method ] ** * Easeinout easing - n (number) input 0..1 = (number) output 0..1 \*/ mina.easeinout = function (n) { if (n == 1) { return 1; } if (n == 0) { return 0; } var q = .48 - n / 1.04, Q = Math.sqrt(.1734 + q * q), x = Q - q, X = Math.pow(Math.abs(x), 1 / 3) * (x < 0 ? -1 : 1), y = -Q - q, Y = Math.pow(Math.abs(y), 1 / 3) * (y < 0 ? -1 : 1), t = X + Y + .5; return (1 - t) * 3 * t * t + t * t * t; }; /*\ * mina.backin [ method ] ** * Backin easing - n (number) input 0..1 = (number) output 0..1 \*/ mina.backin = function (n) { if (n == 1) { return 1; } var s = 1.70158; return n * n * ((s + 1) * n - s); }; /*\ * mina.backout [ method ] ** * Backout easing - n (number) input 0..1 = (number) output 0..1 \*/ mina.backout = function (n) { if (n == 0) { return 0; } n = n - 1; var s = 1.70158; return n * n * ((s + 1) * n + s) + 1; }; /*\ * mina.elastic [ method ] ** * Elastic easing - n (number) input 0..1 = (number) output 0..1 \*/ mina.elastic = function (n) { if (n == !!n) { return n; } return Math.pow(2, -10 * n) * Math.sin((n - .075) * (2 * Math.PI) / .3) + 1; }; /*\ * mina.bounce [ method ] ** * Bounce easing - n (number) input 0..1 = (number) output 0..1 \*/ mina.bounce = function (n) { var s = 7.5625, p = 2.75, l; if (n < 1 / p) { l = s * n * n; } else { if (n < 2 / p) { n -= 1.5 / p; l = s * n * n + .75; } else { if (n < 2.5 / p) { n -= 2.25 / p; l = s * n * n + .9375; } else { n -= 2.625 / p; l = s * n * n + .984375; } } } return l; }; window.mina = mina; return mina; })(typeof eve == "undefined" ? function () {} : eve); // Copyright (c) 2013 - 2017 Adobe Systems Incorporated. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. var Snap = (function(root) { Snap.version = "0.5.1"; /*\ * Snap [ method ] ** * Creates a drawing surface or wraps existing SVG element. ** - width (number|string) width of surface - height (number|string) height of surface * or - DOM (SVGElement) element to be wrapped into Snap structure * or - array (array) array of elements (will return set of elements) * or - query (string) CSS query selector = (object) @Element \*/ function Snap(w, h) { if (w) { if (w.nodeType) { return wrap(w); } if (is(w, "array") && Snap.set) { return Snap.set.apply(Snap, w); } if (w instanceof Element) { return w; } if (h == null) { try { w = glob.doc.querySelector(String(w)); return wrap(w); } catch (e) { return null; } } } w = w == null ? "100%" : w; h = h == null ? "100%" : h; return new Paper(w, h); } Snap.toString = function () { return "Snap v" + this.version; }; Snap._ = {}; var glob = { win: root.window, doc: root.window.document }; Snap._.glob = glob; var has = "hasOwnProperty", Str = String, toFloat = parseFloat, toInt = parseInt, math = Math, mmax = math.max, mmin = math.min, abs = math.abs, pow = math.pow, PI = math.PI, round = math.round, E = "", S = " ", objectToString = Object.prototype.toString, ISURL = /^url\(['"]?([^\)]+?)['"]?\)$/i, colourRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?%?)\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?%?)\s*\))\s*$/i, bezierrg = /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/, separator = Snap._.separator = /[,\s]+/, whitespace = /[\s]/g, commaSpaces = /[\s]*,[\s]*/, hsrg = {hs: 1, rg: 1}, pathCommand = /([a-z])[\s,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\s]*,?[\s]*)+)/ig, tCommand = /([rstm])[\s,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\s]*,?[\s]*)+)/ig, pathValues = /(-?\d*\.?\d*(?:e[\-+]?\d+)?)[\s]*,?[\s]*/ig, idgen = 0, idprefix = "S" + (+new Date).toString(36), ID = function (el) { return (el && el.type ? el.type : E) + idprefix + (idgen++).toString(36); }, xlink = "http://www.w3.org/1999/xlink", xmlns = "http://www.w3.org/2000/svg", hub = {}, /*\ * Snap.url [ method ] ** * Wraps path into `"url('<path>')"`. - value (string) path = (string) wrapped path \*/ URL = Snap.url = function (url) { return "url('#" + url + "')"; }; function $(el, attr) { if (attr) { if (el == "#text") { el = glob.doc.createTextNode(attr.text || attr["#text"] || ""); } if (el == "#comment") { el = glob.doc.createComment(attr.text || attr["#text"] || ""); } if (typeof el == "string") { el = $(el); } if (typeof attr == "string") { if (el.nodeType == 1) { if (attr.substring(0, 6) == "xlink:") { return el.getAttributeNS(xlink, attr.substring(6)); } if (attr.substring(0, 4) == "xml:") { return el.getAttributeNS(xmlns, attr.substring(4)); } return el.getAttribute(attr); } else if (attr == "text") { return el.nodeValue; } else { return null; } } if (el.nodeType == 1) { for (var key in attr) if (attr[has](key)) { var val = Str(attr[key]); if (val) { if (key.substring(0, 6) == "xlink:") { el.setAttributeNS(xlink, key.substring(6), val); } else if (key.substring(0, 4) == "xml:") { el.setAttributeNS(xmlns, key.substring(4), val); } else { el.setAttribute(key, val); } } else { el.removeAttribute(key); } } } else if ("text" in attr) { el.nodeValue = attr.text; } } else { el = glob.doc.createElementNS(xmlns, el); } return el; } Snap._.$ = $; Snap._.id = ID; function getAttrs(el) { var attrs = el.attributes, name, out = {}; for (var i = 0; i < attrs.length; i++) { if (attrs[i].namespaceURI == xlink) { name = "xlink:"; } else { name = ""; } name += attrs[i].name; out[name] = attrs[i].textContent; } return out; } function is(o, type) { type = Str.prototype.toLowerCase.call(type); if (type == "finite") { return isFinite(o); } if (type == "array" && (o instanceof Array || Array.isArray && Array.isArray(o))) { return true; } return type == "null" && o === null || type == typeof o && o !== null || type == "object" && o === Object(o) || objectToString.call(o).slice(8, -1).toLowerCase() == type; } /*\ * Snap.format [ method ] ** * Replaces construction of type `{<name>}` to the corresponding argument ** - token (string) string to format - json (object) object which properties are used as a replacement = (string) formatted string > Usage | // this draws a rectangular shape equivalent to "M10,20h40v50h-40z" | paper.path(Snap.format("M{x},{y}h{dim.width}v{dim.height}h{dim['negative width']}z", { | x: 10, | y: 20, | dim: { | width: 40, | height: 50, | "negative width": -40 | } | })); \*/ Snap.format = (function () { var tokenRegex = /\{([^\}]+)\}/g, objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g, // matches .xxxxx or ["xxxxx"] to run over object properties replacer = function (all, key, obj) { var res = obj; key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) { name = name || quotedName; if (res) { if (name in res) { res = res[name]; } typeof res == "function" && isFunc && (res = res()); } }); res = (res == null || res == obj ? all : res) + ""; return res; }; return function (str, obj) { return Str(str).replace(tokenRegex, function (all, key) { return replacer(all, key, obj); }); }; })(); function clone(obj) { if (typeof obj == "function" || Object(obj) !== obj) { return obj; } var res = new obj.constructor; for (var key in obj) if (obj[has](key)) { res[key] = clone(obj[key]); } return res; } Snap._.clone = clone; function repush(array, item) { for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) { return array.push(array.splice(i, 1)[0]); } } function cacher(f, scope, postprocessor) { function newf() { var arg = Array.prototype.slice.call(arguments, 0), args = arg.join("\u2400"), cache = newf.cache = newf.cache || {}, count = newf.count = newf.count || []; if (cache[has](args)) { repush(count, args); return postprocessor ? postprocessor(cache[args]) : cache[args]; } count.length >= 1e3 && delete cache[count.shift()]; count.push(args); cache[args] = f.apply(scope, arg); return postprocessor ? postprocessor(cache[args]) : cache[args]; } return newf; } Snap._.cacher = cacher; function angle(x1, y1, x2, y2, x3, y3) { if (x3 == null) { var x = x1 - x2, y = y1 - y2; if (!x && !y) { return 0; } return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360; } else { return angle(x1, y1, x3, y3) - angle(x2, y2, x3, y3); } } function rad(deg) { return deg % 360 * PI / 180; } function deg(rad) { return rad * 180 / PI % 360; } function x_y() { return this.x + S + this.y; } function x_y_w_h() { return this.x + S + this.y + S + this.width + " \xd7 " + this.height; } /*\ * Snap.rad [ method ] ** * Transform angle to radians - deg (number) angle in degrees = (number) angle in radians \*/ Snap.rad = rad; /*\ * Snap.deg [ method ] ** * Transform angle to degrees - rad (number) angle in radians = (number) angle in degrees \*/ Snap.deg = deg; /*\ * Snap.sin [ method ] ** * Equivalent to `Math.sin()` only works with degrees, not radians. - angle (number) angle in degrees = (number) sin \*/ Snap.sin = function (angle) { return math.sin(Snap.rad(angle)); }; /*\ * Snap.tan [ method ] ** * Equivalent to `Math.tan()` only works with degrees, not radians. - angle (number) angle in degrees = (number) tan \*/ Snap.tan = function (angle) { return math.tan(Snap.rad(angle)); }; /*\ * Snap.cos [ method ] ** * Equivalent to `Math.cos()` only works with degrees, not radians. - angle (number) angle in degrees = (number) cos \*/ Snap.cos = function (angle) { return math.cos(Snap.rad(angle)); }; /*\ * Snap.asin [ method ] ** * Equivalent to `Math.asin()` only works with degrees, not radians. - num (number) value = (number) asin in degrees \*/ Snap.asin = function (num) { return Snap.deg(math.asin(num)); }; /*\ * Snap.acos [ method ] ** * Equivalent to `Math.acos()` only works with degrees, not radians. - num (number) value = (number) acos in degrees \*/ Snap.acos = function (num) { return Snap.deg(math.acos(num)); }; /*\ * Snap.atan [ method ] ** * Equivalent to `Math.atan()` only works with degrees, not radians. - num (number) value = (number) atan in degrees \*/ Snap.atan = function (num) { return Snap.deg(math.atan(num)); }; /*\ * Snap.atan2 [ method ] ** * Equivalent to `Math.atan2()` only works with degrees, not radians. - num (number) value = (number) atan2 in degrees \*/ Snap.atan2 = function (num) { return Snap.deg(math.atan2(num)); }; /*\ * Snap.angle [ method ] ** * Returns an angle between two or three points - x1 (number) x coord of first point - y1 (number) y coord of first point - x2 (number) x coord of second point - y2 (number) y coord of second point - x3 (number) #optional x coord of third point - y3 (number) #optional y coord of third point = (number) angle in degrees \*/ Snap.angle = angle; /*\ * Snap.len [ method ] ** * Returns distance between two points - x1 (number) x coord of first point - y1 (number) y coord of first point - x2 (number) x coord of second point - y2 (number) y coord of second point = (number) distance \*/ Snap.len = function (x1, y1, x2, y2) { return Math.sqrt(Snap.len2(x1, y1, x2, y2)); }; /*\ * Snap.len2 [ method ] ** * Returns squared distance between two points - x1 (number) x coord of first point - y1 (number) y coord of first point - x2 (number) x coord of second point - y2 (number) y coord of second point = (number) distance \*/ Snap.len2 = function (x1, y1, x2, y2) { return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); }; /*\ * Snap.closestPoint [ method ] ** * Returns closest point to a given one on a given path. - path (Element) path element - x (number) x coord of a point - y (number) y coord of a point = (object) in format { x (number) x coord of the point on the path y (number) y coord of the point on the path length (number) length of the path to the point distance (number) distance from the given point to the path } \*/ // Copied from http://bl.ocks.org/mbostock/8027637 Snap.closestPoint = function (path, x, y) { function distance2(p) { var dx = p.x - x, dy = p.y - y; return dx * dx + dy * dy; } var pathNode = path.node, pathLength = pathNode.getTotalLength(), precision = pathLength / pathNode.pathSegList.numberOfItems * .125, best, bestLength, bestDistance = Infinity; // linear scan for coarse approximation for (var scan, scanLength = 0, scanDistance; scanLength <= pathLength; scanLength += precision) { if ((scanDistance = distance2(scan = pathNode.getPointAtLength(scanLength))) < bestDistance) { best = scan; bestLength = scanLength; bestDistance = scanDistance; } } // binary search for precise estimate precision *= .5; while (precision > .5) { var before, after, beforeLength, afterLength, beforeDistance, afterDistance; if ((beforeLength = bestLength - precision) >= 0 && (beforeDistance = distance2(before = pathNode.getPointAtLength(beforeLength))) < bestDistance) { best = before; bestLength = beforeLength; bestDistance = beforeDistance; } else if ((afterLength = bestLength + precision) <= pathLength && (afterDistance = distance2(after = pathNode.getPointAtLength(afterLength))) < bestDistance) { best = after; bestLength = afterLength; bestDistance = afterDistance; } else { precision *= .5; } } best = { x: best.x, y: best.y, length: bestLength, distance: Math.sqrt(bestDistance) }; return best; } /*\ * Snap.is [ method ] ** * Handy replacement for the `typeof` operator - o (…) any object or primitive - type (string) name of the type, e.g., `string`, `function`, `number`, etc. = (boolean) `true` if given value is of given type \*/ Snap.is = is; /*\ * Snap.snapTo [ method ] ** * Snaps given value to given grid - values (array|number) given array of values or step of the grid - value (number) value to adjust - tolerance (number) #optional maximum distance to the target value that would trigger the snap. Default is `10`. = (number) adjusted value \*/ Snap.snapTo = function (values, value, tolerance) { tolerance = is(tolerance, "finite") ? tolerance : 10; if (is(values, "array")) { var i = values.length; while (i--) if (abs(values[i] - value) <= tolerance) { return values[i]; } } else { values = +values; var rem = value % values; if (rem < tolerance) { return value - rem; } if (rem > values - tolerance) { return value - rem + values; } } return value; }; // Colour /*\ * Snap.getRGB [ method ] ** * Parses color string as RGB object - color (string) color string in one of the following formats: # <ul> # <li>Color name (<code>red</code>, <code>green</code>, <code>cornflowerblue</code>, etc)</li> # <li>#••• — shortened HTML color: (<code>#000</code>, <code>#fc0</code>, etc.)</li> # <li>#•••••• — full length HTML color: (<code>#000000</code>, <code>#bd2300</code>)</li> # <li>rgb(•••, •••, •••) — red, green and blue channels values: (<code>rgb(200,&nbsp;100,&nbsp;0)</code>)</li> # <li>rgba(•••, •••, •••, •••) — also with opacity</li> # <li>rgb(•••%, •••%, •••%) — same as above, but in %: (<code>rgb(100%,&nbsp;175%,&nbsp;0%)</code>)</li> # <li>rgba(•••%, •••%, •••%, •••%) — also with opacity</li> # <li>hsb(•••, •••, •••) — hue, saturation and brightness values: (<code>hsb(0.5,&nbsp;0.25,&nbsp;1)</code>)</li> # <li>hsba(•••, •••, •••, •••) — also with opacity</li> # <li>hsb(•••%, •••%, •••%) — same as above, but in %</li> # <li>hsba(•••%, •••%, •••%, •••%) — also with opacity</li> # <li>hsl(•••, •••, •••) — hue, saturation and luminosity values: (<code>hsb(0.5,&nbsp;0.25,&nbsp;0.5)</code>)</li> # <li>hsla(•••, •••, •••, •••) — also with opacity</li> # <li>hsl(•••%, •••%, •••%) — same as above, but in %</li> # <li>hsla(•••%, •••%, •••%, •••%) — also with opacity</li> # </ul> * Note that `%` can be used any time: `rgb(20%, 255, 50%)`. = (object) RGB object in the following format: o { o r (number) red, o g (number) green, o b (number) blue, o hex (string) color in HTML/CSS format: #••••••, o error (boolean) true if string can't be parsed o } \*/ Snap.getRGB = cacher(function (colour) { if (!colour || !!((colour = Str(colour)).indexOf("-") + 1)) { return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: rgbtoString}; } if (colour == "none") { return {r: -1, g: -1, b: -1, hex: "none", toString: rgbtoString}; } !(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == "#") && (colour = toHex(colour)); if (!colour) { return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: rgbtoString}; } var res, red, green, blue, opacity, t, values, rgb = colour.match(colourRegExp); if (rgb) { if (rgb[2]) { blue = toInt(rgb[2].substring(5), 16); green = toInt(rgb[2].substring(3, 5), 16); red = toInt(rgb[2].substring(1, 3), 16); } if (rgb[3]) { blue = toInt((t = rgb[3].charAt(3)) + t, 16); green = toInt((t = rgb[3].charAt(2)) + t, 16); red = toInt((t = rgb[3].charAt(1)) + t, 16); } if (rgb[4]) { values = rgb[4].split(commaSpaces); red = toFloat(values[0]); values[0].slice(-1) == "%" && (red *= 2.55); green = toFloat(values[1]); values[1].slice(-1) == "%" && (green *= 2.55); blue = toFloat(values[2]); values[2].slice(-1) == "%" && (blue *= 2.55); rgb[1].toLowerCase().slice(0, 4) == "rgba" && (opacity = toFloat(values[3])); values[3] && values[3].slice(-1) == "%" && (opacity /= 100); } if (rgb[5]) { values = rgb[5].split(commaSpaces); red = toFloat(values[0]); values[0].slice(-1) == "%" && (red /= 100); green = toFloat(values[1]); values[1].slice(-1) == "%" && (green /= 100); blue = toFloat(values[2]); values[2].slice(-1) == "%" && (blue /= 100); (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360); rgb[1].toLowerCase().slice(0, 4) == "hsba" && (opacity = toFloat(values[3])); values[3] && values[3].slice(-1) == "%" && (opacity /= 100); return Snap.hsb2rgb(red, green, blue, opacity); } if (rgb[6]) { values = rgb[6].split(commaSpaces); red = toFloat(values[0]); values[0].slice(-1) == "%" && (red /= 100); green = toFloat(values[1]); values[1].slice(-1) == "%" && (green /= 100); blue = toFloat(values[2]); values[2].slice(-1) == "%" && (blue /= 100); (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360); rgb[1].toLowerCase().slice(0, 4) == "hsla" && (opacity = toFloat(values[3])); values[3] && values[3].slice(-1) == "%" && (opacity /= 100); return Snap.hsl2rgb(red, green, blue, opacity); } red = mmin(math.round(red), 255); green = mmin(math.round(green), 255); blue = mmin(math.round(blue), 255); opacity = mmin(mmax(opacity, 0), 1); rgb = {r: red, g: green, b: blue, toString: rgbtoString}; rgb.hex = "#" + (16777216 | blue | green << 8 | red << 16).toString(16).slice(1); rgb.opacity = is(opacity, "finite") ? opacity : 1; return rgb; } return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: rgbtoString}; }, Snap); /*\ * Snap.hsb [ method ] ** * Converts HSB values to a hex representation of the color - h (number) hue - s (number) saturation - b (number) value or brightness = (string) hex representation of the color \*/ Snap.hsb = cacher(function (h, s, b) { return Snap.hsb2rgb(h, s, b).hex; }); /*\ * Snap.hsl [ method ] ** * Converts HSL values to a hex representation of the color - h (number) hue - s (number) saturation - l (number) luminosity = (string) hex representation of the color \*/ Snap.hsl = cacher(function (h, s, l) { return Snap.hsl2rgb(h, s, l).hex; }); /*\ * Snap.rgb [ method ] ** * Converts RGB values to a hex representation of the color - r (number) red - g (number) green - b (number) blue = (string) hex representation of the color \*/ Snap.rgb = cacher(function (r, g, b, o) { if (is(o, "finite")) { var round = math.round; return "rgba(" + [round(r), round(g), round(b), +o.toFixed(2)] + ")"; } return "#" + (16777216 | b | g << 8 | r << 16).toString(16).slice(1); }); var toHex = function (color) { var i = glob.doc.getElementsByTagName("head")[0] || glob.doc.getElementsByTagName("svg")[0], red = "rgb(255, 0, 0)"; toHex = cacher(function (color) { if (color.toLowerCase() == "red") { return red; } i.style.color = red; i.style.color = color; var out = glob.doc.defaultView.getComputedStyle(i, E).getPropertyValue("color"); return out == red ? null : out; }); return toHex(color); }, hsbtoString = function () { return "hsb(" + [this.h, this.s, this.b] + ")"; }, hsltoString = function () { return "hsl(" + [this.h, this.s, this.l] + ")"; }, rgbtoString = function () { return this.opacity == 1 || this.opacity == null ? this.hex : "rgba(" + [this.r, this.g, this.b, this.opacity] + ")"; }, prepareRGB = function (r, g, b) { if (g == null && is(r, "object") && "r" in r && "g" in r && "b" in r) { b = r.b; g = r.g; r = r.r; } if (g == null && is(r, string)) { var clr = Snap.getRGB(r); r = clr.r; g = clr.g; b = clr.b; } if (r > 1 || g > 1 || b > 1) { r /= 255; g /= 255; b /= 255; } return [r, g, b]; }, packageRGB = function (r, g, b, o) { r = math.round(r * 255); g = math.round(g * 255); b = math.round(b * 255); var rgb = { r: r, g: g, b: b, opacity: is(o, "finite") ? o : 1, hex: Snap.rgb(r, g, b), toString: rgbtoString }; is(o, "finite") && (rgb.opacity = o); return rgb; }; /*\ * Snap.color [ method ] ** * Parses the color string and returns an object featuring the color's component values - clr (string) color string in one of the supported formats (see @Snap.getRGB) = (object) Combined RGB/HSB object in the following format: o { o r (number) red, o g (number) green, o b (number) blue, o hex (string) color in HTML/CSS format: #••••••, o error (boolean) `true` if string can't be parsed, o h (number) hue, o s (number) saturation, o v (number) value (brightness), o l (number) lightness o } \*/ Snap.color = function (clr) { var rgb; if (is(clr, "object") && "h" in clr && "s" in clr && "b" in clr) { rgb = Snap.hsb2rgb(clr); clr.r = rgb.r; clr.g = rgb.g; clr.b = rgb.b; clr.opacity = 1; clr.hex = rgb.hex; } else if (is(clr, "object") && "h" in clr && "s" in clr && "l" in clr) { rgb = Snap.hsl2rgb(clr); clr.r = rgb.r; clr.g = rgb.g; clr.b = rgb.b; clr.opacity = 1; clr.hex = rgb.hex; } else { if (is(clr, "string")) { clr = Snap.getRGB(clr); } if (is(clr, "object") && "r" in clr && "g" in clr && "b" in clr && !("error" in clr)) { rgb = Snap.rgb2hsl(clr); clr.h = rgb.h; clr.s = rgb.s; clr.l = rgb.l; rgb = Snap.rgb2hsb(clr); clr.v = rgb.b; } else { clr = {hex: "none"}; clr.r = clr.g = clr.b = clr.h = clr.s = clr.v = clr.l = -1; clr.error = 1; } } clr.toString = rgbtoString; return clr; }; /*\ * Snap.hsb2rgb [ method ] ** * Converts HSB values to an RGB object - h (number) hue - s (number) saturation - v (number) value or brightness = (object) RGB object in the following format: o { o r (number) red, o g (number) green, o b (number) blue, o hex (string) color in HTML/CSS format: #•••••• o } \*/ Snap.hsb2rgb = function (h, s, v, o) { if (is(h, "object") && "h" in h && "s" in h && "b" in h) { v = h.b; s = h.s; o = h.o; h = h.h; } h *= 360; var R, G, B, X, C; h = h % 360 / 60; C = v * s; X = C * (1 - abs(h % 2 - 1)); R = G = B = v - C; h = ~~h; R += [C, X, 0, 0, X, C][h]; G += [X, C, C, X, 0, 0][h]; B += [0, 0, X, C, C, X][h]; return packageRGB(R, G, B, o); }; /*\ * Snap.hsl2rgb [ method ] ** * Converts HSL values to an RGB object - h (number) hue - s (number) saturation - l (number) luminosity = (object) RGB object in the following format: o { o r (number) red, o g (number) green, o b (number) blue, o hex (string) color in HTML/CSS format: #•••••• o } \*/ Snap.hsl2rgb = function (h, s, l, o) { if (is(h, "object") && "h" in h && "s" in h && "l" in h) { l = h.l; s = h.s; h = h.h; } if (h > 1 || s > 1 || l > 1) { h /= 360; s /= 100; l /= 100; } h *= 360; var R, G, B, X, C; h = h % 360 / 60; C = 2 * s * (l < .5 ? l : 1 - l); X = C * (1 - abs(h % 2 - 1)); R = G = B = l - C / 2; h = ~~h; R += [C, X, 0, 0, X, C][h]; G += [X, C, C, X, 0, 0][h]; B += [0, 0, X, C, C, X][h]; return packageRGB(R, G, B, o); }; /*\ * Snap.rgb2hsb [ method ] ** * Converts RGB values to an HSB object - r (number) red - g (number) green - b (number) blue = (object) HSB object in the following format: o { o h (number) hue, o s (number) saturation, o b (number) brightness o } \*/ Snap.rgb2hsb = function (r, g, b) { b = prepareRGB(r, g, b); r = b[0]; g = b[1]; b = b[2]; var H, S, V, C; V = mmax(r, g, b); C = V - mmin(r, g, b); H = C == 0 ? null : V == r ? (g - b) / C : V == g ? (b - r) / C + 2 : (r - g) / C + 4; H = (H + 360) % 6 * 60 / 360; S = C == 0 ? 0 : C / V; return {h: H, s: S, b: V, toString: hsbtoString}; }; /*\ * Snap.rgb2hsl [ method ] ** * Converts RGB values to an HSL object - r (number) red - g (number) green - b (number) blue = (object) HSL object in the following format: o { o h (number) hue, o s (number) saturation, o l (number) luminosity o } \*/ Snap.rgb2hsl = function (r, g, b) { b = prepareRGB(r, g, b); r = b[0]; g = b[1]; b = b[2]; var H, S, L, M, m, C; M = mmax(r, g, b); m = mmin(r, g, b); C = M - m; H = C == 0 ? null : M == r ? (g - b) / C : M == g ? (b - r) / C + 2 : (r - g) / C + 4; H = (H + 360) % 6 * 60 / 360; L = (M + m) / 2; S = C == 0 ? 0 : L < .5 ? C / (2 * L) : C / (2 - 2 * L); return {h: H, s: S, l: L, toString: hsltoString}; }; // Transformations /*\ * Snap.parsePathString [ method ] ** * Utility method ** * Parses given path string into an array of arrays of path segments - pathString (string|array) path string or array of segments (in the last case it is returned straight away) = (array) array of segments \*/ Snap.parsePathString = function (pathString) { if (!pathString) { return null; } var pth = Snap.path(pathString); if (pth.arr) { return Snap.path.clone(pth.arr); } var paramCounts = {a: 7, c: 6, o: 2, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, u: 3, z: 0}, data = []; if (is(pathString, "array") && is(pathString[0], "array")) { // rough assumption data = Snap.path.clone(pathString); } if (!data.length) { Str(pathString).replace(pathCommand, function (a, b, c) { var params = [], name = b.toLowerCase(); c.replace(pathValues, function (a, b) { b && params.push(+b); }); if (name == "m" && params.length > 2) { data.push([b].concat(params.splice(0, 2))); name = "l"; b = b == "m" ? "l" : "L"; } if (name == "o" && params.length == 1) { data.push([b, params[0]]); } if (name == "r") { data.push([b].concat(params)); } else while (params.length >= paramCounts[name]) { data.push([b].concat(params.splice(0, paramCounts[name]))); if (!paramCounts[name]) { break; } } }); } data.toString = Snap.path.toString; pth.arr = Snap.path.clone(data); return data; }; /*\ * Snap.parseTransformString [ method ] ** * Utility method ** * Parses given transform string into an array of transformations - TString (string|array) transform string or array of transformations (in the last case it is returned straight away) = (array) array of transformations \*/ var parseTransformString = Snap.parseTransformString = function (TString) { if (!TString) { return null; } var paramCounts = {r: 3, s: 4, t: 2, m: 6}, data = []; if (is(TString, "array") && is(TString[0], "array")) { // rough assumption data = Snap.path.clone(TString); } if (!data.length) { Str(TString).replace(tCommand, function (a, b, c) { var params = [], name = b.toLowerCase(); c.replace(pathValues, function (a, b) { b && params.push(+b); }); data.push([b].concat(params)); }); } data.toString = Snap.path.toString; return data; }; function svgTransform2string(tstr) { var res = []; tstr = tstr.replace(/(?:^|\s)(\w+)\(([^)]+)\)/g, function (all, name, params) { params = params.split(/\s*,\s*|\s+/); if (name == "rotate" && params.length == 1) { params.push(0, 0); } if (name == "scale") { if (params.length > 2) { params = params.slice(0, 2); } else if (params.length == 2) { params.push(0, 0); } if (params.length == 1) { params.push(params[0], 0, 0); } } if (name == "skewX") { res.push(["m", 1, 0, math.tan(rad(params[0])), 1, 0, 0]); } else if (name == "skewY") { res.push(["m", 1, math.tan(rad(params[0])), 0, 1, 0, 0]); } else { res.push([name.charAt(0)].concat(params)); } return all; }); return res; } Snap._.svgTransform2string = svgTransform2string; Snap._.rgTransform = /^[a-z][\s]*-?\.?\d/i; function transform2matrix(tstr, bbox) { var tdata = parseTransformString(tstr), m = new Snap.Matrix; if (tdata) { for (var i = 0, ii = tdata.length; i < ii; i++) { var t = tdata[i], tlen = t.length, command = Str(t[0]).toLowerCase(), absolute = t[0] != command, inver = absolute ? m.invert() : 0, x1, y1, x2, y2, bb; if (command == "t" && tlen == 2){ m.translate(t[1], 0); } else if (command == "t" && tlen == 3) { if (absolute) { x1 = inver.x(0, 0); y1 = inver.y(0, 0); x2 = inver.x(t[1], t[2]); y2 = inver.y(t[1], t[2]); m.translate(x2 - x1, y2 - y1); } else { m.translate(t[1], t[2]); } } else if (command == "r") { if (tlen == 2) { bb = bb || bbox; m.rotate(t[1], bb.x + bb.width / 2, bb.y + bb.height / 2); } else if (tlen == 4) { if (absolute) { x2 = inver.x(t[2], t[3]); y2 = inver.y(t[2], t[3]); m.rotate(t[1], x2, y2); } else { m.rotate(t[1], t[2], t[3]); } } } else if (command == "s") { if (tlen == 2 || tlen == 3) { bb = bb || bbox; m.scale(t[1], t[tlen - 1], bb.x + bb.width / 2, bb.y + bb.height / 2); } else if (tlen == 4) { if (absolute) { x2 = inver.x(t[2], t[3]); y2 = inver.y(t[2], t[3]); m.scale(t[1], t[1], x2, y2); } else { m.scale(t[1], t[1], t[2], t[3]); } } else if (tlen == 5) { if (absolute) { x2 = inver.x(t[3], t[4]); y2 = inver.y(t[3], t[4]); m.scale(t[1], t[2], x2, y2); } else { m.scale(t[1], t[2], t[3], t[4]); } } } else if (command == "m" && tlen == 7) { m.add(t[1], t[2], t[3], t[4], t[5], t[6]); } } } return m; } Snap._.transform2matrix = transform2matrix; Snap._unit2px = unit2px; var contains = glob.doc.contains || glob.doc.compareDocumentPosition ? function (a, b) { var adown = a.nodeType == 9 ? a.documentElement : a, bup = b && b.parentNode; return a == bup || !!(bup && bup.nodeType == 1 && ( adown.contains ? adown.contains(bup) : a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16 )); } : function (a, b) { if (b) { while (b) { b = b.parentNode; if (b == a) { return true; } } } return false; }; function getSomeDefs(el) { var p = el.node.ownerSVGElement && wrap(el.node.ownerSVGElement) || el.node.parentNode && wrap(el.node.parentNode) || Snap.select("svg") || Snap(0, 0), pdefs = p.select("defs"), defs = pdefs == null ? false : pdefs.node; if (!defs) { defs = make("defs", p.node).node; } return defs; } function getSomeSVG(el) { return el.node.ownerSVGElement && wrap(el.node.ownerSVGElement) || Snap.select("svg"); } Snap._.getSomeDefs = getSomeDefs; Snap._.getSomeSVG = getSomeSVG; function unit2px(el, name, value) { var svg = getSomeSVG(el).node, out = {}, mgr = svg.querySelector(".svg---mgr"); if (!mgr) { mgr = $("rect"); $(mgr, {x: -9e9, y: -9e9, width: 10, height: 10, "class": "svg---mgr", fill: "none"}); svg.appendChild(mgr); } function getW(val) { if (val == null) { return E; } if (val == +val) { return val; } $(mgr, {width: val}); try { return mgr.getBBox().width; } catch (e) { return 0; } } function getH(val) { if (val == null) { return E; } if (val == +val) { return val; } $(mgr, {height: val}); try { return mgr.getBBox().height; } catch (e) { return 0; } } function set(nam, f) { if (name == null) { out[nam] = f(el.attr(nam) || 0); } else if (nam == name) { out = f(value == null ? el.attr(nam) || 0 : value); } } switch (el.type) { case "rect": set("rx", getW); set("ry", getH); case "image": set("width", getW); set("height", getH); case "text": set("x", getW); set("y", getH); break; case "circle": set("cx", getW); set("cy", getH); set("r", getW); break; case "ellipse": set("cx", getW); set("cy", getH); set("rx", getW); set("ry", getH); break; case "line": set("x1", getW); set("x2", getW); set("y1", getH); set("y2", getH); break; case "mar