2025年3月17日 星期一 甲辰(龙)年 月十六 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Html+Div+Css(前端)

科技线条空间3D特效

时间:08-26来源:作者:点击数:26
在这里插入图片描述

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;
  • }
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门