css代码
- body {
- margin: 0;
- overflow: hidden;
- background-color: hsl(0, 0%, 8%);
- // background-color: rgb(20, 20, 20);
- }
-
- .overlay {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- z-index: 100;
- }
-
html代码
- <script>
- window.canvasOptions = {
- //- autoClear: true,
- autoCompensate: false,
- autoPushPop: true,
- canvas: true,
- centered: true,
- width: null,
- height: null
- };
- </script>
-
js代码
- // Based on "Pipeline" by Sean Free
-
-
- const particles = [];
- const padding = 100;
-
- function setup() {
- for (let i = 0; i < 10; i++) {
- const p = new Particle();
- particles.push(p);
- }
- }
-
- function draw(e) {
- // rotate(e * 0.0001);
- compositeOperation(compOper.lighter);
- // lineWidth(2);
- for (let i = particles.length - 1; i >= 0; i--) {
- const p = particles[i];
- // if(p.dead) continue;
- if (p.dead) {
- particles.splice(i, 1);
- continue;
- }
- beginPath();
- circle(p.pos, 1);
- p.pos.add(p.vel);
- ctx.shadowColor = hsl(p.hue, 100, 70, 1);
- ctx.shadowBlur = 10;
- const t = (e - p.lastChanged) / 4000;
- fill(hsl(p.hue, 100, 60, 0.3));
- if (
- p.pos.x < -width_half - padding ||
- p.pos.x > width_half + padding ||
- p.pos.y < -height_half - padding ||
- p.pos.y > height_half + padding)
- {
- if (p.splitable) {
- p.reset();
- } else
- {
- p.dead = true;
- }
- } else
- if (random(0.03, 1) < t) {
- p.lastChanged = e;
- p.pickDirection();
- if (particles.length < 300 && random(0.1, 1) < t) {
- const splitP = new Particle();
- splitP.splitable = false;
- splitP.pos.set(p.pos);
- splitP.vel.set(p.vel);
- splitP.pickDirection();
- particles.push(splitP);
- }
- }
- }
- }
-
- class Particle {
- constructor() {
- this.reset();
- this.splitable = true;
- this.dead = false;
- }
- reset() {
- this.lastChanged = performance.now();
- this.hue = random(130) + 180;
- this.pos = createVector(0, 0);
- this.vel = createVector(2, 0);
- this.pickDirection([-2, -1, 0, 1, 2, 3]);
- }
- pickDirection(range = [-1, 0, 1]) {
- this.vel.rotate(random(range) * THIRD_PI);
- }}
-
js
- const {
- E, LN10, LN2, LOG10E, LOG2E, PI, SQRT1_2, SQRT2,
- abs, acos, acosh, asin, asinh, atan, atan2, atanh, cbrt, ceil, clz32,
- cosh, exp, expm1, floor, fround, hypot, imul, log, log10, log1p, log2, max,
- min, pow, /* random, */ round, sign, sinh, sqrt, tan, tanh, trunc
- } = Math;
-
- let _codepenIDRegex = /codepen\.io\/[^/]+\/(?:pen|debug|fullpage|fullembedgrid)\/([^?#]+)/;
-
- // Why not?
- const ZERO = 0.0;
- const ONE = 1.0;
- const TWO = 2.0;
- const THREE = 3.0;
- const FOUR = 4.0;
- const FIVE = 5.0;
- const SIX = 6.0;
- const SEVEN = 7.0;
- const EIGHT = 8.0;
- const NINE = 9.0;
- const TEN = 10.0;
- const ELEVEN = 11.0;
- const TWELVE = 12.0;
- const SIXTEEN = 16.0;
- const THIRTY = 30.0;
- const THIRTY_TWO = 32.0;
- const SIXTY = 60.0;
- const HUNDRED = 100.0;
- const THOUSAND = 1000.0;
-
- const HALF = ONE / TWO;
- const THIRD = ONE / THREE;
- const TWO_THIRDS = THIRD * TWO;
- const QUARTER = ONE / FOUR;
- const THREE_QUARTER = QUARTER * THREE;
- const FIFTH = ONE / FIVE;
- const SIXTH = ONE / SIX;
- const SEVENTH = ONE / SEVEN;
- const EIGHTH = ONE / EIGHT;
- const TWELFTH = ONE / TWELVE;
- const SIXTEENTH = ONE / SIXTEEN;
- const ONE_THIRTIETH = ONE / THIRTY;
- const THIRTY_SECONDTH = ONE / THIRTY_TWO;
- const SIXTIETH = ONE / SIXTY;
-
- const TENTH = 1e-1;
- const HUNDREDTH = 1e-2;
- const THOUSANDTH = 1e-3;
- const TEN_THOUSANDTH = 1e-4;
- const HUNDRED_THOUSANDTH = 1e-5;
- const MILLIONTH = 1e-6;
- const TEN_MILLIONTH = 1e-7;
- const HUNDRED_MILLIONTH = 1e-8;
- const BILLIONTH = 1e-9;
- const TEN_BILLIONTH = 1e-10;
- const HUNDRED_BILLIONTH = 1e-11;
-
- const HALF_PI = PI * HALF;
- const THIRD_PI = PI * THIRD;
- const THREE_QUARTER_PI = PI * THREE_QUARTER;
- const QUARTER_PI = PI * QUARTER;
- const FIFTH_PI = PI * FIFTH;
- const SIXTH_PI = PI * SIXTH;
- const SEVENTH_PI = PI * SEVENTH;
- const EIGHTH_PI = PI * EIGHTH;
- const TWELFTH_PI = PI * TWELFTH;
- const SIXTEENTH_PI = PI * SIXTEENTH;
- const THIRTY_SECONDTH_PI = PI * THIRTY_SECONDTH;
- const TAU = PI * TWO;
- const TWO_TAU = TAU * TWO;
- const HALF_TAU = PI;
- const THIRD_TAU = TAU * THIRD;
- const QUARTER_TAU = HALF_PI;
- const FIFTH_TAU = TAU * FIFTH;
- const SIXTH_TAU = THIRD_PI;
- const EIGHTH_TAU = QUARTER_PI;
- const TWELFTH_TAU = SIXTH_PI;
- const SIXTEENTH_TAU = EIGHTH_PI;
- const THIRTY_SECONDTH_TAU = SIXTEENTH_PI;
-
- const SQRT_3 = sqrt(THREE);
- const SQRT_4 = sqrt(FOUR);
- const SQRT_5 = sqrt(FIVE);
-
- const PHI = (1 + sqrt(5)) * 0.5;
- const GOLDEN_ANGLE = 1 / (PHI * PHI);
-
- const COLOR_BLACK = hsl(0, 0, 0);
- const COLOR_WHITE = hsl(0, 0, 100);
- const COLOR_RED = hsl(0, 100, 50);
- const COLOR_ORANGE = hsl(30, 100, 50);
- const COLOR_YELLOW = hsl(60, 100, 50);
- const COLOR_GREEN = hsl(120, 100, 50);
- const COLOR_CYAN = hsl(180, 100, 50);
- const COLOR_BLUE = hsl(240, 100, 50);
- const COLOR_PURPLE = hsl(280, 100, 50);
- const COLOR_MAGENTA = hsl(300, 100, 50);
-
- const TEXTALIGN_LEFT = 'left';
- const TEXTALIGN_CENTER = 'center';
- const TEXTALIGN_RIGHT = 'right';
- const TEXTBASELINE_TOP = 'top';
- const TEXTBASELINE_MIDDLE = 'middle';
- const TEXTBASELINE_BOTTOM = 'bottom';
-
- let _defaulCanvasOptions = {
- autoClear: false,
- autoCompensate: true,
- autoPushPop: false,
- canvas: true,
- centered: false,
- desynchronized: false,
- width: null,
- height: null
- };
- let _canvasOptions = {};
- let canvas = document.getElementById('canvas');
- if(canvas === null) {
- canvas = document.createElement('canvas');
- canvas.id = 'canvas';
- document.body.appendChild(canvas);
- }
- let ctx = canvas.getContext('2d', {
- desynchronized: window.canvasOptions && window.canvasOptions.desynchronized !== undefined ?
- window.canvasOptions.desynchronized : _defaulCanvasOptions.desynchronized
- // preserveDrawingBuffer: true // WebGL
- });
- const _originalCtx = ctx;
- let _anim, _lastCanvasTime, canvasFrameRate, frameCount, width, height, width_half, height_half, width_quarter, height_quarter;
- let _canvasCurrentlyCentered = false;
- let mouseIn = false, mouseDown = false, mouseMove = null, mousePos = null, mousePosPrev = null;
-
- function updateMouse(e) { // Modified from p5.js
- if(e && !e.clientX) {
- e = e.touches ? e.touches[0] : (e.changedTouches ? e.changedTouches[0] : e);
- }
- let rect = canvas.getBoundingClientRect();
- let sx = canvas.scrollWidth / width;
- let sy = canvas.scrollHeight / height;
- let x = (e.clientX - rect.left) / sx;
- let y = (e.clientY - rect.top) / sy;
- if(x < 0) x = 0;
- else if(x > width) x = width;
- if(y < 0) y = 0;
- else if(y > height) y = height;
- if(mousePos) {
- mousePosPrev.set(mousePos);
- mousePos.set(x, y);
- }
- // return { x, y, winX: e.clientX, winY: e.clientY, id: e.identifier };
- }
-
- // let mouseIn = false, mouseDown = false, mouseMove = null, mousePos = { x: 0, y: 0 };
- // function updateMouse(e) {
- // if(e && !e.clientX) {
- // e = e.touches ? e.touches[0] : (e.changedTouches ? e.changedTouches[0] : e);
- // }
- // const { innerWidth: width, innerHeight: height } = window;
- // uniforms.mouse.value.set(e.clientX / width, 1 - e.clientY / height);
- // }
-
- // [
- // [ 'mouseenter', e => mouseIn = true ],
- // [ 'mouseleave', e => (mouseIn = false, mouseDown = false) ],
- // [ 'mousemove', e => (mouseIn = true, mouseMove = e.timeStamp) ],
- // [ 'mousedown', e => (mouseIn = true, mouseDown = true) ],
- // [ 'mouseup', e => mouseDown = false ],
- // [ 'touchstart', e => mouseIn = true ],
- // [ 'touchend', e => (mouseIn = false, mouseDown = false) ],
- // [ 'touchcancel', e => (mouseIn = false, mouseDown = false) ],
- // [ 'touchmove', e => (mouseIn = true, mouseMove = e.timeStamp) ]
- // ].forEach(([ eventName, cb ]) => document.body.addEventListener(eventName, e => {
- // updateMouse(e);
- // cb(e);
- // }));
-
- canvas.addEventListener('mouseenter', e => (updateMouse(e), mouseIn = true));
- canvas.addEventListener('mouseleave', e => (updateMouse(e), mouseIn = false, mouseDown = false));
- canvas.addEventListener('mousemove', e => (updateMouse(e), mouseIn = true, mouseMove = e.timeStamp));
- canvas.addEventListener('mousedown', e => (updateMouse(e), mouseIn = true, mouseDown = true));
- canvas.addEventListener('mouseup', e => (updateMouse(e), mouseDown = false));
- canvas.addEventListener('touchstart', e => (updateMouse(e), mouseIn = true));
- canvas.addEventListener('touchend', e => (updateMouse(e), mouseIn = false, mouseDown = false));
- canvas.addEventListener('touchcancel', e => (updateMouse(e), mouseIn = false, mouseDown = false));
- canvas.addEventListener('touchmove', e => (updateMouse(e), mouseIn = true));
- window.addEventListener('resize', _resizeCanvas);
- window.addEventListener('load', () => {
- mousePos = createVector();
- mousePosPrev = createVector();
- Object.assign(
- _canvasOptions,
- _defaulCanvasOptions,
- 'canvasOptions' in window ? window.canvasOptions : {}
- );
- if(_canvasOptions.canvas === false) {
- document.body.removeChild(canvas);
- }
- _resizeCanvas();
- if('setup' in window) {
- window.setup();
- }
- frameCount = 0;
- _anim = requestAnimationFrame(_draw);
- });
-
- function _draw(timestamp) {
- frameCount++;
- canvasFrameRate = 1000.0 / (timestamp - _lastCanvasTime);
- _lastCanvasTime = timestamp;
- ctx = _originalCtx;
- _canvasOptions.autoClear && clear(null);
- if(_canvasOptions.autoPushPop) {
- push();
- _canvasOptions.centered && (_canvasCurrentlyCentered = true) && translateCenter();
- _canvasOptions.autoCompensate && compensateCanvas();
- }
- 'draw' in window && window.draw(timestamp);
- _canvasOptions.autoPushPop && pop();
- _canvasCurrentlyCentered = false;
- _anim = requestAnimationFrame(_draw);
- }
-
- function _resizeCanvas(specificCanvas) {
- // if(_canvasOptions.width === null)
- width = canvas.width = _canvasOptions.width !== null ? _canvasOptions.width : window.innerWidth;
- height = canvas.height = _canvasOptions.height !== null ? _canvasOptions.height : window.innerHeight;
- width_quarter = (width_half = width * HALF) * HALF;
- height_quarter = (height_half = height * HALF) * HALF;
- ctx.fillStyle = 'hsl(0, 0%, 100%)';
- ctx.strokeStyle = 'hsl(0, 0%, 100%)';
- if('onResize' in window) {
- window.onResize();
- }
- }
-
- function clear(x, y, w, h) {
- if(x !== undefined && typeof x === 'number') {
- ctx.clearRect(x, y, w, h);
- }
- else if(_canvasOptions.centered && _canvasCurrentlyCentered/* && x !== null */) {
- ctx.clearRect(-width_half, -height_half, width, height);
- }
- else {
- ctx.clearRect(0, 0, width, height);
- }
- }
-
- function background(a) {
- push();
- if(typeof a !== 'number') {
- fillStyle(a);
- }
- if(_canvasOptions.centered && _canvasCurrentlyCentered) {
- ctx.fillRect(-width_half, -height_half, width, height);
- }
- else {
- ctx.fillRect(0, 0, width, height);
- }
- pop();
- }
-
- function globalAlpha(alpha = ctx.globalAlpha) {
- return ctx.globalAlpha = alpha;
- }
-
- function fillStyle(...args) {
- if(args.length === 1) {
- let a = args[0];
- if(typeof a === 'string' || a instanceof CanvasGradient || a instanceof CanvasPattern) {
- ctx.fillStyle = args[0];
- }
- }
- return ctx.fillStyle;
- }
-
- function lineWidth(w) {
- if(typeof w === 'number') {
- ctx.lineWidth = w;
- }
- return ctx.lineWidth;
- }
-
- // "butt" || "round" || "square";
- function lineCap(style = 'butt') {
- ctx.lineCap = style;
- }
-
- // "bevel" || "round" || "miter"
- function lineJoin(style) {
- ctx.lineJoin = style;
- }
-
- function miterLimit(value = 10) {
- ctx.miterLimit = value;
- }
-
- function strokeStyle(...args) {
- if(args.length === 1) {
- let a = args[0];
- if(typeof a === 'string' || a instanceof CanvasGradient) {
- ctx.strokeStyle = a;
- }
- }
- else if(args.length === 2) {
- strokeStyle(args[0]);
- lineWidth(args[1]);
- }
- return ctx.strokeStyle;
- }
-
- function lerpRGB(...args) {
- let r1 = 255;
- let b1 = 255;
- let g1 = 255;
- let a1 = 1;
- let r2 = 0;
- let g2 = 0;
- let b2 = 0;
- let a2 = 1;
- let t = 0.5;
- if(args.length === 3) {
- if(Array.isArray(args[0]) && Array.isArray(args[1])) {
- return lerpRGB(...args[0], ...args[1], args[2]);
- }
- [
- { r: r1 = 255, b: b1 = 255, g: g1 = 255, a: a1 = 1 },
- { r: r2 = 0, b: b2 = 0, g: g2 = 0, a: a2 = 1 },
- t
- ] = args;
- }
- else if(args.length === 7) {
- [
- r1, g1, b1,
- r2, g2, b2,
- t
- ] = args;
- }
- else if(args.length === 9) {
- [
- r1, g1, b1, a1,
- r2, g2, b2, a2,
- t
- ] = args;
- }
- else if(args.length === 2 && Array.isArray(args[0])) {
- if(args[0].length === 2) {
- return lerpRGB(...args[0], args[1]);
- }
- // TODO: Allow (possibly weighted) lerping between n-count RGBs at specified positions
- }
- else {
- return { r: 127.5, g: 127.5, b: 127.5, a: 1 };
- }
- let r = lerp(r1, r2, t);
- let g = lerp(g1, g2, t);
- let b = lerp(b1, b2, t);
- let a = lerp(a1, a2, t);
- return { r, g, b, a };
- }
-
- function hsl(hue, sat, light, alpha = 1) {
- if(typeof hue !== 'number') {
- if(Array.isArray(hue)) {
- [ hue, sat, light, alpha = alpha ] = hue;
- }
- else if('h' in hue) {
- ({ h: hue, s: sat, l: light, a: alpha = alpha } = hue);
- }
- }
- hue = hue % 360;
- if(hue < 0) {
- hue += 360;
- }
- return `hsl(${hue} ${sat}% ${light}% / ${alpha})`;
- }
-
- function parseHSL(input) {
- if(typeof input !== 'string') {
- return input;
- }
- let result = input.match(/hsla?\(([\d.]+)\s*,?\s*([\d.]+)%\s*,?\s*([\d.]+)%\s*[/,]?\s*([\d.]*)?\)/);
- if(result) {
- let [ i, h, s, l, a ] = result;
- return { input, h, s, l, a };
- }
- return null;
- }
-
- function setHueHSL(input, val) {
- if(val === undefined) return input;
- let p = parseHSL(input);
- p.h = val;
- return hsl(p);
- }
-
- function rotateHSL(input, amt = 90) {
- if(amt === 0) return input;
- let p = parseHSL(input);
- p.h += amt;
- return hsl(p);
- }
-
- function saturateHSL(input, amt = 0.1) {
- if(amt === 0) return input;
- let p = parseHSL(input);
- p.s *= 1 + amt;
- return hsl(p);
- }
-
- function lightenHSL(input, amt = 0.1) {
- if(amt === 0) return input;
- let p = parseHSL(input);
- p.l *= 1 + amt;
- return hsl(p);
- }
-
- function rgb(r = 255, g = 255, b = 255, a = 1) {
- if(typeof r !== 'number' && 'r' in r) {
- ({ r = 255, g = 255, b = 255, a = 1 } = r);
- }
- return `rgba(${r}, ${g}, ${b}, ${a})`;
- }
-
- function fill(...args) {
- if(args.length) {
- fillStyle(...args);
- }
- ctx.fill();
- }
-
- function stroke(...args) {
- if(args.length) {
- strokeStyle(...args);
- }
- ctx.stroke();
- }
-
- function clip() {
- ctx.clip();
- }
-
- function createLinearGradient(x1 = -100, y1 = -100, x2 = 100, y2 = 100) {
- // if(typeof x1 !== 'number') {
- // if('x' in x1) {
-
- // }
- // }
- return ctx.createLinearGradient(x1, y1, x2, y2);
- }
-
- function createRadialGradient(x1 = 0, y1 = 0, r1 = 0, x2 = 0, y2 = 0, r2 = 200) {
- return ctx.createRadialGradient(x1, y1, r1, x2, y2, r2);
- }
-
- function drawImage(img, x = 0, y = 0, ...args) {
- ctx.drawImage(img, x, y, ...args);
- }
-
- function strokeText(str = 'Hello world', x = 0, y = 0) {
- ctx.strokeText(str, x, y);
- }
-
- function fillText(str = 'Hello world', x = 0, y = 0) {
- ctx.fillText(str, x, y);
- }
-
- function strokeFillText(str = 'Hello world', x = 0, y = 0) {
- strokeText(str, x, y);
- fillText(str, x, y);
- }
-
- function fillStrokeText(str = 'Hello world', x = 0, y = 0) {
- fillText(str, x, y);
- strokeText(str, x, y);
- }
-
- function measureText(...args) {
- return ctx.measureText(...args);
- }
-
- // ctx.textAlign = "left" || "right" || "center" || "start" || "end";
- function textAlign(str = 'left') {
- ctx.textAlign = str;
- }
-
- // ctx.textBaseline = "top" || "hanging" || "middle" || "alphabetic" || "ideographic" || "bottom";
- function textBaseline(str = 'left') {
- if(str === 'center') str = 'middle';
- ctx.textBaseline = str;
- }
-
- function push() {
- ctx.save();
- }
-
- function pop() {
- ctx.restore();
- }
-
- function resetTransform() {
- ctx.resetTransform();
- }
-
- function translate(x = 0, y = 0) {
- if(typeof x === 'number') {
- ctx.translate(x, y);
- }
- else if('x' in x) {
- ctx.translate(x.x, x.y);
- }
- }
-
- function translateCenter(x = 0, y = 0) {
- ctx.translate(width_half + x, height_half + y);
- }
-
- function rotate(rot, offsetX, offsetY) {
- rot = rot % TAU;
- if(offsetX === undefined) {
- ctx.rotate(rot);
- }
- else if(typeof offsetX !== 'number') {
- if('x' in offsetX) {
- ctx.translate(offsetX.x, offsetX.y);
- ctx.rotate(rot);
- ctx.translate(-offsetX.x, -offsetX.y);
- }
- }
- else {
- ctx.translate(offsetX, offsetY);
- ctx.rotate(rot);
- ctx.translate(-offsetX, -offsetY);
- }
- }
-
- function scale(x = 1, y = x) {
- ctx.scale(x, y);
- }
-
- function shearX(rad) {
- ctx.transform(1, 0, tan(rad), 1, 0, 0);
- }
-
- function shearY(rad) {
- ctx.transform(1, tan(rad), 0, 1, 0, 0);
- }
-
- function compensateCanvas() {
- let offX = 0;
- let offY = 0;
- if(width % 2) offX += 0.5;
- if(height % 2) offY += 0.5;
- if(offX || offY) {
- translate(offX, offY);
- }
- }
-
- const compOper = {
- default: 'source-over', sourceOver: 'source-over', sourceIn: 'source-in',
- sourceOut: 'source-out', sourceAtop: 'source-atop', destinationOver: 'destination-over',
- destinationIn: 'destination-in', destinationOut: 'destination-out', destinationAtop: 'destination-atop',
- lighter: 'lighter', copy: 'copy', xor: 'xor',
- multiply: 'multiply', screen: 'screen', overlay: 'overlay',
- darken: 'darken', lighten: 'lighten', colorDodge: 'color-dodge',
- colorBurn: 'color-burn', hardLight: 'hard-light', softLight: 'soft-light',
- difference: 'difference', exclusion: 'exclusion', hue: 'hue',
- saturation: 'saturation', color: 'color', luminosity: 'luminosity',
- source: {
- over: 'source-over', in: 'source-in', out: 'source-out',
- atop: 'source-atop'
- },
- destination: {
- over: 'destination-over', in: 'destination-in', out: 'destination-out',
- atop: 'destination-atop'
- },
- light: {
- hard: 'hard-light', soft: 'soft-light'
- }
- };
-
-
- function compositeOperation(type = compOper.default) { // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
- ctx.globalCompositeOperation = type;
- }
-
- // const filters = [
- // [ 'url', [ 'url' ] ],
- // [ 'blur', [ 'length' ] ],
- // [ 'brightness', [ 'percentage' ] ],
- // [ 'contrast', [ 'percentage' ] ]
- // ];
-
- function filter(filterFuncs = 'none') {
- ctx.filter = filterFuncs;
- }
-
- function beginPath() {
- ctx.beginPath();
- }
-
- function moveTo(x, y) {
- if(typeof x === 'number') {
- ctx.moveTo(x, y);
- }
- else if('x' in x) {
- ctx.moveTo(x.x, x.y);
- }
- }
-
- function lineTo(x, y) {
- if(typeof x === 'number') {
- ctx.lineTo(x, y);
- }
- else if('x' in x) {
- ctx.lineTo(x.x, x.y);
- }
- }
-
- function quadraticCurveTo(cpX, cpY, x, y) {
- // ctx.quadraticCurveTo(cpX, cpY, x, y);
- let a = [];
- let b = [];
- if(typeof cpX === 'number') {
- a = [ cpX, cpY ];
- if(typeof x === 'number') {
- b = [ x, y ];
- }
- else if('x' in x) {
- b = x.xy;
- }
- }
- else if('x' in cpX) {
- a = cpX.xy;
- if(typeof cpY === 'number') {
- b = [ cpY, x ];
- }
- else if('x' in cpY) {
- b = cpY.xy;
- }
- }
- ctx.quadraticCurveTo(a[0], a[1], b[0], b[1]);
- }
-
- function bezierCurveTo(cp1X, cp1Y, cp2X, cp2Y, x, y) {
- let a = [];
- let b = [];
- let c = [];
- if(typeof cp1X === 'number') {
- a = [ cp1X, cp1Y ];
- if(typeof cp2X === 'number') {
- b = [ cp2X, cp2Y ];
- if(typeof x === 'number') {
- c = [ x, y ];
- }
- else if('x' in x) {
- c = x.xy;
- }
- }
- else if('x' in cp2X) {
- b = cp2X.xy;
- if(typeof cp2Y === 'number') {
- c = [ cp2Y, x ];
- }
- else if('x' in cp2Y) {
- c = cp2Y.xy;
- }
- }
- }
- else if('x' in cp1X) {
- a = cp1X.xy;
- if(typeof cp1Y === 'number') {
- b = [ cp1Y, cp2X ];
- if(typeof cp2Y === 'number') {
- c = [ cp2Y, x ];
- }
- else if('x' in cp2Y) {
- c = cp2Y.xy;
- }
- }
- else if('x' in cp1Y) {
- b = cp1Y.xy;
- if(typeof cp2X === 'number') {
- c = [ cp2X, cp2Y ];
- }
- else if('x' in cp2X) {
- c = cp2X.xy;
- }
- }
- }
- ctx.bezierCurveTo(a[0], a[1], b[0], b[1], c[0], c[1]);
- }
-
- function closePath() {
- ctx.closePath();
- }
-
- function point(x = 0, y = 0, r = 0, g = 0, b = 0, a = 255, doPut_ = true) {
- // let imgData = ctx.createImageData(1, 1);
- // imgData.data[0] = r;
- // imgData.data[1] = g;
- // imgData.data[2] = b;
- // imgData.data[3] = a;
- // if(doPut_) {
- // ctx.putImageData(imgData, x, y);
- // }
- // return imgData;
- }
-
- function line(x = 0, y = 0, x_ = 0, y_ = 0) {
- if(typeof x === 'number') {
- moveTo(x, y);
- lineTo(x_, y_);
- }
- else if('x' in x) {
- moveTo(x);
- lineTo(y, x_);
- }
- }
-
- function vertices(...verts) {
- if(verts.length === 0) return;
- else if(verts.length === 1 && Array.isArray(verts[0])) {
- verts = verts[0];
- }
- for(let i = 0; i < verts.length; i++) {
- let n = verts[i];
- let x = 0;
- let y = 0;
- if(Array.isArray(n)) {
- ([ x, y ] = n);
- }
- else if(n instanceof Vector || ('x' in n && 'y' in n)) {
- ({ x, y } = n);
- }
- lineTo(x, y);
- }
- }
-
- function arcTo(x1 = 0, y1 = 0, x2 = 0, y2 = 0, radius = 50) {
- ctx.arcTo(x1, y1, x2, y2, radius);
- }
-
- function rect(x = 0, y = 0, w = 10, h = w, r = 0) {
- if(r > 0) {
- moveTo(x + r, y);
- arcTo(x + w, y, x + w, y + h, r);
- arcTo(x + w, y + h, x, y + h, r);
- arcTo(x, y + h, x, y, r);
- arcTo(x, y, x + w, y, r);
- closePath();
- }
- else {
- ctx.rect(x, y, w, h);
- }
- }
-
- function arc(x = 0, y = 0, radius = 50, startAngle = 0, endAngle = Math.PI * 2, anticlockwise = false) {
- if(radius < 0) radius = 0;
- ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);
- }
-
- function circle(x = 0, y = undefined, rX = 20, rY = undefined) {
- if(typeof x !== 'number' && 'x' in x) {
- if(y !== undefined) {
- rX = y;
- }
- y = x.y;
- x = x.x;
- }
- else if(y === undefined) {
- y = 0;
- }
- if(typeof rX !== 'number' && 'x' in rX) {
- rY = rX.y;
- rX = rX.x;
- }
- ctx.moveTo(x + rX, y);
- if(rY !== undefined) {
- ellipse(x, y, rX, rY);
- }
- else {
- if(rX < 0) rX = 0;
- ctx.arc(x, y, rX, 0, TAU);
- }
- }
-
- function ellipse(x = 0, y = 0, rX = 50, rY = 50, rot = 0, angStart = 0, angEnd = Math.PI * 2, antiCw = false) {
- if(rX < 0) rX = 0;
- if(rY < 0) rY = 0;
- ctx.ellipse(x, y, rX, rY, rot, angStart, angEnd, antiCw);
- }
-
- function regularPolygon(sides, radius = 50, rotation = 0) {
- let circumference = TAU * radius;
- let count = min(sides, circumference);
- for(let i = 0; i < count; i++) {
- let t = i / count * TAU + rotation;
- let x = cos(t) * radius;
- let y = sin(t) * radius;
- if(i === 0) {
- ctx.moveTo(x, y);
- }
- else {
- ctx.lineTo(x, y);
- }
- }
- ctx.closePath();
- }
-
- function genRegularPolygon(sides = 3, radius = 50, rotation = 0) {
- let iSizes = 1 / sides * TAU;
- let data = {
- sides,
- radius,
- rotation,
- points: []
- };
- for(let i = 0; i < sides; i++) {
- let t = i * iSizes + rotation;
- let x = cos(t) * radius;
- let y = sin(t) * radius;
- let point = createVector(x, y);
- Object.assign(point, { i, t });
- data.points.push(point);
- }
- return data;
- }
-
- function getCodePenID() {
- if(_codepenIDRegex.test(window.location.href)) {
- return _codepenIDRegex.exec(window.location.href)[1];
- }
- else {
- let metas = document.getElementsByTagName('link');
- for(let i = 0; i < metas.length; i++) {
- let m = metas[i];
- if(m.getAttribute('rel') == 'canonical') {
- let id = _codepenIDRegex.exec(m.getAttribute('href'));
- if(id) {
- return id[1];
- }
- }
- }
- }
- }
-
- function isPreviewEmbed() {
- return location.href.includes('/fullcpgrid/');
- }
-
- function loadImage(url) {
- return new Promise((resolve, reject) => {
- let img = new Image();
- img.crossOrigin = 'Anonymous';
- img.onload = () => resolve(img);
- img.src = url;
- });
- }
-
- loadImage.alca = function(urlPart) {
- return loadImage('https://alca.tv/static/' + urlPart);
- };
-
- loadImage.alca.pen = function(urlPart) {
- return loadImage.alca('codepen/' + urlPart);
- };
-
- loadImage.alca.pen._ = function(urlPart) {
- return loadImage.alca.pen(`pens/${getCodePenID()}/${urlPart}`);
- };
-
- function loadVideo(url) {
- return new Promise((resolve, reject) => {
- let vid = document.createElement('video');
- vid.crossOrigin = 'anonymous';
- vid.onloadeddata = () => resolve(vid);
- vid.preload = true;
- vid.muted = true;
- vid.src = url;
- vid.load();
- });
- }
-
- loadVideo.alca = function(urlPart) {
- return loadVideo('https://alca.tv/static/' + urlPart);
- };
-
- loadVideo.alca.pen = function(urlPart) {
- return loadVideo.alca('codepen/' + urlPart);
- };
-
- loadVideo.alca.pen._ = function(urlPart) {
- return loadVideo.alca.pen(`pens/${getCodePenID()}/${urlPart}`);
- };
-
- function loadData(url) {
- return fetch(url);
- }
-
- loadData.alca = function(urlPart) {
- return loadData('https://alca.tv/static/' + urlPart);
- };
-
- function loadText(url) {
- return loadData(url)
- .then(res => res.text());
- }
-
- loadText.alca = function(urlPart) {
- return loadText('https://alca.tv/static/' + urlPart);
- };
-
- function loadJSON(url) {
- return loadData(url)
- .then(res => res.json());
- }
-
- loadJSON.alca = function(urlPart) {
- return loadJSON('https://alca.tv/static/' + urlPart);
- };
-
- function getImageData(img, ...args) {
- if(img instanceof Image) {
- let canvas = document.createElement('canvas');
- let ctx = canvas.getContext('2d');
- Object.assign(canvas, { width: img.width, height: img.height });
- ctx.drawImage(img, 0, 0);
- let data;
- if(args.length) {
- data = ctx.getImageData(...args);
- }
- else {
- data = ctx.getImageData(0, 0, img.width, img.height);
- }
- return Object.assign(data, { canvas, ctx });
- }
- else {
- return ctx.getImageData(img, ...args);
- }
- }
-
- function xyToI(x, y, w, h) {
- if(typeof x !== 'number' && 'x' in x) {
- h = w;
- w = y;
- ({ x, y } = x);
- }
- if(w === undefined) w = 1;
- // if(h === undefined) h = Infinity;
- return x + w * y;
- }
-
- function iToXY(i, w, h) {
- return createVector(i % w, floor(i / w));
- }
-
- function random(low = 1, high = null) {
- if(Array.isArray(low)) {
- return low[floor(Math.random() * low.length)];
- }
- if(high === null) {
- return Math.random() * low;
- }
- return Math.random() * (high - low) + low;
- }
-
- let _randomGaussianPrevious = false;
- let _randomGaussianY2 = 0;
-
- // https://github.com/processing/p5.js/blob/5a46133fdc3e8c42fda1c1888864cf499940d86d/src/math/random.js#L166
- // Offset, deviation
- function randomGaussian(mean = 0, sd = 1) {
- let y1, x1, x2, w;
- if(_randomGaussianPrevious) {
- y1 = _randomGaussianY2;
- _randomGaussianPrevious = false;
- }
- else {
- do {
- x1 = random(2) - 1;
- x2 = random(2) - 1;
- w = x1 * x1 + x2 * x2;
- } while (w >= 1);
- w = sqrt(-2 * log(w) / w);
- y1 = x1 * w;
- _randomGaussianY2 = x2 * w;
- _randomGaussianPrevious = true;
- }
- return y1 * (sd || 1) + mean;
- }
-
- function map(n, a, b, c, d) {
- return (n - a) * (d - c) / (b - a) + c;
- }
-
- function constrain(n, mn, mx) {
- return max(mn, min(mx, n));
- }
-
- function lerp(start, stop, amt = 0.5) {
- if(typeof start !== 'number') {
- return Vector.lerp(start, stop, amt);
- }
- return amt * (stop - start) + start;
- }
-
- function _distSq(x1, y1, x2, y2) {
- let _x = x2 - x1;
- let _y = y2 - y1;
- return _x * _x + _y * _y;
- }
-
- function distSq(x1, y1, x2, y2) {
- if(x1 === undefined || y1 === undefined || x2 === undefined || y2 === undefined) {
- return 0;
- }
- else if(typeof x1 === 'number') {
- if(x1 === x1) {
- return _distSq(x1, y1, x2, y2);
- }
- return 0;
- }
- else if('x' in x1) {
- return _distSq(x1.x, x1.y, y1.x, y1.y);
- }
- return 0;
- }
-
- function dist(x1, y1, x2, y2) {
- let d = distSq(x1, y1, x2, y2);
- if(d === 0) {
- return 0;
- }
- return sqrt(d);
- }
-
- function cos(input, mult = null) {
- let c = Math.cos(input % TAU);
- if(mult === null) {
- return c;
- }
- return c * mult;
- }
-
- function sin(input, mult = null) {
- let s = Math.sin(input % TAU);
- if(mult === null) {
- return s;
- }
- return s * mult;
- }
-
-
- function createVector(x, y, z) {
- return new Vector(x, y, z);
- }
-
- class Vector {
- constructor(x = 0, y = 0, z = 0) {
- this.x = x;
- this.y = y;
- this.z = z;
- }
- toString() {
- let { x, y, z } = this;
- return `{ x: ${x}, y: ${y}, z: ${z} }`;
- }
-
- static center() {
- return createVector(width_half, height_half);
- }
-
- static from(v, ...args) {
- if(v === undefined) {
- return createVector();
- }
- else if(Array.isArray(v)) {
- return createVector(...v);
- }
- else if(typeof v === 'object') {
- return createVector(v.x, v.y, v.z);
- }
- else if(typeof v === 'number') {
- return createVector(v, ...args);
- }
- }
-
- static fromAngle(angle, mult = 1) {
- let v = createVector(cos(angle), sin(angle));
- if(mult !== 1) v.mult(mult);
- return v;
- }
-
- static random2D(angle = true, mult = 1) {
- let v;
- if(angle === true) {
- v = Vector.fromAngle(random(TAU));
- }
- else {
- v = createVector(random(-1, 1), random(-1, 1));
- }
- if(typeof angle === 'number') {
- v.mult(angle);
- }
- else if(mult !== 1) {
- v.mult(mult);
- }
- return v;
- }
-
- static lerp(start, stop, amt = 0.5, apply = false) {
- let x = start.x === stop.x ? start.x : lerp(start.x, stop.x, amt);
- let y = start.y === stop.y ? start.y : lerp(start.y, stop.y, amt);
- let z = start.z === undefined ? stop.z === undefined ? 0 : stop.z : start.z === stop.z ? start.z : lerp(start.z, stop.z, amt);
- if(apply) {
- return start.set(x, y, z);
- }
- return createVector(x, y, z);
- }
-
- get xy() { return [ this.x, this.y ]; }
- get yx() { return [ this.y, this.x ]; }
- get xz() { return [ this.x, this.z ]; }
- get zx() { return [ this.z, this.x ]; }
- get yz() { return [ this.y, this.z ]; }
- get zy() { return [ this.z, this.y ]; }
- get xyz() { return [ this.x, this.y, this.z ]; }
- get xzy() { return [ this.x, this.z, this.y ]; }
- get yxz() { return [ this.y, this.x, this.z ]; }
- get yzx() { return [ this.y, this.z, this.x ]; }
- get zyx() { return [ this.z, this.y, this.x ]; }
- get zxy() { return [ this.z, this.x, this.y ]; }
-
- get xyObject() { return { x: this.x, y: this.y }; }
- get xzObject() { return { x: this.x, z: this.z }; }
- get yzObject() { return { y: this.y, z: this.z }; }
- get xyzObject() { return { x: this.x, y: this.y, z: this.z }; }
-
- copy() {
- return createVector(this.x, this.y, this.z);
- }
-
- get _() {
- return this.copy();
- }
-
- equals(vec) {
- return this.x === vec.x && this.y === vec.y;
- }
-
- equals3D(vec = {}) {
- return this.x === vec.x && this.y === vec.y && this.z === vec.z;
- }
-
- draw() {
- point(this.x, this.y);
- }
-
- set(x = this.x, y = this.y, z = this.z) {
- if(x instanceof Vector) {
- this.x = x.x;
- this.y = x.y;
- this.z = x.z;
- return this;
- }
- this.x = x;
- this.y = y;
- this.z = z;
- return this;
- }
- setX(x = this.x) {
- if(x instanceof Vector) {
- this.x = x.x;
- return this;
- }
- this.x = x;
- return this;
- }
- setY(y = this.y) {
- if(y instanceof Vector) {
- this.y = y.y;
- return this;
- }
- this.y = y;
- return this;
- }
- setZ(z = this.z) {
- if(z instanceof Vector) {
- this.z = z.z;
- return this;
- }
- this.z = z;
- return this;
- }
- setXY(x = this.x, y = this.y) {
- if(x instanceof Vector) {
- this.x = x.x;
- this.y = x.y;
- return this;
- }
- this.x = x;
- this.y = y;
- return this;
- }
- setYZ(y = this.y, z = this.z) {
- if(y instanceof Vector) {
- this.y = y.y;
- this.z = y.z;
- return this;
- }
- this.y = y;
- this.z = z;
- return this;
- }
- setXZ(x = this.x, z = this.y) {
- if(x instanceof Vector) {
- this.x = x.x;
- this.z = x.z;
- return this;
- }
- this.x = x;
- this.z = z;
- return this;
- }
- setZX(...args) {
- return this.setXZ(...args);
- }
-
- add(x = 0, y = x, z = 0) {
- if(x instanceof Vector) {
- this.x += x.x;
- this.y += x.y;
- this.z += x.z;
- return this;
- }
- this.x += x;
- this.y += y;
- this.z += z;
- return this;
- }
- addX(n = 0) {
- if(n instanceof Vector) {
- this.x += n.x;
- return this;
- }
- this.x += n;
- return this;
- }
- addY(n = 0) {
- if(n instanceof Vector) {
- this.y += n.y;
- return this;
- }
- this.y += n;
- return this;
- }
- addZ(n = 0) {
- if(n instanceof Vector) {
- this.z += n.z;
- return this;
- }
- this.z += n;
- return this;
- }
- sub(x = 0, y = x, z = 0) {
- if(x instanceof Vector) {
- this.x -= x.x;
- this.y -= x.y;
- this.z -= x.z;
- return this;
- }
- this.x -= x;
- this.y -= y;
- this.z -= z;
- return this;
- }
- subX(n = 0) {
- if(n instanceof Vector) {
- this.x -= n.x;
- return this;
- }
- this.x -= n;
- return this;
- }
- subY(n = 0) {
- if(n instanceof Vector) {
- this.y -= n.y;
- return this;
- }
- this.y -= n;
- return this;
- }
- subZ(n = 0) {
- if(n instanceof Vector) {
- this.z -= n.z;
- return this;
- }
- this.z -= n;
- return this;
- }
- mult(x = 1, y = x, z = x) {
- if(x instanceof Vector) {
- this.x *= x.x;
- this.y *= x.y;
- this.z *= x.z;
- return this;
- }
- this.x *= x;
- this.y *= y;
- this.z *= z;
- return this;
- }
- multX(n = 1) {
- if(n instanceof Vector) {
- this.x *= n.x;
- return this;
- }
- this.x *= n;
- return this;
- }
- multY(n = 1) {
- if(n instanceof Vector) {
- this.y *= n.y;
- return this;
- }
- this.y *= n;
- return this;
- }
- multZ(n = 1) {
- if(n instanceof Vector) {
- this.z *= n.z;
- return this;
- }
- this.z *= n;
- return this;
- }
- div(x = 1, y = x, z = x) {
- if(x instanceof Vector) {
- this.x /= x.x;
- this.y /= x.y;
- this.z /= x.z;
- return this;
- }
- this.x /= x;
- this.y /= y;
- this.z /= z;
- return this;
- }
- divX(n = 1) {
- if(n instanceof Vector) {
- this.x /= n.x;
- return this;
- }
- this.x /= n;
- return this;
- }
- divY(n = 1) {
- if(n instanceof Vector) {
- this.y /= n.y;
- return this;
- }
- this.y /= n;
- return this;
- }
- divZ(n = 1) {
- if(n instanceof Vector) {
- this.z /= n.z;
- return this;
- }
- this.z /= n;
- return this;
- }
-
- mod(x, y, z) {
- if(x === undefined) return this;
- else if(x instanceof Vector) {
- this.x %= x.x;
- this.y %= x.y;
- this.z %= x.z;
- return this;
- }
- this.x %= x;
- this.y %= y === undefined ? x : y;
- this.z %= z === undefined ? x : y;
- return this;
- }
- // TODO: modX, modY, modZ
-
- min(mX = this.x, mY = this.y, mZ = this.z) {
- if(mX instanceof Vector) {
- this.x = min(this.x, mX.x);
- this.y = min(this.y, mX.y);
- this.z = min(this.z, mX.z);
- return this;
- }
- this.x = min(this.x, mX);
- this.y = min(this.y, mY);
- this.z = min(this.z, mZ);
- return this;
- }
- max(mX = this.x, mY = this.y, mZ = this.z) {
- if(mX instanceof Vector) {
- this.x = max(this.x, mX.x);
- this.y = max(this.y, mX.y);
- this.z = max(this.z, mX.z);
- return this;
- }
- this.x = max(this.x, mX);
- this.y = max(this.y, mY);
- this.z = max(this.z, mZ);
- return this;
- }
- minX(n) {
- this.x = min(this.x, n instanceof Vector ? n.x : n);
- return this;
- }
- minY(n) {
- this.y = min(this.y, n instanceof Vector ? n.y : n);
- return this;
- }
- minZ(n) {
- this.z = min(this.z, n instanceof Vector ? n.z : n);
- return this;
- }
- maxX(n) {
- this.x = max(this.x, n instanceof Vector ? n.x : n);
- return this;
- }
- maxY(n) {
- this.y = max(this.y, n instanceof Vector ? n.y : n);
- return this;
- }
- maxZ(n) {
- this.z = max(this.z, n instanceof Vector ? n.z : n);
- return this;
- }
-
- heading() {
- return atan2(this.y, this.x);
- }
- rotate(a = 0) {
- // if(a === 0) {
- // return this;
- // }
- // let newHeading = this.heading() + a;
- // let mag = this.mag();
- // return this.set(cos(newHeading), sin(newHeading)).mult(mag);
- if(!a) {
- return this;
- }
- const c = cos(a);
- const s = sin(a);
- const { x, y } = this;
- this.x = x * c - y * s;
- this.y = x * s + y * c;
- return this;
- }
- rotateXY(a) {
- let v = new Vector(this.x, this.y).rotate(a);
- this.x = v.x;
- this.y = v.y;
- return this;
- }
- rotateYZ(a) {
- let v = new Vector(this.y, this.z).rotate(a);
- this.y = v.x;
- this.z = v.y;
- return this;
- }
- rotateZX(a) {
- let v = new Vector(this.z, this.x).rotate(a);
- this.z = v.x;
- this.x = v.y;
- return this;
- }
- magSq() {
- return this.x * this.x + this.y * this.y;
- }
- magSq3D() {
- return this.x * this.x + this.y * this.y + this.z * this.z;
- }
- mag() {
- return Math.sqrt(this.magSq());
- // return hypot(this.x, this.y);
- }
- mag3D() {
- return Math.sqrt(this.magSq3D());
- // return hypot(this.x, this.y);
- }
- normalize(mag = this.mag()) {
- return mag === 0 ? this : this.div(mag);
- }
- normalize3D(mag = this.mag3D()) {
- return mag === 0 ? this : this.div(mag);
- }
- setMag(mag) {
- return this.normalize().mult(mag);
- }
- setMag3D(mag) {
- return this.normalize3D().mult(mag);
- }
- limit(max) {
- const magSq = this.magSq();
- if(magSq > max * max) {
- this.div(sqrt(magSq));
- this.mult(max);
- }
- return this;
- }
- limit3D(max) {
- const magSq = this.magSq3D();
- if(magSq > max * max) {
- this.div(sqrt(magSq));
- this.mult(max);
- }
- return this;
- }
- dot(x = 0, y = 0) {
- if(x instanceof Vector) {
- return this.dot(x.x, x.y);
- }
- return this.x * x + this.y * y;
- }
- dot3D(x = 0, y = 0, z = 0) {
- if(x instanceof Vector) {
- return this.dot(x.x, x.y, x.z);
- }
- return this.x * x + this.y * y + this.z * z;
- }
- dist(x, y) {
- if(x instanceof Vector) {
- return x.copy().sub(this).mag();
- }
- else if(typeof x === 'object' && 'x' in x) {
- ({ x, y } = x);
- }
- return dist(this.x, this.y, x, y);
- }
- dist3D(v) {
- return v.copy().sub(this).mag3D();
- }
- lerp(stop, amt) {
- return Vector.lerp(this, stop, amt, true);
- }
- round() {
- this.x = round(this.x);
- this.y = round(this.y);
- this.z = round(this.z);
- return this;
- }
- floor() {
- this.x = floor(this.x);
- this.y = floor(this.y);
- this.z = floor(this.z);
- return this;
- }
- fastFloor() {
- this.x = ~~this.x;
- this.y = ~~this.y;
- this.z = ~~this.z;
- return this;
- }
- ceil() {
- this.x = ceil(this.x);
- this.y = ceil(this.y);
- this.z = ceil(this.z);
- return this;
- }
- }
-
-
- // Robert Penner - http://gizma.com/easing/
- // t: Current time
- // b: Start value
- // c: Change in value
- // d: Duration
-
- function linearTween /* simple linear tweening */ (t = 0.5, b = 0, c = 1, d = 1) { return c * t / d + b; }
- function easeInQuad /* quadratic easing in */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; return c * t * t + b; }
- function easeOutQuad /* quadratic easing out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; return -c * t * (t - 2) + b; }
- function easeInOutQuad /* quadratic easing in/out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d * 0.5; if(t < 1) return c * 0.5 * t * t + b; t--; return -c * 0.5 * (t * (t - 2) - 1) + b; }
- function easeInCubic /* cubic easing in */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; return c * t * t * t + b; }
- function easeOutCubic /* cubic easing out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; t--; return c * (t * t * t + 1) + b; }
- function easeInOutCubic /* cubic easing in/out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d * 0.5; if(t < 1) return c * 0.5 * t * t * t + b; t -= 2; return c * 0.5 * (t * t * t + 2) + b; }
- function easeInQuart /* quartic easing in */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; return c * t * t * t * t + b; }
- function easeOutQuart /* quartic easing out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; t--; return -c * (t * t * t * t - 1) + b; }
- function easeInOutQuart /* quartic easing in/out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d * 0.5; if(t < 1) return c * 0.5 * t * t * t * t + b; t -= 2; return -c * 0.5 * (t * t * t * t - 2) + b; }
- function easeInQuint /* quintic easing in */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; return c * t * t * t * t * t + b; }
- function easeOutQuint /* quintic easing out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; t--; return c * (t * t * t * t * t + 1) + b; }
- function easeInOutQuint /* quintic easing in/out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d * 0.5; if(t < 1) return c * 0.5 * t * t * t * t * t + b; t -= 2; return c * 0.5 * (t * t * t * t * t + 2) + b; }
- function easeInSine /* sinusoidal easing in */ (t = 0.5, b = 0, c = 1, d = 1) { return -c * cos(t / d * HALF_PI) + c + b; }
- function easeOutSine /* sinusoidal easing out */ (t = 0.5, b = 0, c = 1, d = 1) { return c * sin(t / d * HALF_PI) + b; }
- function easeInOutSine /* sinusoidal easing in/out */ (t = 0.5, b = 0, c = 1, d = 1) { return -c * 0.5 * (cos(PI * t / d) - 1) + b; }
- function easeInExpo /* exponential easing in */ (t = 0.5, b = 0, c = 1, d = 1) { return c * pow(2, 10 * (t / d - 1)) + b; }
- function easeOutExpo /* exponential easing out */ (t = 0.5, b = 0, c = 1, d = 1) { return c * (-pow(2, -10 * t / d ) + 1) + b; }
- function easeInOutExpo /* exponential easing in/out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d * 0.5; if(t < 1) return c * 0.5 * pow(2, 10 * (t - 1)) + b; t--; return c * 0.5 * (-pow(2, -10 * t) + 2) + b; }
- function easeInCirc /* circular easing in */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; return -c * (sqrt(1 - t * t) - 1) + b; }
- function easeOutCirc /* circular easing out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; t--; return c * sqrt(1 - t * t) + b; }
- function easeInOutCirc /* circular easing in/out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d * 0.5; if(t < 1) return -c * 0.5 * (sqrt(1 - t * t) - 1) + b; t -= 2; return c * 0.5 * (sqrt(1 - t * t) + 1) + b; }
-
- const ease = {
- linearTween,
- easeInQuad, easeOutQuad, easeInOutQuad,
- easeInCubic, easeOutCubic, easeInOutCubic,
- easeInQuart, easeOutQuart, easeInOutQuart,
- easeInQuint, easeOutQuint, easeInOutQuint,
- easeInSine, easeOutSine, easeInOutSine,
- easeInExpo, easeOutExpo, easeInOutExpo,
- easeInCirc, easeOutCirc, easeInOutCirc,
- in: { linear: linearTween, quad: easeInQuad, cubic: easeInCubic, quart: easeInQuart, quint: easeInQuint, sine: easeInSine, expo: easeInExpo, circ: easeInCirc },
- out: { linear: linearTween, quad: easeOutQuad, cubic: easeOutCubic, quart: easeOutQuart, quint: easeOutQuint, sine: easeOutSine, expo: easeOutExpo, circ: easeOutCirc },
- inOut: { linear: linearTween, quad: easeInOutQuad, cubic: easeInOutCubic, quart: easeInOutQuart, quint: easeInOutQuint, sine: easeInOutSine, expo: easeInOutExpo, circ: easeInOutCirc },
- linear: Object.assign(linearTween,
- { in: linearTween, out: linearTween, inOut: linearTween }),
- quad: { in: easeInQuad, out: easeOutQuad, inOut: easeInOutQuad },
- cubic: { in: easeInCubic, out: easeOutCubic, inOut: easeInOutCubic },
- quart: { in: easeInQuart, out: easeOutQuart, inOut: easeInOutQuart },
- quint: { in: easeInQuint, out: easeOutQuint, inOut: easeInOutQuint },
- sine: { in: easeInSine, out: easeOutSine, inOut: easeInOutSine },
- expo: { in: easeInExpo, out: easeOutExpo, inOut: easeInOutExpo },
- circ: { in: easeInCirc, out: easeOutCirc, inOut: easeInOutCirc }
- };
-
- function getTimeArray(timestamp = null) {
- if(timestamp === null) {
- timestamp = new Date();
- }
- else if(typeof timestamp === 'string' || typeof timestamp === 'number') {
- let parsedTimestamp = Date.parse(timestamp);
- if(!isNaN(parsedTimestamp)) {
- timestamp = new Date(parsedTimestamp);
- }
- else {
- throw new RangeError('Invalid Date');
- }
- }
- else if(!(timestamp instanceof Date)) {
- throw new TypeError('Unsupported timestamp');
- }
- let arr = [
- timestamp.getHours(),
- timestamp.getMinutes(),
- timestamp.getSeconds(),
- timestamp.getMilliseconds()
- ];
- return arr;
- }
-
- function getTimeArrayPadded(...opts) {
- return getTimeArray(...opts).map(n => `0${n}`.slice(-2));
- }
-
- function getTimeArraySmooth(...opts) {
- let arr = getTimeArray(...opts);
- let milliseconds = arr[3] / 1000;
- let seconds = (arr[2] + milliseconds) / 60;
- let minutes = (arr[1] + seconds) / 60;
- let hours = ((arr[0] % 12 || 12) + minutes) / 12;
- return [ hours, minutes, seconds, milliseconds ];
- }
-
- function loadWebFont(fontName) {
- if('WebFont' in window === false) {
- return Promise.reject('WebFont not available. Load using this script: https://cdnjs.cloudflare.com/ajax/libs/webfont/1.6.28/webfontloader.js');
- }
- if(fontName === '') {
- return Promise.resolve();
- }
- return new Promise((resolve, reject) => {
- let options = { fontactive: resolve };
- let providers = {};
- if(typeof fontName === 'string') {
- providers = { google: { families: [ fontName ] } };
- }
- else if(Array.isArray(fontName)) {
- providers = { google: { families: fontName } };
- }
- else {
- providers = fontName;
- }
- Object.assign(options, providers);
- WebFont.load(options);
- });
- }
-
- function isFontDefault() {
- return ctx.font === '10px sans-serif';
- }
-
- function font(fontStr, fallbackIfDefault) {
- if(fontStr !== undefined) {
- ctx.font = fontStr;
- if(fallbackIfDefault !== undefined && isFontDefault()) {
- ctx.font = fallbackIfDefault;
- }
- }
- return ctx.font;
- }
-