chaos/bundle.js

675 lines
23 KiB
JavaScript

"use strict";
function _typeof(obj) { return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj; }
(function e(t, n, r) {
function s(o, u) {
if (!n[o]) {
if (!t[o]) {
var a = typeof require == "function" && require;if (!u && a) return a(o, !0);if (i) return i(o, !0);var f = new Error("Cannot find module '" + o + "'");throw f.code = "MODULE_NOT_FOUND", f;
}var l = n[o] = { exports: {} };t[o][0].call(l.exports, function (e) {
var n = t[o][1][e];return s(n ? n : e);
}, l, l.exports, e, t, n, r);
}return n[o].exports;
}var i = typeof require == "function" && require;for (var o = 0; o < r.length; o++) {
s(r[o]);
}return s;
})({ 1: [function (require, module, exports) {
'use strict';
var wrapNode = require('./lib/node');
/**
* Import given node into `the-dom`
*
* @param {Node} node Node to import
* @return {Object} Wrapped node
*/
exports.import = function (node) {
return wrapNode(node);
};
/**
* Import an HTML document into `the-dom`
*
* @param {HTMLDocument} doc Document to import
* @return {Object} A hash with doctype, body, head, html props
*/
exports.html = function (doc) {
return {
create: function create(name) {
return doc.createElement(name);
},
body: wrapNode(doc.body),
head: wrapNode(doc.head),
html: wrapNode(doc.documentElement),
doctype: wrapNode(doc.doctype)
};
};
}, { "./lib/node": 3 }], 2: [function (require, module, exports) {
'use strict';
var utils = require('./utils');
var split = utils.split;
var iterateArray = utils.iterateArray;
/**
* Create an object to manipulate given node's CSS classes
*
* @param {HTMLElement} node Input element
* @see `Set` documentation for behaviour information
* @return {Object} Set-like object
*/
var wrapClass = function wrapClass(node) {
var res = {
add: function add(el) {
if (!this.has(el)) {
var classes = split(node.className);
classes.push(el);
node.className = classes.join(' ');
}
return this;
},
delete: function _delete(el) {
var classes = split(node.className),
pos = classes.indexOf(el);
if (pos > -1) {
classes.splice(pos, 1);
node.className = classes.join(' ');
return true;
}
return false;
},
has: function has(el) {
return split(node.className).indexOf(el) !== -1;
},
clear: function clear() {
return node.className = '';
},
get size() {
return split(node.className).length;
},
keys: function keys() {
return iterateArray(split(node.className));
},
values: function values() {
return iterateArray(split(node.className));
},
entries: function entries() {
return iterateArray(split(node.className).map(function (el) {
return [el, el];
}));
},
forEach: function forEach(callback, thisArg) {
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = this[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var cls = _step.value;
callback.call(thisArg, cls, cls, this);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
}
};
res[Symbol.iterator] = res.values;
return res;
};
module.exports = wrapClass;
}, { "./utils": 5 }], 3: [function (require, module, exports) {
'use strict';
var wrapClass = require('./class');
var wrapStyle = require('./style');
var split = require('./utils').split;
/**
* Ensure a node is not wrapped before using it in native methods
*
* @param {Node|Object} node A node, wrapped or not
* @return {Node} Unwrapped node
*/
var unwrap = function unwrap(node) {
return (typeof node === "undefined" ? "undefined" : _typeof(node)) !== 'object' || node === null || !node.node ? node : node.node;
};
/**
* Turn a NodeList/HTMLCollection into an array
* for easy manipulation
*
* @param {NodeList|HTMLCollection} list Input collection
* @return {Array} Wrapping array
*/
var wrapList = function wrapList(list) {
var length = list.length;
var result = [];
for (var i = 0; i < length; i += 1) {
result.push(wrapNode(list.item(i)));
}
return Object.assign(result, {
on: function on(evts, handler) {
result.forEach(function (node) {
return node.on(evts, handler);
});
},
off: function off(evts, handler) {
result.forEach(function (node) {
return node.off(evts, handler);
});
}
});
};
/**
* Create an object of shortcuts to manipulate
* given node more easily
*
* @param {Node} Input node
* @return {Object} DOM shortcuts
*/
var wrapNode = function wrapNode(node) {
if (node === null || (typeof node === "undefined" ? "undefined" : _typeof(node)) !== 'object') {
return null;
}
return {
node: node,
// search among children
find: function find(query) {
return wrapNode(node.querySelector(query));
},
findAll: function findAll(query) {
return wrapList(node.querySelectorAll(query));
},
// access node's relative tree (parent, children, siblings)
equal: function equal(el) {
return unwrap(el) === node;
},
get following() {
return wrapNode(node.nextElementSibling);
},
get preceding() {
return wrapNode(node.previousElementSibling);
},
get parent() {
return wrapNode(node.parentNode);
},
get children() {
return wrapList(node.children);
},
// check relative positions
precedes: function precedes(el) {
return !!(unwrap(el).compareDocumentPosition(node) & 2);
},
follows: function follows(el) {
return !!(unwrap(el).compareDocumentPosition(node) & 4);
},
contains: function contains(el) {
return !!(unwrap(el).compareDocumentPosition(node) & 8);
},
contained: function contained(el) {
return !!(unwrap(el).compareDocumentPosition(node) & 16);
},
// get and set element attributes
get name() {
return node.tagName.toLowerCase().trim();
},
get type() {
switch (node.nodeType) {
case 1:
return 'element';
case 3:
return 'text';
case 7:
return 'processing-instruction';
case 8:
return 'comment';
case 9:
return 'document';
case 10:
return 'document-type';
case 11:
return 'document-fragment';
default:
return null;
}
},
getAttr: function getAttr(attr) {
return node.getAttribute(attr);
},
setAttr: function setAttr(attr, value) {
return node.setAttribute(attr, value);
},
// place an element in the DOM tree
append: function append(subnode) {
return node.appendChild(unwrap(subnode));
},
attach: function attach(parent) {
return unwrap(parent).appendChild(node);
},
remove: function remove(child) {
if (child) {
node.removeChild(unwrap(child));
return;
}
node.parentNode.removeChild(node);
},
// manipulate element's CSS (see wrapClass, wrapStyle)
class: wrapClass(node),
style: wrapStyle(node),
// change an element's content
get text() {
return node.textContent;
},
set text(val) {
node.textContent = val;
},
get html() {
return node.innerHTML;
},
set html(val) {
node.innerHTML = val;
},
// listen to events
on: function on(evts, handler) {
split(evts).forEach(function (evt) {
node.addEventListener(evt, handler);
});
},
off: function off(evts, handler) {
split(evts).forEach(function (evt) {
node.removeEventListener(evt, handler);
});
}
};
};
module.exports = wrapNode;
}, { "./class": 2, "./style": 4, "./utils": 5 }], 4: [function (require, module, exports) {
'use strict';
var iterateArray = require('./utils').iterateArray;
/**
* Create an object to manipulate given node's CSS styles
*
* @param {HTMLElement} node Input element
* @see `Map` documentation for behaviour information
* @return {Object} Map-like object
*/
var wrapStyle = function wrapStyle(node) {
var res = {
set: function set(prop, value) {
node.style.setProperty(prop, value);
return this;
},
delete: function _delete(prop) {
return node.style.removeProperty(prop) !== '';
},
has: function has(prop) {
return [].slice.call(node.style).indexOf(prop) > -1;
},
get: function get(prop) {
var result = node.style.getPropertyValue(prop);
if (result.trim() === '') {
return undefined;
}
return result;
},
clear: function clear() {
var length = node.style.length;
for (var i = 0; i < length; i += 1) {
node.style.removeProperty(node.style[i]);
}
},
get size() {
return node.style.length;
},
keys: function keys() {
return iterateArray([].slice.call(node.style));
},
values: function values() {
return iterateArray([].slice.call(node.style).map(function (prop) {
return node.style.getPropertyValue(prop);
}));
},
entries: function entries() {
return iterateArray([].slice.call(node.style).map(function (prop) {
return [prop, node.style.getPropertyValue(prop)];
}));
},
forEach: function forEach(callback, thisArg) {
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = this[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var cls = _step2.value;
callback.call(thisArg, cls, cls, this);
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
}
};
res[Symbol.iterator] = res.values;
return res;
};
module.exports = wrapStyle;
}, { "./utils": 5 }], 5: [function (require, module, exports) {
'use strict';
var whitespace = /\s+/g;
/**
* Split a list of whitespace separated tokens,
* excluding empty ones
*
* @param {string} str Input string
* @return {Array} Split tokens
*/
exports.split = function (str) {
return str.split(whitespace).filter(function (el) {
return el.trim().length;
});
};
/**
* Create an iterator on an array
*
* @param {Array} arr Array to iterate on
* @return {Object} Iterator for given array
*/
exports.iterateArray = function (arr) {
var _next = 0;
return {
next: function next() {
return _next < arr.length ? { value: arr[_next++], done: false } : { done: true };
}
};
};
}, {}], 6: [function (require, module, exports) {
'use strict'
/**
* Choose an index at random among a list of weights,
* more weighted indices have a greater proability to be chosen
*
* @param {Array} weights List of weights
* @return {number} Selected index
*/
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var chooseIndex = function chooseIndex(weights) {
var number = Math.random();
var sum = 0,
index = 0;
while (number >= sum) {
sum += weights[index];
index += 1;
}
return index - 1;
};
/**
* Apply the chaos game: starting from `start`, we plot
* the next `n` points. To get to the next point, we apply
* a random transformation among given ones
*
* @param {Array} start Starting point
* @param {number} iterations Number of points to plot
* @param {Array} transforms List of available transforms
* @param {Array} weights Probability weights for each transform
* @return {null}
*/
var applyChaos = exports.applyChaos = function applyChaos(start, iterations, transforms, weights, cb) {
var point = start;
if (weights === undefined) {
weights = Array.apply(null, Array(transforms.length)).map(function () {
return 1 / transforms.length;
});
}
while (iterations--) {
var index = chooseIndex(weights);
point = transforms[index](point);
cb(point);
}
};
}, {}], 7: [function (require, module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var linearTransform = function linearTransform(a, b, c, d, e, f) {
return function (point) {
return [a * point[0] + b * point[1] + e, c * point[0] + d * point[1] + f];
};
};
var polygonTransforms = function polygonTransforms(vertices, frac) {
return vertices.map(function (vertex) {
return linearTransform(frac, 0, 0, frac, vertex[0] * (frac - 1), vertex[1] * (frac - 1));
});
};
var barnsley = exports.barnsley = [[linearTransform(0, 0, 0, 0.16, 0, 0), linearTransform(.85, .04, -.04, .85, 0, 1.6), linearTransform(.20, -.26, .23, .22, 0, 1.6), linearTransform(-.15, .28, .26, .24, 0, .44)], [.01, .85, .07, .07]];
var sierpinski = exports.sierpinski = [polygonTransforms([[.866, .5], [-.866, .5], [0, -1]], 1 / 2), [1 / 3, 1 / 3, 1 / 3]];
}, {}], 8: [function (require, module, exports) {
'use strict';
var _theDom = require('the-dom');
var _chaos = require('./chaos');
var _ifs = require('./ifs');
function _toConsumableArray(arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {
arr2[i] = arr[i];
}return arr2;
} else {
return Array.from(arr);
}
}
var _html = (0, _theDom.html)(document);
var body = _html.body;
var content = body.find('#content');
var plotting = body.find('#plotting').node;
var ctx = plotting.getContext('2d');
var dragging = false;
var center = undefined,
zoom = 200;
var width = undefined,
height = undefined;
/**
* Re-render the scene from scratch
*
* @return {null}
*/
var render = function render() {
plotting.width = width;
plotting.height = height;
// do not plot (very) small sizes
if (width < 1) {
return;
}
// do the chaos game
var image = ctx.getImageData(0, 0, width, height);
var color = [0, 0, 0];
var skip = 50;
_chaos.applyChaos.apply(undefined, [[0, 0], 200000].concat(_toConsumableArray(_ifs.barnsley), [function (point) {
var x = Math.floor(point[0] * zoom + center[0]);
var y = height - Math.floor(point[1] * zoom + center[1]);
if (x >= 0 && x < width && y >= 0 && y < height && skip <= 0) {
var i = (y * width + x) * 4;
image.data[i] = color[0];
image.data[i + 1] = color[1];
image.data[i + 2] = color[2];
image.data[i + 3] = 255;
}
skip -= 1;
}]));
ctx.putImageData(image, 0, 0);
};
/**
* Update the scene when the window has been resized
*
* @return {null}
*/
var resize = function resize() {
width = content.node.clientWidth;
height = content.node.clientHeight;
center = [Math.floor(width / 2), Math.floor(height / 2)];
render();
};
/**
* Zoom on the cursor position when using mouse wheel
*/
content.on('wheel', function (event) {
var delta = event.deltaMode === 0 ? event.deltaY / 53 : event.deltaY;
var newZoom = zoom * (1 - delta * .035);
// which (unprojected) point does the mouse point on?
var mouse = [(event.offsetX - center[0]) / zoom, (height - event.offsetY - center[1]) / zoom];
// we need to set the center so that `mouse` stays at
// the same position on screen, i.e (vectorially):
// mouse * newZoom + newCenter = mouse * zoom + center
// => newCenter = mouse * zoom - mouse * newZoom + center
center = [mouse[0] * zoom - mouse[0] * newZoom + center[0], mouse[1] * zoom - mouse[1] * newZoom + center[1]];
zoom = newZoom;
render();
event.preventDefault();
});
/**
* Pan the content with click-drag action
*/
content.on('mousedown', function (event) {
return dragging = [event.offsetX, event.offsetY];
});
content.on('mouseup', function () {
return dragging = false;
});
content.on('mousemove', function (event) {
if (dragging !== false) {
var newMouse = [event.offsetX, event.offsetY];
var movement = [newMouse[0] - dragging[0], newMouse[1] - dragging[1]];
center[0] += movement[0];
center[1] -= movement[1];
render();
dragging = newMouse;
event.preventDefault();
}
});
window.onresize = resize;
resize();
}, { "./chaos": 6, "./ifs": 7, "the-dom": 1 }] }, {}, [8]);