12 |
13 |
14 |
19 |
20 |
--------------------------------------------------------------------------------
/example/svelte/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "svelte-app",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "build": "rollup -c",
6 | "dev": "rollup -c -w",
7 | "start": "sirv public"
8 | },
9 | "devDependencies": {
10 | "@rollup/plugin-commonjs": "^11.0.0",
11 | "@rollup/plugin-node-resolve": "^7.0.0",
12 | "rollup": "^1.20.0",
13 | "rollup-plugin-livereload": "^1.0.0",
14 | "rollup-plugin-svelte": "^5.0.3",
15 | "rollup-plugin-terser": "^5.1.2",
16 | "sparticles": "../../",
17 | "svelte": "^3.0.0"
18 | },
19 | "dependencies": {
20 | "sirv-cli": "^0.4.4"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/example/esm/esm.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Sparticles with Vanilla Javascript
9 |
10 |
11 |
12 |
13 |
14 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/example/test/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | Sparticles Test Area
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/example/vanilla/vanilla.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Sparticles with Vanilla Javascript
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/example/example.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | html, body {
6 | color: rgb(237, 231, 255);
7 | background: rgb(33, 32, 39);
8 | padding: 10px;
9 | margin: 0;
10 | height: 100%;
11 | }
12 |
13 | main {
14 | height: 100%;
15 | }
16 |
17 | nav {
18 | position: fixed;
19 | bottom: 10px;
20 | left: 10px;
21 | }
22 |
23 | nav ul {
24 | list-style: none;
25 | }
26 |
27 | nav li {
28 | margin: 0 10px 0 -2px;
29 | padding: 0 10px 0 0;
30 | display: inline-block;
31 | }
32 |
33 | nav li:not(:last-child) {
34 | border-right: 1px solid white;
35 | }
36 |
37 | nav a {
38 | color: rgba(255, 255, 255, 0.6);
39 | line-height: 1.4;
40 | display: inline-block;
41 | }
42 |
43 | nav a.current,
44 | nav a:hover,
45 | nav a:active,
46 | nav a:focus {
47 | color: white;
48 | }
49 |
--------------------------------------------------------------------------------
/example/svelte/public/global.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | html, body {
6 | color: rgb(237, 231, 255);
7 | background: rgb(33, 32, 39);
8 | padding: 10px;
9 | margin: 0;
10 | height: 100%;
11 | }
12 |
13 | nav {
14 | position: fixed;
15 | bottom: 10px;
16 | left: 10px;
17 | }
18 |
19 | nav ul {
20 | list-style: none;
21 | }
22 |
23 | nav li {
24 | margin: 0 10px 0 -2px;
25 | padding: 0 10px 0 0;
26 | display: inline-block;
27 | }
28 |
29 | nav li:not(:last-child) {
30 | border-right: 1px solid white;
31 | }
32 |
33 | nav a {
34 | color: rgba(255, 255, 255, 0.6);
35 | line-height: 1.4;
36 | display: inline-block;
37 | }
38 |
39 | nav a.current,
40 | nav a:hover,
41 | nav a:active,
42 | nav a:focus {
43 | color: white;
44 | }
45 |
46 | canvas {
47 | position: absolute;
48 | inset: 0;
49 | }
--------------------------------------------------------------------------------
/example/jquery/jquery.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Sparticles with jQuery
11 |
12 |
13 |
14 |
15 |
16 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/example/sveltekit/static/global.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | html, body {
6 | color: rgb(237, 231, 255);
7 | background: rgb(33, 32, 39);
8 | padding: 10px;
9 | margin: 0;
10 | height: 100%;
11 | }
12 |
13 | nav {
14 | position: fixed;
15 | bottom: 10px;
16 | left: 10px;
17 | }
18 |
19 | nav ul {
20 | list-style: none;
21 | }
22 |
23 | nav li {
24 | margin: 0 10px 0 -2px;
25 | padding: 0 10px 0 0;
26 | display: inline-block;
27 | }
28 |
29 | nav li:not(:last-child) {
30 | border-right: 1px solid white;
31 | }
32 |
33 | nav a {
34 | color: rgba(255, 255, 255, 0.6);
35 | line-height: 1.4;
36 | display: inline-block;
37 | }
38 |
39 | nav a.current,
40 | nav a:hover,
41 | nav a:active,
42 | nav a:focus {
43 | color: white;
44 | }
45 |
46 | canvas {
47 | position: absolute;
48 | inset: 0;
49 | }
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change log
2 | ## 1.1.0
3 |
4 | - shapes and images can now be used together in an array to mix basic shapes and custom images;
5 | ```js
6 | let mySparticles = new Sparticles( el, {
7 |
8 | shape: ["circle", "image"],
9 | imageUrl: "./snowflake.png"
10 |
11 | })
12 | ```
13 |
14 | - fixed some performance / looping errors
15 | - refactored/renamed a lot of prototype methods
16 |
17 | - added the ability to write custom shapes in the off-chance that's
18 | better/easier than using a custom svg-image
19 | ```js
20 | // first make sure the Sparticles is ready in page.
21 | // then you can add a custom offScreenCanvas before initialising.
22 | Sparticles.prototype.offScreenCanvas.doge = function(style, color, canvas) {
23 | // code for custom shape here, access to "this" object
24 | // which is the Sparticles prototype.
25 | };
26 | // then initialise your sparticles instance with the custom shape
27 | let mySparticles = new Sparticles( el, { shape: "doge" });
28 |
29 |
30 | ```
31 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # next.js build output
61 | .next
62 |
--------------------------------------------------------------------------------
/example/sveltekit/README.md:
--------------------------------------------------------------------------------
1 | # create-svelte
2 |
3 | Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte);
4 |
5 | ## Creating a project
6 |
7 | If you're seeing this, you've probably already done this step. Congrats!
8 |
9 | ```bash
10 | # create a new project in the current directory
11 | npm init svelte@next
12 |
13 | # create a new project in my-app
14 | npm init svelte@next my-app
15 | ```
16 |
17 | > Note: the `@next` is temporary
18 |
19 | ## Developing
20 |
21 | Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
22 |
23 | ```bash
24 | npm run dev
25 |
26 | # or start the server and open the app in a new browser tab
27 | npm run dev -- --open
28 | ```
29 |
30 | ## Building
31 |
32 | Before creating a production version of your app, install an [adapter](https://kit.svelte.dev/docs#adapters) for your target environment. Then:
33 |
34 | ```bash
35 | npm run build
36 | ```
37 |
38 | > You can preview the built app with `npm run preview`, regardless of whether you installed an adapter. This should _not_ be used to serve your app in production.
39 |
--------------------------------------------------------------------------------
/src/animationFrame.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Limited Animation Frame method, to allow running
3 | * a given handler at the maximum desired frame rate.
4 | * inspired from https://gist.github.com/addyosmani/5434533
5 | * @param {Function} handler method to execute upon every frame
6 | * @param {Number} fps how many frames to render every second
7 | */
8 | export const AnimationFrame = function(handler = () => {}, fps = 60) {
9 | this.fps = fps;
10 | this.handler = handler;
11 | let renderId = 0;
12 |
13 | /**
14 | * begin the animation loop which is assigned
15 | * to the instance in the constructor
16 | */
17 | this.start = function() {
18 | if (!this.started) {
19 | let then = performance.now();
20 | const interval = 1000 / this.fps;
21 | const tolerance = 0;
22 |
23 | const loop = now => {
24 | const delta = now - then;
25 | renderId = requestAnimationFrame(loop);
26 | if (delta >= interval - tolerance) {
27 | this.handler(delta);
28 | then = now - (delta % interval);
29 | }
30 | };
31 |
32 | renderId = requestAnimationFrame(loop);
33 | this.started = true;
34 | }
35 | };
36 |
37 | /**
38 | * stop the currently running animation loop
39 | */
40 | this.stop = function() {
41 | cancelAnimationFrame(renderId);
42 | this.started = false;
43 | };
44 | };
45 |
46 | export default AnimationFrame;
47 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sparticles",
3 | "version": "1.3.1",
4 | "description": "Lightweight, High Performance Particles in Canvas",
5 | "main": "dist/sparticles.mjs",
6 | "files": [
7 | "dist/sparticles.js",
8 | "dist/sparticles.min.js",
9 | "dist/sparticles.esm.js",
10 | "src/sparticles.js"
11 | ],
12 | "repository": "https://github.com/simeydotme/sparticles.git",
13 | "author": "simeydotme ",
14 | "homepage": "http://sparticlesjs.dev",
15 | "license": "MPL-2.0",
16 | "private": false,
17 | "scripts": {
18 | "build": "rollup --config",
19 | "dev": "rollup --config --watch",
20 | "lint": "yarn -s lint-code && yarn -s lint-config",
21 | "lint-code": "echo '\n✨ linting source code...\n' && prettier --write 'src/**/*.js'",
22 | "lint-config": "echo '\n✨ linting config files...\n' && prettier --write '*.js' && echo ''",
23 | "lint-staged": "pretty-quick --staged --pattern 'src/**/*.js' && pretty-quick --pattern '*.js'"
24 | },
25 | "husky": {
26 | "hooks": {
27 | "pre-commit": "yarn lint-staged"
28 | }
29 | },
30 | "devDependencies": {
31 | "@babel/core": "^7.7.2",
32 | "@babel/preset-env": "^7.7.1",
33 | "@rollup/plugin-babel": "^5.2.1",
34 | "dat.gui": "^0.7.6",
35 | "husky": "^3.0.9",
36 | "lodash": "^4.17.19",
37 | "prettier": "^1.19.1",
38 | "pretty-quick": "^2.0.1",
39 | "rollup": "^1.32.0",
40 | "rollup-plugin-filesize": "^6.2.1",
41 | "rollup-plugin-livereload": "^1.0.4",
42 | "rollup-plugin-serve": "^1.0.1",
43 | "rollup-plugin-terser": "^5.3.0",
44 | "stats.js": "^0.17.0"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/example/svelte/rollup.config.js:
--------------------------------------------------------------------------------
1 | import svelte from 'rollup-plugin-svelte';
2 | import resolve from '@rollup/plugin-node-resolve';
3 | import commonjs from '@rollup/plugin-commonjs';
4 | import livereload from 'rollup-plugin-livereload';
5 | import { terser } from 'rollup-plugin-terser';
6 |
7 | const production = !process.env.ROLLUP_WATCH;
8 |
9 | export default {
10 | input: 'src/main.js',
11 | output: {
12 | sourcemap: true,
13 | format: 'iife',
14 | name: 'app',
15 | file: 'public/build/bundle.js'
16 | },
17 | plugins: [
18 | svelte({
19 | // enable run-time checks when not in production
20 | dev: !production,
21 | // we'll extract any component CSS out into
22 | // a separate file - better for performance
23 | css: css => {
24 | css.write('public/build/bundle.css');
25 | }
26 | }),
27 |
28 | // If you have external dependencies installed from
29 | // npm, you'll most likely need these plugins. In
30 | // some cases you'll need additional configuration -
31 | // consult the documentation for details:
32 | // https://github.com/rollup/plugins/tree/master/packages/commonjs
33 | resolve({
34 | browser: true,
35 | dedupe: ['svelte']
36 | }),
37 | commonjs(),
38 |
39 | // In dev mode, call `npm run start` once
40 | // the bundle has been generated
41 | !production && serve(),
42 |
43 | // Watch the `public` directory and refresh the
44 | // browser on changes when not in production
45 | !production && livereload('public'),
46 |
47 | // If we're building for production (npm run build
48 | // instead of npm run dev), minify
49 | production && terser()
50 | ],
51 | watch: {
52 | clearScreen: false
53 | }
54 | };
55 |
56 | function serve() {
57 | let started = false;
58 |
59 | return {
60 | writeBundle() {
61 | if (!started) {
62 | started = true;
63 |
64 | require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
65 | stdio: ['ignore', 'inherit', 'inherit'],
66 | shell: true
67 | });
68 | }
69 | }
70 | };
71 | }
72 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import { terser } from "rollup-plugin-terser";
2 | import babel from "@rollup/plugin-babel";
3 | import filesize from "rollup-plugin-filesize";
4 | import livereload from "rollup-plugin-livereload";
5 | import serve from "rollup-plugin-serve";
6 | import pkg from "./package.json";
7 |
8 | const dev = process.env.ROLLUP_WATCH;
9 | const prod = !dev;
10 | const banner = () => `/**!
11 | * Sparticles - ${pkg.description}
12 | * @version ${pkg.version}
13 | * @license ${pkg.license}
14 | * @author ${pkg.author}
15 | * @website ${pkg.homepage}
16 | * @repository ${pkg.repository}
17 | */
18 | `;
19 |
20 | export default [
21 | {
22 | input: "src/sparticles.js",
23 | output: [
24 | {
25 | file: "dist/sparticles.esm.js",
26 | format: "esm",
27 | banner: banner(),
28 | plugins: [filesize()],
29 | },
30 | {
31 | file: "dist/sparticles.mjs",
32 | format: "esm",
33 | banner: banner(),
34 | plugins: [filesize()],
35 | },
36 | {
37 | name: "Sparticles",
38 | file: "dist/sparticles.js",
39 | format: "iife",
40 | banner: banner(),
41 | plugins: [filesize()],
42 | },
43 | {
44 | name: "Sparticles",
45 | file: "dist/sparticles.min.js",
46 | format: "iife",
47 | banner: banner(),
48 | plugins: [prod && terser()],
49 | },
50 | ],
51 | plugins: [
52 | babel({
53 | babelrc: false,
54 | exclude: "node_modules/**",
55 | babelHelpers: "bundled",
56 | }),
57 | dev &&
58 | serve({
59 | contentBase: "",
60 | host: "localhost",
61 | openPage: "/example/vanilla/vanilla.html",
62 | port: 5555,
63 | }),
64 | dev && livereload(),
65 | ],
66 | watch: {
67 | include: "src/**",
68 | chokidar: {
69 | usePolling: true,
70 | interval: 2000,
71 | binaryInterval: 2000,
72 | },
73 | buildDelay: 1000,
74 | },
75 | },
76 | ];
77 |
--------------------------------------------------------------------------------
/src/helpers.js:
--------------------------------------------------------------------------------
1 | /**
2 | * return the cartesian x/y delta value from a degree
3 | * eg: 90 (→) = [1,0]
4 | * @param {Number} angle angle in degrees
5 | * @returns {Number[]} cartesian delta values
6 | */
7 | export const cartesian = angle => {
8 | return [Math.cos(radian(angle - 90)), Math.sin(radian(angle - 90))];
9 | };
10 |
11 | /**
12 | * clamp the input number to the min/max values
13 | * @param {Number} value value to clamp between min and max
14 | * @param {Number} min minimum value possible
15 | * @param {Number} max maximum value possible
16 | * @returns {Number} the input num clamped between min/max
17 | */
18 | export const clamp = (value, min = 0, max = 1) => {
19 | return Math.max(min, Math.min(max, value));
20 | };
21 | /**
22 | * return the radian equivalent to a degree value
23 | * @param {Number} angle angle in degrees
24 | * @returns {Number} radian equivalent
25 | */
26 | export const radian = angle => {
27 | return (angle * Math.PI) / 180;
28 | };
29 |
30 | /**
31 | * return random number between a min and max value
32 | * @param {Number} min minimum value
33 | * @param {Number} max maximum value
34 | * @param {Boolean} rounded should the result be rounded
35 | * @returns {Number} a random number between min and max
36 | */
37 | export const random = (min = 0, max = 1, value = Math.random()) => {
38 | if (max <= min) {
39 | value = min;
40 | } else if ((min !== 0 || max !== 1) && max > min) {
41 | value = value * (max - min) + min;
42 | }
43 | return value;
44 | };
45 |
46 | /**
47 | * return a random value from an array
48 | * @param {Array} array an array to get random value from
49 | * @returns {*} random value from array
50 | */
51 | export const randomArray = array => {
52 | return array[Math.floor(random(0, array.length))];
53 | };
54 |
55 | /**
56 | * return a random HSL colour string for use in random color effect
57 | * @returns {String} "hsl(100,100,80)"
58 | */
59 | export const randomHsl = () => {
60 | const h = round(random(0, 360));
61 | const s = round(random(90, 100));
62 | const l = round(random(45, 85));
63 | return `hsl(${h},${s}%,${l}%)`;
64 | };
65 |
66 | /**
67 | * return a boolean to pass a dice roll
68 | * @param {Number} odds a fraction to use as the probability, can be supplied as "1/2"
69 | * @returns {Boolean}
70 | */
71 | export const roll = odds => {
72 | return odds > random();
73 | };
74 |
75 | /**
76 | * round a number to the nearest integer value
77 | * @param {Number} value value to round to the nearest integer
78 | * @returns {Number} nearest integer
79 | */
80 | export const round = value => {
81 | return (0.5 + value) | 0;
82 | };
83 |
--------------------------------------------------------------------------------
/example/svelte/README.md:
--------------------------------------------------------------------------------
1 | *Looking for a shareable component template? Go here --> [sveltejs/component-template](https://github.com/sveltejs/component-template)*
2 |
3 | ---
4 |
5 | # svelte app
6 |
7 | This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template.
8 |
9 | To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit):
10 |
11 | ```bash
12 | npx degit sveltejs/template svelte-app
13 | cd svelte-app
14 | ```
15 |
16 | *Note that you will need to have [Node.js](https://nodejs.org) installed.*
17 |
18 |
19 | ## Get started
20 |
21 | Install the dependencies...
22 |
23 | ```bash
24 | cd svelte-app
25 | npm install
26 | ```
27 |
28 | ...then start [Rollup](https://rollupjs.org):
29 |
30 | ```bash
31 | npm run dev
32 | ```
33 |
34 | Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
35 |
36 | By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`.
37 |
38 |
39 | ## Building and running in production mode
40 |
41 | To create an optimised version of the app:
42 |
43 | ```bash
44 | npm run build
45 | ```
46 |
47 | You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com).
48 |
49 |
50 | ## Single-page app mode
51 |
52 | By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere.
53 |
54 | If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json:
55 |
56 | ```js
57 | "start": "sirv public --single"
58 | ```
59 |
60 |
61 | ## Deploying to the web
62 |
63 | ### With [now](https://zeit.co/now)
64 |
65 | Install `now` if you haven't already:
66 |
67 | ```bash
68 | npm install -g now
69 | ```
70 |
71 | Then, from within your project folder:
72 |
73 | ```bash
74 | cd public
75 | now deploy --name my-project
76 | ```
77 |
78 | As an alternative, use the [Now desktop client](https://zeit.co/download) and simply drag the unzipped project folder to the taskbar icon.
79 |
80 | ### With [surge](https://surge.sh/)
81 |
82 | Install `surge` if you haven't already:
83 |
84 | ```bash
85 | npm install -g surge
86 | ```
87 |
88 | Then, from within your project folder:
89 |
90 | ```bash
91 | npm run build
92 | surge public my-project.surge.sh
93 | ```
94 |
--------------------------------------------------------------------------------
/example/test/test.js:
--------------------------------------------------------------------------------
1 |
2 | let colorType = {
3 | type: "single"
4 | };
5 |
6 | let colors = {
7 | color1: "rgba(244,0,0,1)",
8 | color2: "rgba(252,248,230,1)",
9 | color3: "rgba(255,227,241,1)",
10 | color4: "rgba(230,248,255,1)"
11 | };
12 |
13 | let options = {
14 | alphaSpeed: 3,
15 | alphaVariance: 8,
16 | color: colors.color1,
17 | randomColorCount: 7,
18 | composition: "source-over",
19 | bounce: false,
20 | count: 200,
21 | direction: 180,
22 | drift: 0,
23 | glow: 0,
24 | imageUrl: [
25 | "./snowflake.png",
26 | "./star.png",
27 | "./star.png",
28 | "./star.png",
29 | "./star.png",
30 | "./star.png",
31 | "./star.png",
32 | "./star.png",
33 | "./star.png",
34 | "./star.png"
35 | ],
36 | maxAlpha: 1,
37 | maxSize: 50,
38 | minAlpha: 1,
39 | minSize: 20,
40 | parallax: 0,
41 | rotate: false,
42 | rotation: 0,
43 | shape: ["star"],
44 | speed: 1,
45 | style: "both",
46 | twinkle: false,
47 | xVariance: 0,
48 | yVariance: 0,
49 | };
50 |
51 | window.onload = function() {
52 |
53 | Sparticles.prototype.offScreenCanvas.wow = function(style, color, canvas) {
54 | const ctx = canvas.getContext("2d");
55 | const size = this.settings.maxSize;
56 | const lineSize = this.getLineSize(size);
57 | const glowSize = this.getGlowSize(size);
58 | const canvasSize = size + lineSize + glowSize;
59 | canvas.width = canvasSize;
60 | canvas.height = canvasSize;
61 | this.renderGlow(ctx, color, size);
62 | this.renderStyle(ctx, color, lineSize, style);
63 | ctx.beginPath();
64 | ctx.ellipse(canvasSize / 2, canvasSize / 2, size / 2, size / 2, 0, 0, 360);
65 | this.renderColor(ctx, style);
66 | return canvas;
67 | };
68 |
69 |
70 | initStats();
71 | initSparticles();
72 | initGui();
73 | }
74 |
75 | window.initSparticles = function() {
76 | var $main = document.querySelector("main");
77 | window.mySparticles = new Sparticles($main,JSON.parse(JSON.stringify(options)));
78 | };
79 |
80 | window.initStats = function() {
81 | var stats = new Stats();
82 | document.body.appendChild(stats.dom);
83 | function statsDisplay() {
84 | stats.begin();
85 | stats.end();
86 | requestAnimationFrame(statsDisplay);
87 | }
88 | requestAnimationFrame(statsDisplay);
89 | };
90 |
91 | window.initGui = function() {
92 | let s = window.mySparticles;
93 | const shapes = ["random", "circle", "square", "triangle", "diamond", "star", "line", "image"];
94 | const styles = ["fill", "stroke", "both"];
95 | const colorOptions = ["single", "multi", "random"];
96 | const composites = [
97 | "source-over",
98 | "source-in",
99 | "source-out",
100 | "source-atop",
101 | "destination-over",
102 | "destination-in",
103 | "destination-out",
104 | "destination-atop",
105 | "lighter",
106 | "copy",
107 | "xor",
108 | "multiply",
109 | "screen",
110 | "overlay",
111 | "darken",
112 | "color-dodge",
113 | "color-burn",
114 | "hard-light",
115 | "soft-light",
116 | "difference",
117 | "exclusion",
118 | "hue",
119 | "saturation",
120 | "color",
121 | "luminosity"
122 | ];
123 |
124 | const rerender = () => {
125 | if( window.mySparticles && window.mySparticles instanceof Sparticles ) {
126 | try {
127 | window.mySparticles.destroy();
128 | } catch(e) {
129 | document.querySelector("main").removeChild( s.canvas );
130 | }
131 | }
132 | window.initSparticles();
133 | };
134 |
135 | var rerenderColors = function(v) {
136 | if (colorType.type === "random") {
137 | options.color = "random";
138 | } else if (colorType.type === "single") {
139 | options.color = colors.color1;
140 | } else {
141 | options.color = Object.keys(colors).map(i => {
142 | return colors[i];
143 | });
144 | }
145 | rerender();
146 | };
147 |
148 | const gui = new dat.GUI({ load: options });
149 | const part = gui.addFolder("Particles");
150 | part.open();
151 | part.add(options, "count", 1, 500, 1).onFinishChange(rerender);
152 | part.add(options, "shape", shapes).onFinishChange(rerender);
153 | part.add(options, "style", styles).onFinishChange(rerender);
154 | part.add(options, "rotate").onFinishChange(rerender);
155 | part.add(options, "bounce").onFinishChange(rerender);
156 | const image = part.addFolder("Image");
157 | // image.add(options, "imageUrl").onFinishChange(rerender);
158 | part.add(options, "minSize", 1, 250, 1).onFinishChange(rerender);
159 | part.add(options, "maxSize", 1, 250, 1).onFinishChange(rerender);
160 | const anim = gui.addFolder("Animation");
161 | anim.add(options, "direction", 0, 360, 1).onFinishChange(rerender);
162 | anim.add(options, "speed", 0, 100, 0.1).onFinishChange(rerender);
163 | anim.add(options, "rotation", 0, 100, 0.1).onFinishChange(rerender);
164 | const move = anim.addFolder("Movement");
165 | move.add(options, "parallax", 0, 10, 0.1).onFinishChange(rerender);
166 | move.add(options, "drift", 0, 30, 0.01).onFinishChange(rerender);
167 | move.add(options, "xVariance", 0, 20, 0.1).onFinishChange(rerender);
168 | move.add(options, "yVariance", 0, 20, 0.1).onFinishChange(rerender);
169 | const vis = gui.addFolder("Visual");
170 | vis.add(options, "glow", 0,150).onFinishChange(rerender);
171 | vis.add(options, "composition", composites).onFinishChange(rerender);
172 | const alpha = vis.addFolder("Alpha");
173 | alpha.add(options, "twinkle").onFinishChange(rerender);
174 | alpha.add(options, "minAlpha", -2, 2, 0.1).onFinishChange(rerender);
175 | alpha.add(options, "maxAlpha", -2, 2, 0.1).onFinishChange(rerender);
176 | alpha.add(options, "alphaSpeed", 0, 50, 1).onFinishChange(rerender);
177 | alpha.add(options, "alphaVariance", 0, 20, 1).onFinishChange(rerender);
178 | const color = vis.addFolder("Color");
179 | color.open();
180 | color.add(colorType, "type", colorOptions).onFinishChange(rerenderColors);
181 | color.addColor(colors, "color1").onFinishChange(rerenderColors);
182 | color.addColor(colors, "color2").onFinishChange(rerenderColors);
183 | color.addColor(colors, "color3").onFinishChange(rerenderColors);
184 | color.addColor(colors, "color4").onFinishChange(rerenderColors);
185 | const control = gui.addFolder("Controls");
186 | control.add(s,"start");
187 | control.add(s,"stop");
188 | };
189 |
--------------------------------------------------------------------------------
/dist/sparticles.min.js:
--------------------------------------------------------------------------------
1 | /**!
2 | * Sparticles - Lightweight, High Performance Particles in Canvas
3 | * @version 1.3.1
4 | * @license MPL-2.0
5 | * @author simeydotme
6 | * @website http://sparticlesjs.dev
7 | * @repository https://github.com/simeydotme/sparticles.git
8 | */
9 | var Sparticles=function(){"use strict";function t(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(t);e&&(s=s.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,s)}return i}function e(e){for(var s=1;s0&&void 0!==arguments[0]?arguments[0]:function(){},e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:60;this.fps=e,this.handler=t;var i=0;this.start=function(){var t=this;if(!this.started){var e=performance.now(),s=1e3/this.fps;i=requestAnimationFrame((function n(r){var h=r-e;i=requestAnimationFrame(n),h>=s-0&&(t.handler(h),e=r-h%s)})),this.started=!0}},this.stop=function(){cancelAnimationFrame(i),this.started=!1}},n=function(t){return[Math.cos(h(t-90)),Math.sin(h(t-90))]},r=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1;return Math.max(e,Math.min(i,t))},h=function(t){return t*Math.PI/180},a=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:Math.random();return e<=t?i=t:(0!==t||1!==e)&&e>t&&(i=i*(e-t)+t),i},o=function(t){return t[Math.floor(a(0,t.length))]},c=function(){var t=p(a(0,360)),e=p(a(90,100)),i=p(a(45,85));return"hsl(".concat(t,",").concat(e,"%,").concat(i,"%)")},l=function(t){return t>a()},p=function(t){return.5+t|0},g=function(t){return t?(this.canvas=t.canvas,this.settings=t.settings,this.colors=t.colors,this.shapes=t.shapes,this.images=t.images,this.styles=t.styles,this.ctx=t.canvas.getContext("2d"),this.setup(),this.init()):console.warn("Invalid parameters given to Sparticle()",arguments),this};g.prototype.setup=function(){var t=this.settings;this.frame=0,this.frameoffset=p(a(0,360)),this.size=p(a(t.minSize,t.maxSize)),this.da=this.getAlphaDelta(),this.dx=this.getDeltaX(),this.dy=this.getDeltaY(),this.dd=this.getDriftDelta(),this.dr=this.getRotationDelta(),this.color=this.getColor(),this.shape=this.getShape(),this.image=this.getImage(),this.style=this.getStyle(),this.rotation=t.rotate?h(a(0,360)):0,this.vertical=t.direction>150&&t.direction<210||t.direction>330&&t.direction<390||t.direction>-30&&t.direction<30,this.horizontal=t.direction>60&&t.direction<120||t.direction>240&&t.direction<300},g.prototype.init=function(){var t=this.settings,e=this.canvas;this.alpha=0,(t.speed>0||0===t.alphaSpeed)&&(this.alpha=a(t.minAlpha,t.maxAlpha)),t.bounce?(this.px=p(a(2,e.width-this.size-2)),this.py=p(a(2,e.height-this.size-2))):(this.px=p(a(2*-this.size,e.width+this.size)),this.py=p(a(2*-this.size,e.height+this.size)))},g.prototype.reset=function(){this.setup(),this.py<0?this.py=this.canvas.height+2*this.size:this.py>this.canvas.height&&(this.py=0-2*this.size),this.px<0?this.px=this.canvas.width+2*this.size:this.px>this.canvas.width&&(this.px=0-2*this.size)},g.prototype.bounce=function(){this.settings.direction;(this.py<=0||this.py+this.size>=this.canvas.height)&&(this.dy=-this.dy,this.horizontal&&(this.dd=-this.dd)),(this.px<=0||this.px+this.size>=this.canvas.width)&&(this.dx=-this.dx,this.vertical&&(this.dd=-this.dd))},g.prototype.isOffCanvas=function(){var t=0-2*this.size,e=this.canvas.height+2*this.size,i=this.canvas.width+2*this.size;return this.pxi||this.pye},g.prototype.isTouchingEdge=function(){var t=this.canvas.height-this.size,e=this.canvas.width-this.size;return this.px<0||this.px>e||this.py<0||this.py>t},g.prototype.getColor=function(){return"random"===this.settings.color?o(this.colors):Array.isArray(this.settings.color)?o(this.settings.color):this.settings.color},g.prototype.getShape=function(){return"random"===this.settings.shape?o(this.shapes):Array.isArray(this.settings.shape)?o(this.settings.shape):this.settings.shape},g.prototype.getImage=function(){return Array.isArray(this.settings.imageUrl)?o(this.settings.imageUrl):this.settings.imageUrl},g.prototype.getStyle=function(){return o(this.styles)},g.prototype.getDelta=function(){var t=.1*this.settings.speed;return this.settings.speed&&this.settings.parallax?t+this.size*this.settings.parallax/50:t},g.prototype.getDeltaVariance=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=this.settings.speed||10;return t>0?a(-t,t)*e/100:0},g.prototype.getDeltaX=function(){var t=this.getDelta(),e=this.getDeltaVariance(this.settings.xVariance);return n(this.settings.direction)[0]*t+e},g.prototype.getDeltaY=function(){var t=this.getDelta(),e=this.getDeltaVariance(this.settings.yVariance);return n(this.settings.direction)[1]*t+e},g.prototype.getAlphaDelta=function(){var t=this.settings.alphaVariance,e=a(1,t+1);return l(.5)&&(e=-e),e},g.prototype.getDriftDelta=function(){return this.settings.drift?a(this.settings.drift-this.settings.drift/2,this.settings.drift+this.settings.drift/2):0},g.prototype.getRotationDelta=function(){var t=0;return this.settings.rotate&&this.settings.rotation&&(t=h(a(.5,1.5)*this.settings.rotation),l(.5)&&(t=-t)),t},g.prototype.update=function(){return this.frame+=1,this.updatePosition(),this.updateAlpha(),this},g.prototype.updateAlpha=function(){return this.settings.alphaSpeed>0&&(this.settings.twinkle?this.alpha=this.updateTwinkle():this.alpha=this.updateFade()),this.alpha},g.prototype.updateFade=function(){var t=this.da/1e3*this.settings.alphaSpeed*.5,e=this.alpha+t,i=this.da>0&&e>this.settings.maxAlpha,s=this.da<0&ðis.settings.maxAlpha,s=t=1&&!(arguments[0]instanceof HTMLElement)&&(i=arguments[0],n=arguments[1],r=arguments[2],t=void 0),n&&!r&&(r=n);var h={alphaSpeed:10,alphaVariance:1,bounce:!1,color:"random",randomColor:c,randomColorCount:3,composition:"source-over",count:50,direction:180,drift:1,glow:0,imageUrl:"",maxAlpha:1,maxSize:10,minAlpha:0,minSize:1,parallax:1,rotate:!0,rotation:1,shape:"circle",speed:10,style:"fill",twinkle:!1,xVariance:2,yVariance:2};return this.el=t||document.body,this.settings=e(e({},h),i),this.resizable=!n&&!r,this.width=this.resizable?this.el.clientWidth:n,this.height=this.resizable?this.el.clientHeight:r,this.init=function(){var t=this;return this.sparticles=[],this.colors=this.getColorArray(),this.shapes=this.getShapeArray(),this.styles=this.getStyleArray(),this.imageUrls=this.getImageArray(),this.setupMainCanvas(),this.setupOffscreenCanvasses((function(){t.createSparticles(),t.start()})),window.addEventListener("resize",this),this},this.handleEvent=function(t){var e=this;"resize"===t.type&&(clearTimeout(this.resizeTimer),this.resizeTimer=setTimeout((function(){e.resizable&&(e.width=e.el.clientWidth,e.height=e.el.clientHeight,e.setCanvasSize().resetSparticles())}),200))},this.start=function(){var t=this;return this.loop||(this.loop=new s((function(e){t.drawFrame(e)}))),this.loop.start(),this},this.stop=function(){return this.loop.stop(),this},this.destroy=function(){for(var t in this.stop(),this.el.removeChild(this.canvas),window.removeEventListener("resize",this),this)this.hasOwnProperty(t)&&delete this[t];return this},this.setCanvasSize=function(t,e){return t&&(this.resizable=!1),this.width=t||this.width,this.height=e||this.height,this.canvas.width=this.width,this.canvas.height=this.height,this},this.resetSparticles=this.createSparticles=function(){this.sparticles=[],this.ctx.globalCompositeOperation=this.settings.composition;for(var t=0;t 150 && _.direction < 210) ||
48 | (_.direction > 330 && _.direction < 390) ||
49 | (_.direction > -30 && _.direction < 30);
50 | this.horizontal =
51 | (_.direction > 60 && _.direction < 120) || (_.direction > 240 && _.direction < 300);
52 | };
53 |
54 | /**
55 | * initialise a particle with the default values from
56 | * the Sparticles instance settings.
57 | * these values do not change when the particle goes offscreen
58 | */
59 | Sparticle.prototype.init = function() {
60 | const _ = this.settings;
61 | const canvas = this.canvas;
62 | this.alpha = 0;
63 | if (_.speed > 0 || _.alphaSpeed === 0) {
64 | this.alpha = random(_.minAlpha, _.maxAlpha);
65 | }
66 | if (_.bounce) {
67 | this.px = round(random(2, canvas.width - this.size - 2));
68 | this.py = round(random(2, canvas.height - this.size - 2));
69 | } else {
70 | this.px = round(random(-this.size * 2, canvas.width + this.size));
71 | this.py = round(random(-this.size * 2, canvas.height + this.size));
72 | }
73 | };
74 |
75 | /**
76 | * reset the particle after it has gone off canvas.
77 | * this should be better than popping it from the array
78 | * and creating a new particle instance.
79 | */
80 | Sparticle.prototype.reset = function() {
81 | // give the particle a new set of initial values
82 | this.setup();
83 | // set the particle's Y position
84 | if (this.py < 0) {
85 | this.py = this.canvas.height + this.size * 2;
86 | } else if (this.py > this.canvas.height) {
87 | this.py = 0 - this.size * 2;
88 | }
89 | // set the particle's X position
90 | if (this.px < 0) {
91 | this.px = this.canvas.width + this.size * 2;
92 | } else if (this.px > this.canvas.width) {
93 | this.px = 0 - this.size * 2;
94 | }
95 | };
96 |
97 | /**
98 | * bounce the particle off the edge of canvas
99 | * when it has touched
100 | */
101 | Sparticle.prototype.bounce = function() {
102 | const _ = this.settings;
103 | const dir = _.direction;
104 |
105 | // reverse the particle's Y position
106 | if (this.py <= 0 || this.py + this.size >= this.canvas.height) {
107 | this.dy = -this.dy;
108 | if (this.horizontal) {
109 | this.dd = -this.dd;
110 | }
111 | }
112 | // reverse the particle's X position
113 | if (this.px <= 0 || this.px + this.size >= this.canvas.width) {
114 | this.dx = -this.dx;
115 | if (this.vertical) {
116 | this.dd = -this.dd;
117 | }
118 | }
119 | };
120 |
121 | /**
122 | * check if the particle is off the canvas based
123 | * on it's current position
124 | * @returns {Boolean} is the particle completely off canvas
125 | */
126 | Sparticle.prototype.isOffCanvas = function() {
127 | const topleft = 0 - this.size * 2;
128 | const bottom = this.canvas.height + this.size * 2;
129 | const right = this.canvas.width + this.size * 2;
130 | return this.px < topleft || this.px > right || this.py < topleft || this.py > bottom;
131 | };
132 |
133 | /**
134 | * check if the particle is touching the canvas edge
135 | * @returns {Boolean} is the particle touching edge
136 | */
137 | Sparticle.prototype.isTouchingEdge = function() {
138 | const topleft = 0;
139 | const bottom = this.canvas.height - this.size;
140 | const right = this.canvas.width - this.size;
141 | return this.px < topleft || this.px > right || this.py < topleft || this.py > bottom;
142 | };
143 |
144 | /**
145 | * get a random color for the particle from the
146 | * array of colors set in the options object
147 | * @returns {String} - random color from color array
148 | */
149 | Sparticle.prototype.getColor = function() {
150 | if (this.settings.color === "random") {
151 | return randomArray(this.colors);
152 | } else if (Array.isArray(this.settings.color)) {
153 | return randomArray(this.settings.color);
154 | } else {
155 | return this.settings.color;
156 | }
157 | };
158 |
159 | /**
160 | * get a random shape for the particle from the
161 | * array of shapes set in the options object
162 | * @returns {String} - random shape from shape array
163 | */
164 | Sparticle.prototype.getShape = function() {
165 | if (this.settings.shape === "random") {
166 | return randomArray(this.shapes);
167 | } else if (Array.isArray(this.settings.shape)) {
168 | return randomArray(this.settings.shape);
169 | } else {
170 | return this.settings.shape;
171 | }
172 | };
173 |
174 | /**
175 | * get the image for the particle from the array
176 | * of possible image urls
177 | * @returns {String} - random imageUrl from imageUrl array
178 | */
179 | Sparticle.prototype.getImage = function() {
180 | if (Array.isArray(this.settings.imageUrl)) {
181 | return randomArray(this.settings.imageUrl);
182 | } else {
183 | return this.settings.imageUrl;
184 | }
185 | };
186 |
187 | /**
188 | * get the style of the particle, either "fill" or "stroke"
189 | * depending on the settings as fill/stroke/both
190 | * @returns {String} - either "fill" or "stroke"
191 | */
192 | Sparticle.prototype.getStyle = function() {
193 | return randomArray(this.styles);
194 | };
195 |
196 | /**
197 | * get a random delta (velocity) for the particle
198 | * based on the speed, and the parallax value (if applicable)
199 | * @returns {Number} - the velocity to be applied to the particle
200 | */
201 | Sparticle.prototype.getDelta = function() {
202 | let baseDelta = this.settings.speed * 0.1;
203 | if (this.settings.speed && this.settings.parallax) {
204 | return baseDelta + (this.size * this.settings.parallax) / 50;
205 | } else {
206 | return baseDelta;
207 | }
208 | };
209 |
210 | /**
211 | * get a random variable speed for use as a multiplier,
212 | * based on the values given in the settings object, this
213 | * can be positive or negative
214 | * @returns {Number} - a variable delta speed
215 | */
216 | Sparticle.prototype.getDeltaVariance = function(v = 0) {
217 | const s = this.settings.speed || 10;
218 | if (v > 0) {
219 | return (random(-v, v) * s) / 100;
220 | } else {
221 | return 0;
222 | }
223 | };
224 |
225 | /**
226 | * get a random delta on the X axis, taking in to account
227 | * the variance range in the settings object and the particle's
228 | * direction as a multiplier
229 | * @returns {Number} - the X delta to be applied to particle
230 | */
231 | Sparticle.prototype.getDeltaX = function() {
232 | const d = this.getDelta();
233 | const dv = this.getDeltaVariance(this.settings.xVariance);
234 | return cartesian(this.settings.direction)[0] * d + dv;
235 | };
236 |
237 | /**
238 | * get a random delta on the Y axis, taking in to account
239 | * the variance range in the settings object and the particle's
240 | * direction as a multiplier
241 | * @returns {Number} - the Y delta to be applied to particle
242 | */
243 | Sparticle.prototype.getDeltaY = function() {
244 | const d = this.getDelta();
245 | const dv = this.getDeltaVariance(this.settings.yVariance);
246 | return cartesian(this.settings.direction)[1] * d + dv;
247 | };
248 |
249 | /**
250 | * get a random delta for the alpha change over time from
251 | * between a positive and negative alpha variance value
252 | * @returns {Number} - the alpha delta to be applied to particle
253 | */
254 | Sparticle.prototype.getAlphaDelta = function() {
255 | let variance = this.settings.alphaVariance;
256 | let a = random(1, variance + 1);
257 | if (roll(1 / 2)) {
258 | a = -a;
259 | }
260 | return a;
261 | };
262 |
263 | /**
264 | * return a random drift value either positive or negative
265 | * @returns {Number} - the drift value
266 | */
267 | Sparticle.prototype.getDriftDelta = function() {
268 | if (!this.settings.drift) {
269 | return 0;
270 | } else {
271 | return random(
272 | this.settings.drift - this.settings.drift / 2,
273 | this.settings.drift + this.settings.drift / 2
274 | );
275 | }
276 | };
277 |
278 | /**
279 | * return a random rotation value either positive or negative
280 | * @returns {Number} - the rotation value
281 | */
282 | Sparticle.prototype.getRotationDelta = function() {
283 | let r = 0;
284 | if (this.settings.rotate && this.settings.rotation) {
285 | r = radian(random(0.5, 1.5) * this.settings.rotation);
286 | if (roll(1 / 2)) {
287 | r = -r;
288 | }
289 | }
290 | return r;
291 | };
292 |
293 | /**
294 | * progress the particle's frame number, as well
295 | * as the internal values for both the particle's
296 | * position and the particle's alpha.
297 | * @returns {Object} - reference to the current Sparticle instance
298 | */
299 | Sparticle.prototype.update = function() {
300 | this.frame += 1;
301 | this.updatePosition();
302 | this.updateAlpha();
303 | return this;
304 | };
305 |
306 | /**
307 | * progress the particle's alpha value depending on the
308 | * alphaSpeed and the twinkle setting
309 | * @returns {Number} - new alpha value of the particle
310 | */
311 | Sparticle.prototype.updateAlpha = function() {
312 | if (this.settings.alphaSpeed > 0) {
313 | if (this.settings.twinkle) {
314 | this.alpha = this.updateTwinkle();
315 | } else {
316 | this.alpha = this.updateFade();
317 | }
318 | }
319 | return this.alpha;
320 | };
321 |
322 | /**
323 | * progress the particle's alpha value according to
324 | * the fading effect
325 | * @returns {Number} - new alpha value of the particle
326 | */
327 | Sparticle.prototype.updateFade = function() {
328 | const tick = (this.da / 1000) * this.settings.alphaSpeed * 0.5;
329 | let alpha = this.alpha + tick;
330 | const over = this.da > 0 && alpha > this.settings.maxAlpha;
331 | const under = this.da < 0 && alpha < this.settings.minAlpha;
332 | // if the alpha is over or under the min or max values,
333 | // then we reverse the delta so that it can increase or
334 | // decrease in opacity in the opposite direction
335 | if (over || under) {
336 | this.da = -this.da;
337 | alpha = this.settings.maxAlpha;
338 | if (under) {
339 | alpha = this.settings.minAlpha;
340 | }
341 | }
342 | return alpha;
343 | };
344 |
345 | /**
346 | * progress the particle's alpha value according to
347 | * the twinkle effect
348 | * @returns {Number} - new alpha value of the particle
349 | */
350 | Sparticle.prototype.updateTwinkle = function() {
351 | let alpha = this.alpha;
352 | const delta = Math.abs(this.da);
353 | const over = alpha > this.settings.maxAlpha;
354 | const under = alpha < this.settings.minAlpha;
355 | const tick = (delta / 1000) * this.settings.alphaSpeed * 0.5;
356 | const flickerOn = roll(1 / 30);
357 | const flickerOff = roll(1 / 30);
358 | // if the particle is resetting the twinkle effect, then
359 | // we simply want to quickly get back to max alpha
360 | // over a short period of time, otherwise just advance the tick
361 | if (this.resettingTwinkle) {
362 | alpha += tick * 5;
363 | } else if (flickerOn) {
364 | alpha += tick * 50;
365 | } else if (flickerOff) {
366 | alpha -= tick * 25;
367 | } else {
368 | alpha -= tick;
369 | }
370 | // once the alpha is under the min alpha value, then we need
371 | // to set the twinkle effect to reset, and once it is over
372 | // the max alpha, we stop resetting.
373 | if (under) {
374 | this.resettingTwinkle = true;
375 | alpha = this.settings.minAlpha;
376 | } else if (over) {
377 | this.resettingTwinkle = false;
378 | alpha = this.settings.maxAlpha;
379 | }
380 | return alpha;
381 | };
382 |
383 | /**
384 | * progress the particle's position values, rotation and drift
385 | * according to the settings given
386 | */
387 | Sparticle.prototype.updatePosition = function() {
388 | if (this.settings.bounce && this.isTouchingEdge()) {
389 | this.bounce();
390 | } else if (this.isOffCanvas()) {
391 | this.reset();
392 | return;
393 | }
394 |
395 | this.px += this.dx;
396 | this.py += this.dy;
397 | // drift must be applied after position x/y
398 | // as it modifies the values by wave function
399 | this.updateDrift();
400 | this.updateRotation();
401 | };
402 |
403 | /**
404 | * progress the particle's rotation value according
405 | * to the settings given
406 | */
407 | Sparticle.prototype.updateRotation = function() {
408 | if (this.settings.rotate && this.settings.rotation) {
409 | this.rotation += this.dr;
410 | }
411 | };
412 |
413 | /**
414 | * progress the particle's drift value according
415 | * to the settings given
416 | */
417 | Sparticle.prototype.updateDrift = function() {
418 | const _ = this.settings;
419 | const dir = _.direction;
420 |
421 | if (_.drift && _.speed) {
422 | if (this.vertical) {
423 | // apply HORIZONTAL drift ~ when "direction" is mostly vertical.
424 | this.px += (cartesian(this.frame + this.frameoffset)[0] * this.dd) / (this.getDelta() * 15);
425 | } else if (this.horizontal) {
426 | // apply VERTICAL drift ~ when "direction" is mostly horizontal.
427 | this.py += (cartesian(this.frame + this.frameoffset)[1] * this.dd) / (this.getDelta() * 15);
428 | }
429 | }
430 | };
431 |
432 | Sparticle.prototype.render = function(canvasses) {
433 | let particleCanvas;
434 | if (this.shape !== "image") {
435 | particleCanvas = canvasses[this.color][this.shape][this.style];
436 | } else {
437 | particleCanvas = canvasses[this.color][this.shape][this.image];
438 | }
439 | const canvasSize = particleCanvas.width;
440 | const scale = this.size / canvasSize;
441 | const px = this.px / scale;
442 | const py = this.py / scale;
443 | this.ctx.globalAlpha = clamp(this.alpha, 0, 1);
444 | this.renderRotate();
445 | this.ctx.transform(scale, 0, 0, scale, 0, 0);
446 | this.ctx.drawImage(particleCanvas, 0, 0, canvasSize, canvasSize, px, py, canvasSize, canvasSize);
447 | this.ctx.setTransform(1, 0, 0, 1, 0, 0);
448 | return this;
449 | };
450 |
451 | Sparticle.prototype.renderRotate = function() {
452 | if (this.shape !== "circle" && this.settings.rotate) {
453 | const centerX = this.px + this.size / 2;
454 | const centerY = this.py + this.size / 2;
455 | this.ctx.translate(centerX, centerY);
456 | this.ctx.rotate(this.rotation);
457 | this.ctx.translate(-centerX, -centerY);
458 | }
459 | };
460 |
--------------------------------------------------------------------------------
/example/sveltekit/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@iarna/toml@^2.2.5":
6 | version "2.2.5"
7 | resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.5.tgz#b32366c89b43c6f8cefbdefac778b9c828e3ba8c"
8 | integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==
9 |
10 | "@rollup/pluginutils@^4.1.1":
11 | version "4.1.2"
12 | resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.1.2.tgz#ed5821c15e5e05e32816f5fb9ec607cdf5a75751"
13 | integrity sha512-ROn4qvkxP9SyPeHaf7uQC/GPFY6L/OWy9+bd9AwcjOAWQwxRscoEyAUD8qCY5o5iL4jqQwoLk2kaTKJPb/HwzQ==
14 | dependencies:
15 | estree-walker "^2.0.1"
16 | picomatch "^2.2.2"
17 |
18 | "@sveltejs/adapter-auto@next":
19 | version "1.0.0-next.4"
20 | resolved "https://registry.yarnpkg.com/@sveltejs/adapter-auto/-/adapter-auto-1.0.0-next.4.tgz#c87a05f110cf23062953269423be8f7809d84da1"
21 | integrity sha512-kfygrjF2uIgVVDsySl7I9oWSekU6adJCr/3qzLQDLM4FJ98FWmfhj4OOWsmF9X4JRPSm97t3RPugYsN3NLwKMQ==
22 | dependencies:
23 | "@sveltejs/adapter-cloudflare" "1.0.0-next.3"
24 | "@sveltejs/adapter-netlify" "1.0.0-next.36"
25 | "@sveltejs/adapter-vercel" "1.0.0-next.32"
26 |
27 | "@sveltejs/adapter-cloudflare@1.0.0-next.3":
28 | version "1.0.0-next.3"
29 | resolved "https://registry.yarnpkg.com/@sveltejs/adapter-cloudflare/-/adapter-cloudflare-1.0.0-next.3.tgz#2c89eb9baba40e1ce63e85412571cbd4e3ded0f4"
30 | integrity sha512-LauvvkBFCE8myGMLWOncv97/xU8JJn9OMl1miy8f/q8qs0CrduvR1sv2uCM9AylqT/FNPy3mony5wpe3w1v7sg==
31 | dependencies:
32 | esbuild "^0.13.15"
33 |
34 | "@sveltejs/adapter-netlify@1.0.0-next.36":
35 | version "1.0.0-next.36"
36 | resolved "https://registry.yarnpkg.com/@sveltejs/adapter-netlify/-/adapter-netlify-1.0.0-next.36.tgz#a1037f67940fce59c49aa64854843d428f55c49c"
37 | integrity sha512-LdrIXCTBnIubtt/lthcnyt5VljuHpZlVzUqpWXk9Eu6bpNKblqQLMHkTBQfIbPfanmNSDZXJQVsdcFLqF2/+Cw==
38 | dependencies:
39 | "@iarna/toml" "^2.2.5"
40 | esbuild "^0.13.15"
41 |
42 | "@sveltejs/adapter-vercel@1.0.0-next.32":
43 | version "1.0.0-next.32"
44 | resolved "https://registry.yarnpkg.com/@sveltejs/adapter-vercel/-/adapter-vercel-1.0.0-next.32.tgz#90a8c1078a477a81d16cfd0efb27e5df2dc90189"
45 | integrity sha512-ZcltaS5bAobGD5P0z7xJIjPHSlGpF7padMIkqTzJxwMEb/acGgdO5yzDS8XUEaSNgj+prpD2oG8+gm33ds8x0A==
46 | dependencies:
47 | esbuild "^0.13.15"
48 |
49 | "@sveltejs/kit@next":
50 | version "1.0.0-next.202"
51 | resolved "https://registry.yarnpkg.com/@sveltejs/kit/-/kit-1.0.0-next.202.tgz#7438bc1b20c1acdd611588c3c1c1470959b2a251"
52 | integrity sha512-rXmJ0FplkWvD1CaeCfejRYhOJYrlmeUm5Fkw7gIKDdWPQev5rqOhd9B9ZvRpq35oMqCAwaOfK+e5S6k+83feEQ==
53 | dependencies:
54 | "@sveltejs/vite-plugin-svelte" "^1.0.0-next.30"
55 | cheap-watch "^1.0.4"
56 | sade "^1.7.4"
57 | vite "^2.7.2"
58 |
59 | "@sveltejs/vite-plugin-svelte@^1.0.0-next.30":
60 | version "1.0.0-next.32"
61 | resolved "https://registry.yarnpkg.com/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.0-next.32.tgz#bafcb15dfa7832566dac2b8a67ac6b03e2be5ef6"
62 | integrity sha512-Lhf5BxVylosHIW6U2s6WDQA39ycd+bXivC8gHsXCJeLzxoHj7Pv7XAOk25xRSXT4wHg9DWFMBQh2DFU0DxHZ2g==
63 | dependencies:
64 | "@rollup/pluginutils" "^4.1.1"
65 | debug "^4.3.3"
66 | kleur "^4.1.4"
67 | magic-string "^0.25.7"
68 | require-relative "^0.8.7"
69 | svelte-hmr "^0.14.7"
70 |
71 | cheap-watch@^1.0.4:
72 | version "1.0.4"
73 | resolved "https://registry.yarnpkg.com/cheap-watch/-/cheap-watch-1.0.4.tgz#0bcb4a3a8fbd9d5327936493f6b56baa668d8fef"
74 | integrity sha512-QR/9FrtRL5fjfUJBhAKCdi0lSRQ3rVRRum3GF9wDKp2TJbEIMGhUEr2yU8lORzm9Isdjx7/k9S0DFDx+z5VGtw==
75 |
76 | debug@^4.3.3:
77 | version "4.3.3"
78 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
79 | integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==
80 | dependencies:
81 | ms "2.1.2"
82 |
83 | esbuild-android-arm64@0.13.15:
84 | version "0.13.15"
85 | resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.13.15.tgz#3fc3ff0bab76fe35dd237476b5d2b32bb20a3d44"
86 | integrity sha512-m602nft/XXeO8YQPUDVoHfjyRVPdPgjyyXOxZ44MK/agewFFkPa8tUo6lAzSWh5Ui5PB4KR9UIFTSBKh/RrCmg==
87 |
88 | esbuild-darwin-64@0.13.15:
89 | version "0.13.15"
90 | resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.13.15.tgz#8e9169c16baf444eacec60d09b24d11b255a8e72"
91 | integrity sha512-ihOQRGs2yyp7t5bArCwnvn2Atr6X4axqPpEdCFPVp7iUj4cVSdisgvEKdNR7yH3JDjW6aQDw40iQFoTqejqxvQ==
92 |
93 | esbuild-darwin-arm64@0.13.15:
94 | version "0.13.15"
95 | resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.15.tgz#1b07f893b632114f805e188ddfca41b2b778229a"
96 | integrity sha512-i1FZssTVxUqNlJ6cBTj5YQj4imWy3m49RZRnHhLpefFIh0To05ow9DTrXROTE1urGTQCloFUXTX8QfGJy1P8dQ==
97 |
98 | esbuild-freebsd-64@0.13.15:
99 | version "0.13.15"
100 | resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.15.tgz#0b8b7eca1690c8ec94c75680c38c07269c1f4a85"
101 | integrity sha512-G3dLBXUI6lC6Z09/x+WtXBXbOYQZ0E8TDBqvn7aMaOCzryJs8LyVXKY4CPnHFXZAbSwkCbqiPuSQ1+HhrNk7EA==
102 |
103 | esbuild-freebsd-arm64@0.13.15:
104 | version "0.13.15"
105 | resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.15.tgz#2e1a6c696bfdcd20a99578b76350b41db1934e52"
106 | integrity sha512-KJx0fzEDf1uhNOZQStV4ujg30WlnwqUASaGSFPhznLM/bbheu9HhqZ6mJJZM32lkyfGJikw0jg7v3S0oAvtvQQ==
107 |
108 | esbuild-linux-32@0.13.15:
109 | version "0.13.15"
110 | resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.13.15.tgz#6fd39f36fc66dd45b6b5f515728c7bbebc342a69"
111 | integrity sha512-ZvTBPk0YWCLMCXiFmD5EUtB30zIPvC5Itxz0mdTu/xZBbbHJftQgLWY49wEPSn2T/TxahYCRDWun5smRa0Tu+g==
112 |
113 | esbuild-linux-64@0.13.15:
114 | version "0.13.15"
115 | resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.13.15.tgz#9cb8e4bcd7574e67946e4ee5f1f1e12386bb6dd3"
116 | integrity sha512-eCKzkNSLywNeQTRBxJRQ0jxRCl2YWdMB3+PkWFo2BBQYC5mISLIVIjThNtn6HUNqua1pnvgP5xX0nHbZbPj5oA==
117 |
118 | esbuild-linux-arm64@0.13.15:
119 | version "0.13.15"
120 | resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.15.tgz#3891aa3704ec579a1b92d2a586122e5b6a2bfba1"
121 | integrity sha512-bYpuUlN6qYU9slzr/ltyLTR9YTBS7qUDymO8SV7kjeNext61OdmqFAzuVZom+OLW1HPHseBfJ/JfdSlx8oTUoA==
122 |
123 | esbuild-linux-arm@0.13.15:
124 | version "0.13.15"
125 | resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.13.15.tgz#8a00e99e6a0c6c9a6b7f334841364d8a2b4aecfe"
126 | integrity sha512-wUHttDi/ol0tD8ZgUMDH8Ef7IbDX+/UsWJOXaAyTdkT7Yy9ZBqPg8bgB/Dn3CZ9SBpNieozrPRHm0BGww7W/jA==
127 |
128 | esbuild-linux-mips64le@0.13.15:
129 | version "0.13.15"
130 | resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.15.tgz#36b07cc47c3d21e48db3bb1f4d9ef8f46aead4f7"
131 | integrity sha512-KlVjIG828uFPyJkO/8gKwy9RbXhCEUeFsCGOJBepUlpa7G8/SeZgncUEz/tOOUJTcWMTmFMtdd3GElGyAtbSWg==
132 |
133 | esbuild-linux-ppc64le@0.13.15:
134 | version "0.13.15"
135 | resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.15.tgz#f7e6bba40b9a11eb9dcae5b01550ea04670edad2"
136 | integrity sha512-h6gYF+OsaqEuBjeesTBtUPw0bmiDu7eAeuc2OEH9S6mV9/jPhPdhOWzdeshb0BskRZxPhxPOjqZ+/OqLcxQwEQ==
137 |
138 | esbuild-netbsd-64@0.13.15:
139 | version "0.13.15"
140 | resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.15.tgz#a2fedc549c2b629d580a732d840712b08d440038"
141 | integrity sha512-3+yE9emwoevLMyvu+iR3rsa+Xwhie7ZEHMGDQ6dkqP/ndFzRHkobHUKTe+NCApSqG5ce2z4rFu+NX/UHnxlh3w==
142 |
143 | esbuild-openbsd-64@0.13.15:
144 | version "0.13.15"
145 | resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.15.tgz#b22c0e5806d3a1fbf0325872037f885306b05cd7"
146 | integrity sha512-wTfvtwYJYAFL1fSs8yHIdf5GEE4NkbtbXtjLWjM3Cw8mmQKqsg8kTiqJ9NJQe5NX/5Qlo7Xd9r1yKMMkHllp5g==
147 |
148 | esbuild-sunos-64@0.13.15:
149 | version "0.13.15"
150 | resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.13.15.tgz#d0b6454a88375ee8d3964daeff55c85c91c7cef4"
151 | integrity sha512-lbivT9Bx3t1iWWrSnGyBP9ODriEvWDRiweAs69vI+miJoeKwHWOComSRukttbuzjZ8r1q0mQJ8Z7yUsDJ3hKdw==
152 |
153 | esbuild-windows-32@0.13.15:
154 | version "0.13.15"
155 | resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.13.15.tgz#c96d0b9bbb52f3303322582ef8e4847c5ad375a7"
156 | integrity sha512-fDMEf2g3SsJ599MBr50cY5ve5lP1wyVwTe6aLJsM01KtxyKkB4UT+fc5MXQFn3RLrAIAZOG+tHC+yXObpSn7Nw==
157 |
158 | esbuild-windows-64@0.13.15:
159 | version "0.13.15"
160 | resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.13.15.tgz#1f79cb9b1e1bb02fb25cd414cb90d4ea2892c294"
161 | integrity sha512-9aMsPRGDWCd3bGjUIKG/ZOJPKsiztlxl/Q3C1XDswO6eNX/Jtwu4M+jb6YDH9hRSUflQWX0XKAfWzgy5Wk54JQ==
162 |
163 | esbuild-windows-arm64@0.13.15:
164 | version "0.13.15"
165 | resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.15.tgz#482173070810df22a752c686509c370c3be3b3c3"
166 | integrity sha512-zzvyCVVpbwQQATaf3IG8mu1IwGEiDxKkYUdA4FpoCHi1KtPa13jeScYDjlW0Qh+ebWzpKfR2ZwvqAQkSWNcKjA==
167 |
168 | esbuild@^0.13.12, esbuild@^0.13.15:
169 | version "0.13.15"
170 | resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.13.15.tgz#db56a88166ee373f87dbb2d8798ff449e0450cdf"
171 | integrity sha512-raCxt02HBKv8RJxE8vkTSCXGIyKHdEdGfUmiYb8wnabnaEmHzyW7DCHb5tEN0xU8ryqg5xw54mcwnYkC4x3AIw==
172 | optionalDependencies:
173 | esbuild-android-arm64 "0.13.15"
174 | esbuild-darwin-64 "0.13.15"
175 | esbuild-darwin-arm64 "0.13.15"
176 | esbuild-freebsd-64 "0.13.15"
177 | esbuild-freebsd-arm64 "0.13.15"
178 | esbuild-linux-32 "0.13.15"
179 | esbuild-linux-64 "0.13.15"
180 | esbuild-linux-arm "0.13.15"
181 | esbuild-linux-arm64 "0.13.15"
182 | esbuild-linux-mips64le "0.13.15"
183 | esbuild-linux-ppc64le "0.13.15"
184 | esbuild-netbsd-64 "0.13.15"
185 | esbuild-openbsd-64 "0.13.15"
186 | esbuild-sunos-64 "0.13.15"
187 | esbuild-windows-32 "0.13.15"
188 | esbuild-windows-64 "0.13.15"
189 | esbuild-windows-arm64 "0.13.15"
190 |
191 | estree-walker@^2.0.1:
192 | version "2.0.2"
193 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
194 | integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
195 |
196 | fsevents@~2.3.2:
197 | version "2.3.2"
198 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
199 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
200 |
201 | function-bind@^1.1.1:
202 | version "1.1.1"
203 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
204 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
205 |
206 | has@^1.0.3:
207 | version "1.0.3"
208 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
209 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
210 | dependencies:
211 | function-bind "^1.1.1"
212 |
213 | is-core-module@^2.2.0:
214 | version "2.8.0"
215 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548"
216 | integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==
217 | dependencies:
218 | has "^1.0.3"
219 |
220 | kleur@^4.1.4:
221 | version "4.1.4"
222 | resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.4.tgz#8c202987d7e577766d039a8cd461934c01cda04d"
223 | integrity sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==
224 |
225 | magic-string@^0.25.7:
226 | version "0.25.7"
227 | resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
228 | integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==
229 | dependencies:
230 | sourcemap-codec "^1.4.4"
231 |
232 | mri@^1.1.0:
233 | version "1.2.0"
234 | resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b"
235 | integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==
236 |
237 | ms@2.1.2:
238 | version "2.1.2"
239 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
240 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
241 |
242 | nanoid@^3.1.30:
243 | version "3.1.30"
244 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362"
245 | integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==
246 |
247 | path-parse@^1.0.6:
248 | version "1.0.7"
249 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
250 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
251 |
252 | picocolors@^1.0.0:
253 | version "1.0.0"
254 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
255 | integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
256 |
257 | picomatch@^2.2.2:
258 | version "2.3.0"
259 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
260 | integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
261 |
262 | postcss@^8.4.5:
263 | version "8.4.5"
264 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95"
265 | integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==
266 | dependencies:
267 | nanoid "^3.1.30"
268 | picocolors "^1.0.0"
269 | source-map-js "^1.0.1"
270 |
271 | require-relative@^0.8.7:
272 | version "0.8.7"
273 | resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de"
274 | integrity sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=
275 |
276 | resolve@^1.20.0:
277 | version "1.20.0"
278 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
279 | integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
280 | dependencies:
281 | is-core-module "^2.2.0"
282 | path-parse "^1.0.6"
283 |
284 | rollup@^2.59.0:
285 | version "2.61.1"
286 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.61.1.tgz#1a5491f84543cf9e4caf6c61222d9a3f8f2ba454"
287 | integrity sha512-BbTXlEvB8d+XFbK/7E5doIcRtxWPRiqr0eb5vQ0+2paMM04Ye4PZY5nHOQef2ix24l/L0SpLd5hwcH15QHPdvA==
288 | optionalDependencies:
289 | fsevents "~2.3.2"
290 |
291 | sade@^1.7.4:
292 | version "1.7.4"
293 | resolved "https://registry.yarnpkg.com/sade/-/sade-1.7.4.tgz#ea681e0c65d248d2095c90578c03ca0bb1b54691"
294 | integrity sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==
295 | dependencies:
296 | mri "^1.1.0"
297 |
298 | source-map-js@^1.0.1:
299 | version "1.0.1"
300 | resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.1.tgz#a1741c131e3c77d048252adfa24e23b908670caf"
301 | integrity sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA==
302 |
303 | sourcemap-codec@^1.4.4:
304 | version "1.4.8"
305 | resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
306 | integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
307 |
308 | svelte-hmr@^0.14.7:
309 | version "0.14.7"
310 | resolved "https://registry.yarnpkg.com/svelte-hmr/-/svelte-hmr-0.14.7.tgz#7fa8261c7b225d9409f0a86f3b9ea5c3ca6f6607"
311 | integrity sha512-pDrzgcWSoMaK6AJkBWkmgIsecW0GChxYZSZieIYfCP0v2oPyx2CYU/zm7TBIcjLVUPP714WxmViE9Thht4etog==
312 |
313 | svelte@^3.44.0:
314 | version "3.44.3"
315 | resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.44.3.tgz#795b1ced6ed3da44969099e5061b850c93c95e9a"
316 | integrity sha512-aGgrNCip5PQFNfq9e9tmm7EYxWLVHoFsEsmKrtOeRD8dmoGDdyTQ+21xd7qgFd8MNdKGSYvg7F9dr+Tc0yDymg==
317 |
318 | vite@^2.7.2:
319 | version "2.7.4"
320 | resolved "https://registry.yarnpkg.com/vite/-/vite-2.7.4.tgz#06f68f8909943f9fe582c26120b0c2b85894a05e"
321 | integrity sha512-f+0426k9R/roz5mRNwJlQ+6UOnhCwIypJSbfgCmsVzVJe9jTTM5iRX2GWYUean+iqPBWaU/dYLryx9AoH2pmrw==
322 | dependencies:
323 | esbuild "^0.13.12"
324 | postcss "^8.4.5"
325 | resolve "^1.20.0"
326 | rollup "^2.59.0"
327 | optionalDependencies:
328 | fsevents "~2.3.2"
329 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Mozilla Public License Version 2.0
2 | ==================================
3 |
4 | 1. Definitions
5 | --------------
6 |
7 | 1.1. "Contributor"
8 | means each individual or legal entity that creates, contributes to
9 | the creation of, or owns Covered Software.
10 |
11 | 1.2. "Contributor Version"
12 | means the combination of the Contributions of others (if any) used
13 | by a Contributor and that particular Contributor's Contribution.
14 |
15 | 1.3. "Contribution"
16 | means Covered Software of a particular Contributor.
17 |
18 | 1.4. "Covered Software"
19 | means Source Code Form to which the initial Contributor has attached
20 | the notice in Exhibit A, the Executable Form of such Source Code
21 | Form, and Modifications of such Source Code Form, in each case
22 | including portions thereof.
23 |
24 | 1.5. "Incompatible With Secondary Licenses"
25 | means
26 |
27 | (a) that the initial Contributor has attached the notice described
28 | in Exhibit B to the Covered Software; or
29 |
30 | (b) that the Covered Software was made available under the terms of
31 | version 1.1 or earlier of the License, but not also under the
32 | terms of a Secondary License.
33 |
34 | 1.6. "Executable Form"
35 | means any form of the work other than Source Code Form.
36 |
37 | 1.7. "Larger Work"
38 | means a work that combines Covered Software with other material, in
39 | a separate file or files, that is not Covered Software.
40 |
41 | 1.8. "License"
42 | means this document.
43 |
44 | 1.9. "Licensable"
45 | means having the right to grant, to the maximum extent possible,
46 | whether at the time of the initial grant or subsequently, any and
47 | all of the rights conveyed by this License.
48 |
49 | 1.10. "Modifications"
50 | means any of the following:
51 |
52 | (a) any file in Source Code Form that results from an addition to,
53 | deletion from, or modification of the contents of Covered
54 | Software; or
55 |
56 | (b) any new file in Source Code Form that contains any Covered
57 | Software.
58 |
59 | 1.11. "Patent Claims" of a Contributor
60 | means any patent claim(s), including without limitation, method,
61 | process, and apparatus claims, in any patent Licensable by such
62 | Contributor that would be infringed, but for the grant of the
63 | License, by the making, using, selling, offering for sale, having
64 | made, import, or transfer of either its Contributions or its
65 | Contributor Version.
66 |
67 | 1.12. "Secondary License"
68 | means either the GNU General Public License, Version 2.0, the GNU
69 | Lesser General Public License, Version 2.1, the GNU Affero General
70 | Public License, Version 3.0, or any later versions of those
71 | licenses.
72 |
73 | 1.13. "Source Code Form"
74 | means the form of the work preferred for making modifications.
75 |
76 | 1.14. "You" (or "Your")
77 | means an individual or a legal entity exercising rights under this
78 | License. For legal entities, "You" includes any entity that
79 | controls, is controlled by, or is under common control with You. For
80 | purposes of this definition, "control" means (a) the power, direct
81 | or indirect, to cause the direction or management of such entity,
82 | whether by contract or otherwise, or (b) ownership of more than
83 | fifty percent (50%) of the outstanding shares or beneficial
84 | ownership of such entity.
85 |
86 | 2. License Grants and Conditions
87 | --------------------------------
88 |
89 | 2.1. Grants
90 |
91 | Each Contributor hereby grants You a world-wide, royalty-free,
92 | non-exclusive license:
93 |
94 | (a) under intellectual property rights (other than patent or trademark)
95 | Licensable by such Contributor to use, reproduce, make available,
96 | modify, display, perform, distribute, and otherwise exploit its
97 | Contributions, either on an unmodified basis, with Modifications, or
98 | as part of a Larger Work; and
99 |
100 | (b) under Patent Claims of such Contributor to make, use, sell, offer
101 | for sale, have made, import, and otherwise transfer either its
102 | Contributions or its Contributor Version.
103 |
104 | 2.2. Effective Date
105 |
106 | The licenses granted in Section 2.1 with respect to any Contribution
107 | become effective for each Contribution on the date the Contributor first
108 | distributes such Contribution.
109 |
110 | 2.3. Limitations on Grant Scope
111 |
112 | The licenses granted in this Section 2 are the only rights granted under
113 | this License. No additional rights or licenses will be implied from the
114 | distribution or licensing of Covered Software under this License.
115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a
116 | Contributor:
117 |
118 | (a) for any code that a Contributor has removed from Covered Software;
119 | or
120 |
121 | (b) for infringements caused by: (i) Your and any other third party's
122 | modifications of Covered Software, or (ii) the combination of its
123 | Contributions with other software (except as part of its Contributor
124 | Version); or
125 |
126 | (c) under Patent Claims infringed by Covered Software in the absence of
127 | its Contributions.
128 |
129 | This License does not grant any rights in the trademarks, service marks,
130 | or logos of any Contributor (except as may be necessary to comply with
131 | the notice requirements in Section 3.4).
132 |
133 | 2.4. Subsequent Licenses
134 |
135 | No Contributor makes additional grants as a result of Your choice to
136 | distribute the Covered Software under a subsequent version of this
137 | License (see Section 10.2) or under the terms of a Secondary License (if
138 | permitted under the terms of Section 3.3).
139 |
140 | 2.5. Representation
141 |
142 | Each Contributor represents that the Contributor believes its
143 | Contributions are its original creation(s) or it has sufficient rights
144 | to grant the rights to its Contributions conveyed by this License.
145 |
146 | 2.6. Fair Use
147 |
148 | This License is not intended to limit any rights You have under
149 | applicable copyright doctrines of fair use, fair dealing, or other
150 | equivalents.
151 |
152 | 2.7. Conditions
153 |
154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
155 | in Section 2.1.
156 |
157 | 3. Responsibilities
158 | -------------------
159 |
160 | 3.1. Distribution of Source Form
161 |
162 | All distribution of Covered Software in Source Code Form, including any
163 | Modifications that You create or to which You contribute, must be under
164 | the terms of this License. You must inform recipients that the Source
165 | Code Form of the Covered Software is governed by the terms of this
166 | License, and how they can obtain a copy of this License. You may not
167 | attempt to alter or restrict the recipients' rights in the Source Code
168 | Form.
169 |
170 | 3.2. Distribution of Executable Form
171 |
172 | If You distribute Covered Software in Executable Form then:
173 |
174 | (a) such Covered Software must also be made available in Source Code
175 | Form, as described in Section 3.1, and You must inform recipients of
176 | the Executable Form how they can obtain a copy of such Source Code
177 | Form by reasonable means in a timely manner, at a charge no more
178 | than the cost of distribution to the recipient; and
179 |
180 | (b) You may distribute such Executable Form under the terms of this
181 | License, or sublicense it under different terms, provided that the
182 | license for the Executable Form does not attempt to limit or alter
183 | the recipients' rights in the Source Code Form under this License.
184 |
185 | 3.3. Distribution of a Larger Work
186 |
187 | You may create and distribute a Larger Work under terms of Your choice,
188 | provided that You also comply with the requirements of this License for
189 | the Covered Software. If the Larger Work is a combination of Covered
190 | Software with a work governed by one or more Secondary Licenses, and the
191 | Covered Software is not Incompatible With Secondary Licenses, this
192 | License permits You to additionally distribute such Covered Software
193 | under the terms of such Secondary License(s), so that the recipient of
194 | the Larger Work may, at their option, further distribute the Covered
195 | Software under the terms of either this License or such Secondary
196 | License(s).
197 |
198 | 3.4. Notices
199 |
200 | You may not remove or alter the substance of any license notices
201 | (including copyright notices, patent notices, disclaimers of warranty,
202 | or limitations of liability) contained within the Source Code Form of
203 | the Covered Software, except that You may alter any license notices to
204 | the extent required to remedy known factual inaccuracies.
205 |
206 | 3.5. Application of Additional Terms
207 |
208 | You may choose to offer, and to charge a fee for, warranty, support,
209 | indemnity or liability obligations to one or more recipients of Covered
210 | Software. However, You may do so only on Your own behalf, and not on
211 | behalf of any Contributor. You must make it absolutely clear that any
212 | such warranty, support, indemnity, or liability obligation is offered by
213 | You alone, and You hereby agree to indemnify every Contributor for any
214 | liability incurred by such Contributor as a result of warranty, support,
215 | indemnity or liability terms You offer. You may include additional
216 | disclaimers of warranty and limitations of liability specific to any
217 | jurisdiction.
218 |
219 | 4. Inability to Comply Due to Statute or Regulation
220 | ---------------------------------------------------
221 |
222 | If it is impossible for You to comply with any of the terms of this
223 | License with respect to some or all of the Covered Software due to
224 | statute, judicial order, or regulation then You must: (a) comply with
225 | the terms of this License to the maximum extent possible; and (b)
226 | describe the limitations and the code they affect. Such description must
227 | be placed in a text file included with all distributions of the Covered
228 | Software under this License. Except to the extent prohibited by statute
229 | or regulation, such description must be sufficiently detailed for a
230 | recipient of ordinary skill to be able to understand it.
231 |
232 | 5. Termination
233 | --------------
234 |
235 | 5.1. The rights granted under this License will terminate automatically
236 | if You fail to comply with any of its terms. However, if You become
237 | compliant, then the rights granted under this License from a particular
238 | Contributor are reinstated (a) provisionally, unless and until such
239 | Contributor explicitly and finally terminates Your grants, and (b) on an
240 | ongoing basis, if such Contributor fails to notify You of the
241 | non-compliance by some reasonable means prior to 60 days after You have
242 | come back into compliance. Moreover, Your grants from a particular
243 | Contributor are reinstated on an ongoing basis if such Contributor
244 | notifies You of the non-compliance by some reasonable means, this is the
245 | first time You have received notice of non-compliance with this License
246 | from such Contributor, and You become compliant prior to 30 days after
247 | Your receipt of the notice.
248 |
249 | 5.2. If You initiate litigation against any entity by asserting a patent
250 | infringement claim (excluding declaratory judgment actions,
251 | counter-claims, and cross-claims) alleging that a Contributor Version
252 | directly or indirectly infringes any patent, then the rights granted to
253 | You by any and all Contributors for the Covered Software under Section
254 | 2.1 of this License shall terminate.
255 |
256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
257 | end user license agreements (excluding distributors and resellers) which
258 | have been validly granted by You or Your distributors under this License
259 | prior to termination shall survive termination.
260 |
261 | ************************************************************************
262 | * *
263 | * 6. Disclaimer of Warranty *
264 | * ------------------------- *
265 | * *
266 | * Covered Software is provided under this License on an "as is" *
267 | * basis, without warranty of any kind, either expressed, implied, or *
268 | * statutory, including, without limitation, warranties that the *
269 | * Covered Software is free of defects, merchantable, fit for a *
270 | * particular purpose or non-infringing. The entire risk as to the *
271 | * quality and performance of the Covered Software is with You. *
272 | * Should any Covered Software prove defective in any respect, You *
273 | * (not any Contributor) assume the cost of any necessary servicing, *
274 | * repair, or correction. This disclaimer of warranty constitutes an *
275 | * essential part of this License. No use of any Covered Software is *
276 | * authorized under this License except under this disclaimer. *
277 | * *
278 | ************************************************************************
279 |
280 | ************************************************************************
281 | * *
282 | * 7. Limitation of Liability *
283 | * -------------------------- *
284 | * *
285 | * Under no circumstances and under no legal theory, whether tort *
286 | * (including negligence), contract, or otherwise, shall any *
287 | * Contributor, or anyone who distributes Covered Software as *
288 | * permitted above, be liable to You for any direct, indirect, *
289 | * special, incidental, or consequential damages of any character *
290 | * including, without limitation, damages for lost profits, loss of *
291 | * goodwill, work stoppage, computer failure or malfunction, or any *
292 | * and all other commercial damages or losses, even if such party *
293 | * shall have been informed of the possibility of such damages. This *
294 | * limitation of liability shall not apply to liability for death or *
295 | * personal injury resulting from such party's negligence to the *
296 | * extent applicable law prohibits such limitation. Some *
297 | * jurisdictions do not allow the exclusion or limitation of *
298 | * incidental or consequential damages, so this exclusion and *
299 | * limitation may not apply to You. *
300 | * *
301 | ************************************************************************
302 |
303 | 8. Litigation
304 | -------------
305 |
306 | Any litigation relating to this License may be brought only in the
307 | courts of a jurisdiction where the defendant maintains its principal
308 | place of business and such litigation shall be governed by laws of that
309 | jurisdiction, without reference to its conflict-of-law provisions.
310 | Nothing in this Section shall prevent a party's ability to bring
311 | cross-claims or counter-claims.
312 |
313 | 9. Miscellaneous
314 | ----------------
315 |
316 | This License represents the complete agreement concerning the subject
317 | matter hereof. If any provision of this License is held to be
318 | unenforceable, such provision shall be reformed only to the extent
319 | necessary to make it enforceable. Any law or regulation which provides
320 | that the language of a contract shall be construed against the drafter
321 | shall not be used to construe this License against a Contributor.
322 |
323 | 10. Versions of the License
324 | ---------------------------
325 |
326 | 10.1. New Versions
327 |
328 | Mozilla Foundation is the license steward. Except as provided in Section
329 | 10.3, no one other than the license steward has the right to modify or
330 | publish new versions of this License. Each version will be given a
331 | distinguishing version number.
332 |
333 | 10.2. Effect of New Versions
334 |
335 | You may distribute the Covered Software under the terms of the version
336 | of the License under which You originally received the Covered Software,
337 | or under the terms of any subsequent version published by the license
338 | steward.
339 |
340 | 10.3. Modified Versions
341 |
342 | If you create software not governed by this License, and you want to
343 | create a new license for such software, you may create and use a
344 | modified version of this License if you rename the license and remove
345 | any references to the name of the license steward (except to note that
346 | such modified license differs from this License).
347 |
348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary
349 | Licenses
350 |
351 | If You choose to distribute Source Code Form that is Incompatible With
352 | Secondary Licenses under the terms of this version of the License, the
353 | notice described in Exhibit B of this License must be attached.
354 |
355 | Exhibit A - Source Code Form License Notice
356 | -------------------------------------------
357 |
358 | This Source Code Form is subject to the terms of the Mozilla Public
359 | License, v. 2.0. If a copy of the MPL was not distributed with this
360 | file, You can obtain one at http://mozilla.org/MPL/2.0/.
361 |
362 | If it is not possible or desirable to put the notice in a particular
363 | file, then You may include the notice in a location (such as a LICENSE
364 | file in a relevant directory) where a recipient would be likely to look
365 | for such a notice.
366 |
367 | You may add additional accurate notices of copyright ownership.
368 |
369 | Exhibit B - "Incompatible With Secondary Licenses" Notice
370 | ---------------------------------------------------------
371 |
372 | This Source Code Form is "Incompatible With Secondary Licenses", as
373 | defined by the Mozilla Public License, v. 2.0.
374 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Sparticles
2 | ### javascript particles in canvas
3 |
4 | #### https://sparticlesjs.dev
5 |
6 | **Lightweight, _High Performance_ Particles in Canvas.**
7 | For those occasions when you ***👏 just 👏 gotta 👏 have 👏*** sparkles,
8 | snow, or stars on your homepage!
9 |
10 | 
11 |
12 |
13 | ---
14 |
15 | - [installation](#installation)
16 | - [parameters](#parameters)
17 | - [options](#options)
18 | - [methods](#methods)
19 | - [styling](#styling)
20 | - [performance](#performance)
21 | - [why?](#why-sparticles-)
22 |
23 | ---
24 |
25 |
26 | # installation
27 |
28 | Depending on how your project looks,
29 | - you may want to [include a direct link to the script](#vanilla) and
30 | then initialise the sparkles,
31 | - or you may want
32 | to [import the module in to your application](#app--bundler) for a more modern approach.
33 |
34 | ## vanilla
35 |
36 | 1. firstly make sure you've downloaded [the latest version of the script](https://github.com/simeydotme/sparticles/releases)
37 | to your application directory _(if you are running on a CMS you might also
38 | need to upload the file to your server)_. The file you'll want to use is; `dist/sparticles.min.js`
39 | to make sure it downloads the fastest for your users.
40 |
41 | 2. After you've downloaded, or uploaded, the `sparticles.min.js` file to the
42 | correct place, you'll then need to include it in your web page;
43 |
44 | ```html
45 |
46 | ```
47 |
48 | 3. And finally, you should then be able to initialise the Sparticles by
49 | running this code in your javascript;
50 | _(make sure this code runs _after_ you've included the script above.)_
51 |
52 | ```html
53 |
59 | ```
60 |
61 | ## jquery
62 |
63 | For jQuery sites, you may follow all of the steps above, but replace
64 | the third step with something like below;
65 |
66 | ```html
67 |
71 | ```
72 |
73 | ## app / bundler
74 |
75 | If you're running a more modern type of application with something like Svelte or VueJs;
76 |
77 | 1. First you will want to install the module with NPM;
78 |
79 | ```bash
80 | yarn add --dev sparticles
81 | # or npm, if you prefer
82 | npm install --save-dev sparticles
83 | ```
84 |
85 | 2. Then import the module in to the app where you want to use it
86 |
87 | ```js
88 | import Sparticles from "sparticles";
89 | ```
90 |
91 | 3. Finally initialise with vanillaJS
92 |
93 | ```js
94 | new Sparticles(node, { count: 100 }, 400);
95 | ```
96 |
97 | 4. If you're using SvelteJS specifically, then your single-file component
98 | would look a little like this;
99 |
100 | ```html
101 |
113 |
114 |
115 |
116 | ```
117 |
118 | # usage
119 |
120 | Providing that the script/module has been properly included, then it can be initialised
121 | by running the `Sparticles()` constructor;
122 | ```js
123 | let mySparticles = new Sparticles();
124 | ```
125 |
126 | # parameters
127 |
128 | When initialising the Sparticles instance there are some parameters that can be supplied.
129 |
130 | parameter | type | default | description
131 | ----------------------------|--------------------|--------------------|-----------------------------------------------------------
132 | **node** | `HTMLElement` | `document.body` | the element in the DOM which the Sparticles will append to
133 | **[options](#options)** | `Object` | `{}` | an object with [all the options for the instance](#options)
134 | **width** | `Number` | `node.clientWidth` | the width of the canvas element
135 | **height** | `Number` | `node.clientWidth` | the height of the canvas element (defaults to width)
136 |
137 | Leave the `width`/`height` properties empty to make the canvas resize to fit it's `node`
138 |
139 | ---
140 |
141 | - Supply nothing and get a default Sparticle instance on the ``
142 | ```js
143 | let mySparticles = new Sparticles();
144 | ```
145 |
146 | - Supply a single HTMLElement parameter for a default Sparticle instance on that element
147 | ```js
148 | let mySparticles = new Sparticles(document.getElementById("myDiv"));
149 | ```
150 |
151 | - Supply a single `Object` parameter to customise a Sparticle instance on the ``
152 | ```js
153 | let mySparticles = new Sparticles({ color: "red" });
154 | ```
155 |
156 | - Supply the width and height parameters for a custom size
157 | ```js
158 | let mySparticles = new Sparticles({ color: "red" }, 400, 300);
159 | ```
160 |
161 | # options
162 |
163 | A brief look at all the options, with more details below.
164 |
165 | option | type | default | description
166 | -------------------------------------------|-------------------|-----------------|-----------------------------------------------------
167 | **[composition](#composition)** | `String` | `source-over` | canvas globalCompositeOperation value for particles
168 | **[count](#count)** | `Number` | `50` | number of particles on the canvas simultaneously
169 | **[speed](#speed)** | `Number` | `10` | default velocity of every particle
170 | **[parallax](#parallax)** | `Number` | `1` | speed multiplier effect for larger particles (0 = none)
171 | **[direction](#direction)** | `Number` | `180` | default direction of particles in degrees (0 = ↑, 180 = ↓)
172 | **[xVariance](#xVariance)** | `Number` | `2` | random deviation of particles on x-axis from default direction
173 | **[yVariance](#yVariance)** | `Number` | `2` | random deviation of particles on y-axis from default direction
174 | **[rotate](#rotate)** | `Boolean` | `true` | can particles rotate
175 | **[rotation](#rotation)** | `Number` | `1` | default rotational speed for every particle
176 | **[alphaSpeed](#alphaSpeed)** | `Number` | `10` | rate of change in alpha over time
177 | **[alphaVariance](#alphaVariance)** | `Number` | `1` | random deviation of alpha change
178 | **[minAlpha](#minAlpha)** | `Number` | `0` | minumum alpha value of every particle
179 | **[maxAlpha](#maxAlpha)** | `Number` | `1` | maximum alpha value of every particle
180 | **[minSize](#minSize)** | `Number` | `1` | minimum size of every particle
181 | **[maxSize](#maxSize)** | `Number` | `10` | maximum size of every particle
182 | **[bounce](#bounce)** | `Boolean` | `false` | should the particles bounce off edge of canvas
183 | **[drift](#drift)** | `Number` | `1` | the "driftiness" of particles which have a horizontal/vertical direction
184 | **[glow](#glow)** | `Number` | `0` | the glow effect size of each particle
185 | **[twinkle](#twinkle)** | `Boolean` | `false` | particles to exhibit an alternative alpha transition as "twinkling"
186 | **[style](#style)** | `String` | `fill` | fill style of particles (one of; "fill", "stroke" or "both")
187 | **[shape](#shape)** | `String`/`Array` | `circle` | shape of particles (any of; circle, square, triangle, diamond, line, image) or "random"
188 | **[color](#color)** | `String`/`Array` | `random` | css color as string, or array of color strings (can also be "random")
189 | **[randomColor](#randomColor)** | `Function` | `randomHsl()` | function for returning a random color when the color is set as "random"
190 | **[randomColorCount](#randomColorCount)** | `Number` | `3` | number of random colours when the color is set as "random"
191 | **[imageUrl](#imageUrl)** | `String`/`Array` | | if shape is "image", define an image url (can be data-uri, **should be square (1:1 ratio)**)
192 |
193 | ---
194 |
195 | ## `composition`
196 | - Type: `String`
197 | - Default: `source-over`
198 | - Possible: [`see list here`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation)
199 |
200 | The [global render composition](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation)
201 | when rendering particles on top of one-another. This, however, is a very expensive operation when set to anything
202 | other than the default value (`source-over`), and will ultimately degrade performance, especially with many particles.
203 |
204 | Will accept [any of the values that are provided as part of the Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation)
205 |
206 | ## `count`
207 | - Type: `Number`
208 | - Default: `50`
209 | - Range: `1 - 10000`
210 |
211 | Simply the number of particles drawn to the screen.
212 | Values over `500` may begin to degrade performance.
213 |
214 | ## `speed`
215 | - Type: `Number`
216 | - Default: `10`
217 | - Range: `0 - 100`
218 |
219 | The base value of speed across all particles. This is modified by options such as
220 | `parallax` and `[x/y]Variance` to determine the final velocity of each individual particle.
221 | A speed of `0` will render particles stationary before applying `[x/y]Variance`.
222 |
223 | ## `parallax`
224 | - Type: `Number`
225 | - Default: `1`
226 | - Range: `0 - 20`
227 |
228 | A value to apply more speed to larger particles, and less speed to smaller particles, creating
229 | an effect which makes larger particles appear closer to the screen.
230 |
231 | ## `direction`
232 | - Type: `Number`
233 | - Default: `180`
234 | - Range: `0 - 360`
235 |
236 | The base angle (in degrees) at which the particles are travelling, so long as they have a speed value.
237 |
238 | ## `xVariance`
239 | - Type: `Number`
240 | - Default: `2`
241 | - Range: `0 - 20`
242 |
243 | How much variance is applied between particles on the `X` axis. A value of `0` will make all particles
244 | appear to be going completely parallel, and look unnatural.
245 |
246 | Can be used in conjunction with `speed: 0;` to make particles which float randomly in space.
247 |
248 | ## `yVariance`
249 | - Type: `Number`
250 | - Default: `2`
251 | - Range: `0 - 20`
252 |
253 | How much variance is applied between particles on the `Y` axis. A value of `0` will make all particles
254 | appear to be going completely parallel, and look unnatural.
255 |
256 | Can be used in conjunction with `speed: 0;` to make particles which float randomly in space.
257 |
258 | ## `rotate`
259 | - Type: `Boolean`
260 | - Default: `true`
261 |
262 | Toggle whether the particles are allowed to spin about their axis.
263 |
264 | ## `rotation`
265 | - Type: `Number`
266 | - Default: `1`
267 | - Range: `0 - 20`
268 |
269 | How fast the particles can spin about their axis, this has a random multiplier added per-particle
270 | which prevents a completely unnatural spinning effect.
271 |
272 | ## `alphaSpeed`
273 | - Type: `Number`
274 | - Default: `10`
275 | - Range: `0 - 50`
276 |
277 | Rate of change for the alpha value of all particles. A higher value will encourage the particles
278 | to flicker like candle lights. A value of `0` will disable alpha change.
279 |
280 | ## `alphaVariance`
281 | - Type: `Number`
282 | - Default: `2`
283 | - Range: `0 - 10`
284 |
285 | How much variance is applied between each particle on the alpha value change over time. A value
286 | of `0` will cause all particles to change alpha at the same rate, a higher value will introduce more
287 | variety.
288 |
289 | ## `minAlpha`
290 | - Type: `Number`
291 | - Default: `0`
292 | - Range: `-5 - +1`
293 |
294 | The minimum alpha value a particle can change to. The lower the number the longer it will stay invisible
295 | on the canvas, this could be useful in some scenarios where the particle should fade out for a while.
296 |
297 | Must be lower than the `maxAlpha` value.
298 |
299 | ## `maxAlpha`
300 | - Type: `Number`
301 | - Default: `0`
302 | - Range: `0 - +5`
303 |
304 | The maximum alpha value a particle can change to. The higher the number the longer it will stay visible
305 | on the canvas, this could be useful in some scenarios where the particle should stay at max alpha for a time.
306 |
307 | Must be higher than the `minAlpha` value.
308 |
309 | ## `minSize`
310 | - Type: `Number`
311 | - Default: `1`
312 | - Range: `1 - 100`
313 |
314 | Minimum size (in pixels) of the particles. The actual size of each particle is variable between the `minSize`
315 | and `maxSize`. If the `minSize` and `maxSize` are the same value; then all particles will be uniformly sized.
316 |
317 | ## `maxSize`
318 | - Type: `Number`
319 | - Default: `10`
320 | - Range: `1 - 100`
321 |
322 | Maximum size (in pixels) of the particles. The actual size of each particle is variable between the `minSize`
323 | and `maxSize`. If the `minSize` and `maxSize` are the same value; then all particles will be uniformly sized.
324 |
325 | ## `style`
326 | - Type: `String`
327 | - Default: `"fill"`
328 | - Values: `"fill"`, `"stroke"` or `"both"`
329 |
330 | Particles can be either stroked (outline) or filled (solid) and this setting determines that style. It's
331 | also possible to randomize the style by choosing `"both"`
332 |
333 | ## `bounce`
334 | - Type: `Boolean`
335 | - Default: `false`
336 |
337 | Determine if particles should bounce off the boundaries of the canvas instead of resetting to the opposite side.
338 | This is best used with `speed: 0;` and a high value for `[x/yVariance]` to create a chaotic effect.
339 |
340 | ## `drift`
341 | - Type: `Number`
342 | - Default: `1`
343 | - Range: `1 - 20`
344 |
345 | How much a particle will "drift" as it falls. This is to imply a floatiness/wind effect like seen with snow flakes,
346 | or leaves. The `drift` will only apply if `speed > 0` and `direction` is near to a 90degree value (`0, 90, 180, 270`)
347 |
348 | ## `glow`
349 | - Type: `Number`
350 | - Default: `0`
351 | - Range: `0 - 50`
352 |
353 | Glow (or shadow) effect around the particle. This will not affect images.
354 |
355 | ## `twinkle`
356 | - Type: `Boolean`
357 | - Default: `false`
358 |
359 | Apply a "twinkle" effect to the particle when changing alpha. This works best with a higher `alphaSpeed` and
360 | `alphaVariance` value.
361 |
362 | ## `color`
363 | - Type: `String` / `Array`
364 | - Default: `"random"`
365 | - Values: any valid css/html color string
366 |
367 | A CSS/HTML color string to apply across all particles.
368 | If an array of colors (`[ "#ff0", "red", "hsl(10,50%,50%)" ]`) is given, then each particle will
369 | be assigned a random color from the array. Additionally `"random"` can be used to assign any random color.
370 |
371 | ## `randomColor`
372 | - Type: `Function`
373 | - Default: [`randomHSL()`](https://github.com/simeydotme/sparticles/blob/master/src/helpers.js#L55-L64)
374 | - Arguments: `index`, `total`
375 |
376 | Custom function to use when generating `random` colors. The default function will return a fairly
377 | pleasant `hsl()` color with a high saturation and medium lightness. This can be overridden to suit
378 | your environment better. The two arguments (`index`, `total`) are `Integer`s and allow for a little
379 | psuedo-randomizing.
380 |
381 | **example:**
382 |
383 | ```js
384 | randomColor: function( index, total ) {
385 | return `hsl( ${index}, 80%, ${total - index}% )`;
386 | }
387 | ```
388 |
389 | ## `randomColorCount`
390 | - Type: `Number`
391 | - Default: `3`
392 | - Range: `1 - 50`
393 |
394 | How many random colors to generate when `color` is `random`. The more colors generated
395 | the more chance there is of a performance penalty. It should be OK up to `50`.
396 |
397 | ## `shape`
398 | - Type: `String` / `Array`
399 | - Default: `"circle"`
400 | - Values: `"circle"`, `"square"`, `"triangle"`, `"line"`, `"diamond"`, `"star"` or `"image"`
401 |
402 | Determine the shape of all the particles.
403 | If an array of shapes (`[ "circle", "star", "diamond" ]`) is given, then each particle will
404 | be assigned a random shape form the array. Additionally `"image"` can be used to [define a custom
405 | particle shape from an image when combined with `imageUrl`](#imageUrl).
406 |
407 | ## `imageUrl`
408 | - Type: `String` / `Array`
409 | - Default: `""`
410 | - Values: a valid url, or data-uri
411 |
412 | Determine the custom image to be used for all the particles.
413 | If an array of urls (`[ "http://my.image/shape.png", "http://my.svg/shape.svg" ]`) is given, then each particle
414 | will be assigned a random image as it's shape from the array.
415 | **This image should be a square (1:1)**
416 |
417 | - ℹ `imageUrl` only has an effect [if a `shape` in the array is; `"image"`](#shape).
418 | - ℹ `imageUrl` can accept **svg**, but the `