├── example
├── .gitignore
├── .babelrc
├── .eslintrc
├── .editorconfig
├── src
│ ├── index.html
│ └── app.js
├── webpack.config.js
└── package.json
├── .gitignore
├── .babelrc
├── .eslintrc
├── .editorconfig
├── src
├── particle-line
│ ├── color.js
│ ├── dot.js
│ └── index.js
└── index.js
├── package.json
├── README.md
└── lib
├── particle-line
├── color.js
├── dot.js
└── index.js
└── index.js
/example/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | *.log
4 | package-lock.json
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | *.log
4 | package-lock.json
5 | yarn
6 | yarn.lock
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["@babel/preset-env", "@babel/preset-react"],
3 | "plugins": ["@babel/plugin-proposal-class-properties"]
4 | }
--------------------------------------------------------------------------------
/example/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["@babel/preset-env", "@babel/preset-react"],
3 | "plugins": ["@babel/plugin-proposal-class-properties"]
4 | }
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "env": {
4 | "browser": true,
5 | "node": true,
6 | "es6": true,
7 | "jest": true
8 | },
9 | "extends": "airbnb",
10 | "rules": {
11 | "no-unused-vars": 0,
12 | "react/require-default-props": 0
13 | }
14 | }
--------------------------------------------------------------------------------
/example/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "env": {
4 | "browser": true,
5 | "node": true,
6 | "es6": true,
7 | "jest": true
8 | },
9 | "extends": "airbnb",
10 | "rules": {
11 | "no-unused-vars": 0,
12 | "react/require-default-props": 0
13 | }
14 | }
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # top-most EditorConfig file
2 | root = true
3 |
4 | # Unix-style newlines with a newline ending every file
5 | [*]
6 | end_of_line = lf
7 | insert_final_newline = true
8 | charset = utf-8
9 |
10 | # Indentation override for all files
11 | [*]
12 | indent_style = space
13 | indent_size = 2
14 | trim_trailing_whitespace: true
--------------------------------------------------------------------------------
/example/.editorconfig:
--------------------------------------------------------------------------------
1 | # top-most EditorConfig file
2 | root = true
3 |
4 | # Unix-style newlines with a newline ending every file
5 | [*]
6 | end_of_line = lf
7 | insert_final_newline = true
8 | charset = utf-8
9 |
10 | # Indentation override for all files
11 | [*]
12 | indent_style = space
13 | indent_size = 2
14 | trim_trailing_whitespace: true
--------------------------------------------------------------------------------
/example/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 基于 React 的线性粒子背景
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/example/src/app.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { render } from 'react-dom'
3 | import styled from 'styled-components'
4 | import ReactParticleLine from 'react-particle-line'
5 |
6 | const Home = styled.div`
7 | height: 100vh;
8 | `;
9 |
10 | const App = () =>
11 | render(, document.getElementById('root'))
--------------------------------------------------------------------------------
/src/particle-line/color.js:
--------------------------------------------------------------------------------
1 | export default class Color {
2 | constructor (min) {
3 | this.min = min || 0
4 | this._init(this.min)
5 | }
6 |
7 | _init (min) {
8 | this.r = this.colorValue(min)
9 | this.g = this.colorValue(min)
10 | this.b = this.colorValue(min)
11 | this.style = this.createColorStyle(this.r, this.g, this.b)
12 | }
13 |
14 | colorValue (min) {
15 | return Math.floor(Math.random() * 255 + min)
16 | }
17 |
18 | createColorStyle (r, g, b) {
19 | return `rgba(${r}, ${g}, ${b}, .8)`
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/particle-line/dot.js:
--------------------------------------------------------------------------------
1 | import Color from './color'
2 |
3 | export default class Dot {
4 | constructor (ctx, canvasWidth, canvasHeight, x, y) {
5 | this.ctx = ctx
6 | this.x = x || Math.random() * canvasWidth
7 | this.y = y || Math.random() * canvasHeight
8 | this._init()
9 | }
10 |
11 | _init () {
12 | this.vx = -0.5 + Math.random()
13 | this.vy = -0.5 + Math.random()
14 | this.radius = Math.random() * 3
15 | this.color = new Color()
16 | }
17 |
18 | draw () {
19 | this.ctx.beginPath()
20 | this.ctx.fillStyle = this.color.style
21 | this.ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false)
22 | this.ctx.fill()
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/example/webpack.config.js:
--------------------------------------------------------------------------------
1 | const { resolve } = require('path');
2 | const HtmlWebpackPlugin = require("html-webpack-plugin");
3 |
4 | module.exports = {
5 | entry: resolve(__dirname, "./src/app.js"),
6 | output: {
7 | path: resolve(__dirname, "./dist"),
8 | filename: "bundle.js"
9 | },
10 | module: {
11 | rules: [{
12 | test: /\.(js|jsx)$/,
13 | use: "babel-loader",
14 | exclude: /node_modules/
15 | }]
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({
19 | template: resolve(__dirname, './src/index.html'),
20 | // filename: "./index.html"
21 | })
22 | ],
23 | resolve: {
24 | extensions: ['*', '.js', '.jsx', '.json'],
25 | },
26 | devServer: {
27 | port: 3001
28 | }
29 | };
30 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-particle-line",
3 | "version": "0.1.0",
4 | "description": "基于 React 的线性粒子背景",
5 | "main": "lib/index.js",
6 | "scripts": {
7 | "start": "webpack-dev-server --open development",
8 | "build": "webpack --mode production",
9 | "deploy": "gh-pages -d example/dist",
10 | "publish-demo": "npm run build && npm run deploy"
11 | },
12 | "author": "hzzly",
13 | "license": "MIT",
14 | "devDependencies": {
15 | "@babel/cli": "^7.4.3",
16 | "@babel/core": "^7.4.3",
17 | "@babel/plugin-proposal-class-properties": "^7.4.0",
18 | "@babel/preset-env": "^7.4.3",
19 | "@babel/preset-react": "^7.0.0",
20 | "babel-loader": "^8.0.5",
21 | "html-webpack-plugin": "^3.2.0",
22 | "webpack": "^4.30.0",
23 | "webpack-cli": "^3.3.1",
24 | "webpack-dev-server": "^3.3.1"
25 | },
26 | "dependencies": {
27 | "prop-types": "^15.7.2",
28 | "react": "^16.8.6",
29 | "react-dom": "^16.8.6",
30 | "styled-components": "^4.3.1"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-particle-line",
3 | "version": "0.1.9",
4 | "description": "基于 React 的线性粒子背景",
5 | "main": "lib/index.js",
6 | "scripts": {
7 | "compile": "rimraf lib && babel src --out-dir lib"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/hzzly/react-particle-line.git"
12 | },
13 | "author": "hzzly",
14 | "license": "MIT",
15 | "bugs": {
16 | "url": "https://github.com/hzzly/react-particle-line/issues"
17 | },
18 |
19 | "keywords": [
20 | "react",
21 | "particle-line",
22 | "react-particle-line"
23 | ],
24 | "files": [
25 | "lib/"
26 | ],
27 | "homepage": "https://github.com/hzzly/react-particle-line#readme",
28 | "dependencies": {
29 | "react": "^16.8.6",
30 | "prop-types": "^15.7.2",
31 | "styled-components": "^4.2.0"
32 | },
33 | "peerDependencies": {
34 | "react": "^16.8.6",
35 | "prop-types": "^15.7.2"
36 | },
37 | "devDependencies": {
38 | "@babel/cli": "^7.4.3",
39 | "@babel/core": "^7.4.3",
40 | "@babel/plugin-proposal-class-properties": "^7.4.0",
41 | "@babel/preset-env": "^7.4.3",
42 | "@babel/preset-react": "^7.0.0",
43 | "babel-loader": "^8.0.5",
44 | "rimraf": "^2.6.3"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## react-particle-line
2 |
3 | 
4 | 
5 |
6 | ### How to use
7 | ```
8 | npm install react-particle-line --save
9 | ```
10 |
11 | ### Examples
12 | ```javascript
13 | import React from 'react';
14 | import ReactParticleLine from 'react-particle-line';
15 |
16 | const Example = () => (
17 |
18 | {/* ... */}
19 |
20 | );
21 |
22 | export default Example;
23 | ```
24 |
25 | ```javascript
26 | import React from 'react';
27 | import ReactParticleLine from 'react-particle-line';
28 |
29 | const Example = () => (
30 |
36 | {/* ... */}
37 |
38 | );
39 |
40 | export default Example;
41 | ```
42 |
43 | ### Props
44 |
45 | | Prop | Type | Default | Description |
46 | | ------- | ----- | :------: | ----------- |
47 | | lineWidth | Number | 0.3 | connect line width |
48 | | dotsNumber | Number | 100 | dot number |
49 | | dotsDistance | Number | 100 | far as points to connect |
50 | | hoverEffect | Boolean | true | mouse hover events |
51 |
52 | ### License
53 |
54 | MIT
55 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import styled from 'styled-components';
4 | import ParticleLine from './particle-line';
5 |
6 | const ParticleLineWraper = styled.div`
7 | position: relative;
8 | width: 100%;
9 | height: 100%;
10 | `;
11 | const ChildWraper = styled.div`
12 | z-index: 1;
13 | `;
14 | const CanvasWraper = styled.canvas.attrs({
15 | id: 'react-particle-line-canvas',
16 | })`
17 | position: absolute;
18 | top: 0;
19 | left: 0;
20 | width: 100%;
21 | height: 100%;
22 | `;
23 |
24 | export default class ReactParticleLine extends Component {
25 | static propTypes = {
26 | lineWidth: PropTypes.number,
27 | dotsNumber: PropTypes.number,
28 | dotsDistance: PropTypes.number,
29 | hoverEffect: PropTypes.bool,
30 | };
31 |
32 | static defaultProps = {
33 | lineWidth: 0.3,
34 | dotsNumber: 100,
35 | dotsDistance: 100,
36 | hoverEffect: true,
37 | };
38 |
39 | componentDidMount() {
40 | const { lineWidth, dotsNumber, dotsDistance, hoverEffect } = this.props;
41 |
42 | new ParticleLine('#react-particle-line-canvas', {
43 | lineWidth,
44 | dotsNumber,
45 | dotsDistance,
46 | hoverEffect,
47 | })
48 | }
49 |
50 | render() {
51 | return (
52 |
53 | {this.props.children}
54 |
55 |
56 | );
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/lib/particle-line/color.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports["default"] = void 0;
7 |
8 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
9 |
10 | function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
11 |
12 | function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
13 |
14 | var Color =
15 | /*#__PURE__*/
16 | function () {
17 | function Color(min) {
18 | _classCallCheck(this, Color);
19 |
20 | this.min = min || 0;
21 |
22 | this._init(this.min);
23 | }
24 |
25 | _createClass(Color, [{
26 | key: "_init",
27 | value: function _init(min) {
28 | this.r = this.colorValue(min);
29 | this.g = this.colorValue(min);
30 | this.b = this.colorValue(min);
31 | this.style = this.createColorStyle(this.r, this.g, this.b);
32 | }
33 | }, {
34 | key: "colorValue",
35 | value: function colorValue(min) {
36 | return Math.floor(Math.random() * 255 + min);
37 | }
38 | }, {
39 | key: "createColorStyle",
40 | value: function createColorStyle(r, g, b) {
41 | return "rgba(".concat(r, ", ").concat(g, ", ").concat(b, ", .8)");
42 | }
43 | }]);
44 |
45 | return Color;
46 | }();
47 |
48 | exports["default"] = Color;
--------------------------------------------------------------------------------
/lib/particle-line/dot.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports["default"] = void 0;
7 |
8 | var _color = _interopRequireDefault(require("./color"));
9 |
10 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
11 |
12 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
13 |
14 | function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
15 |
16 | function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
17 |
18 | var Dot =
19 | /*#__PURE__*/
20 | function () {
21 | function Dot(ctx, canvasWidth, canvasHeight, x, y) {
22 | _classCallCheck(this, Dot);
23 |
24 | this.ctx = ctx;
25 | this.x = x || Math.random() * canvasWidth;
26 | this.y = y || Math.random() * canvasHeight;
27 |
28 | this._init();
29 | }
30 |
31 | _createClass(Dot, [{
32 | key: "_init",
33 | value: function _init() {
34 | this.vx = -0.5 + Math.random();
35 | this.vy = -0.5 + Math.random();
36 | this.radius = Math.random() * 3;
37 | this.color = new _color["default"]();
38 | }
39 | }, {
40 | key: "draw",
41 | value: function draw() {
42 | this.ctx.beginPath();
43 | this.ctx.fillStyle = this.color.style;
44 | this.ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
45 | this.ctx.fill();
46 | }
47 | }]);
48 |
49 | return Dot;
50 | }();
51 |
52 | exports["default"] = Dot;
--------------------------------------------------------------------------------
/src/particle-line/index.js:
--------------------------------------------------------------------------------
1 | import Color from './color'
2 | import Dot from './dot'
3 |
4 | const minWidth = 1200
5 | const minHeight = 700
6 |
7 | export default class ParticleLine {
8 | constructor (tagId, options) {
9 | this.tagId = tagId
10 | this.options = options
11 | this.init()
12 | }
13 |
14 | init () {
15 | const canvas = document.querySelector(this.tagId)
16 | const ctx = canvas.getContext('2d')
17 | canvas.width = document.body.clientWidth > minWidth ? document.body.clientWidth : minWidth
18 | canvas.height = document.body.clientHeight > minHeight ? document.body.clientHeight : minHeight
19 | ctx.lineWidth = (this.options && this.options.lineWidth) || 0.3
20 | ctx.strokeStyle = (new Color(150)).style
21 | this.dots = {
22 | nb: (this.options && this.options.dotsNumber) || 100,
23 | distance: (this.options && this.options.dotsDistance) || 100,
24 | array: []
25 | }
26 | this.canvas = canvas
27 | this.ctx = ctx
28 | this.color = new Color()
29 | this.createDots(this.ctx, this.canvas.width, this.canvas.height)
30 | this.animateDots()
31 | this.hoverEffect()
32 | }
33 |
34 | hoverEffect () {
35 | if (this.options && this.options.hoverEffect) {
36 | this.canvas.addEventListener('mousemove', e => {
37 | if (this.dots.array.length > this.dots.nb) {
38 | this.dots.array.pop()
39 | }
40 | this.dots.array.push(new Dot(this.ctx, this.canvas.width, this.canvas.height, e.pageX, e.pageY))
41 | })
42 | }
43 | }
44 |
45 | resize () {
46 | const width = document.body.clientWidth > minWidth ? document.body.clientWidth : minWidth
47 | const height = document.body.clientHeight > minHeight ? document.body.clientHeight : minHeight
48 | this.canvas.width = width
49 | this.canvas.height = height
50 | this.createDots(this.ctx, width, height)
51 | }
52 |
53 | mixComponents (comp1, weight1, comp2, weight2) {
54 | return (comp1 * weight1 + comp2 * weight2) / (weight1 + weight2)
55 | }
56 |
57 | averageColorStyles (dot1, dot2) {
58 | const color1 = dot1.color
59 | const color2 = dot2.color
60 | const r = this.mixComponents(color1.r, dot1.radius, color2.r, dot2.radius)
61 | const g = this.mixComponents(color1.g, dot1.radius, color2.g, dot2.radius)
62 | const b = this.mixComponents(color1.b, dot1.radius, color2.b, dot2.radius)
63 | return this.color.createColorStyle(Math.floor(r), Math.floor(g), Math.floor(b))
64 | }
65 |
66 | createDots (ctx, canvasWidth, canvasHeight) {
67 | this.dots.array = []
68 | for (let i = 0; i < this.dots.nb; i++) {
69 | this.dots.array.push(new Dot(ctx, canvasWidth, canvasHeight))
70 | }
71 | }
72 |
73 | moveDots () {
74 | for (let i = 0; i < this.dots.nb; i++) {
75 | const dot = this.dots.array[i]
76 | if (dot.y < 0 || dot.y > this.canvas.height) {
77 | dot.vx = dot.vx // eslint-disable-line
78 | dot.vy = -dot.vy
79 | } else if (dot.x < 0 || dot.x > this.canvas.width) {
80 | dot.vx = -dot.vx
81 | dot.vy = dot.vy // eslint-disable-line
82 | }
83 | dot.x += dot.vx
84 | dot.y += dot.vy
85 | }
86 | }
87 |
88 | connectDots () {
89 | for (let i = 0; i < this.dots.array.length; i++) {
90 | for (let j = 0; j < this.dots.array.length; j++) {
91 | const iDot = this.dots.array[i]
92 | const jDot = this.dots.array[j]
93 | if ((iDot.x - jDot.x) < this.dots.distance && (iDot.y - jDot.y) < this.dots.distance && (iDot.x - jDot.x) > -this.dots.distance && (iDot.y - jDot.y) > -this.dots.distance) {
94 | this.ctx.beginPath()
95 | this.ctx.strokeStyle = this.averageColorStyles(iDot, jDot)
96 | this.ctx.moveTo(iDot.x, iDot.y)
97 | this.ctx.lineTo(jDot.x, jDot.y)
98 | this.ctx.stroke()
99 | this.ctx.closePath()
100 | }
101 | }
102 | }
103 | }
104 |
105 | drawDots () {
106 | for (let i = 0; i < this.dots.array.length; i++) {
107 | const dot = this.dots.array[i]
108 | dot.draw()
109 | }
110 | }
111 |
112 | animateDots () {
113 | this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
114 | this.drawDots()
115 | this.connectDots()
116 | this.moveDots()
117 | requestAnimationFrame(this.animateDots.bind(this))
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/lib/particle-line/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports["default"] = void 0;
7 |
8 | var _color = _interopRequireDefault(require("./color"));
9 |
10 | var _dot = _interopRequireDefault(require("./dot"));
11 |
12 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
13 |
14 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
15 |
16 | function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
17 |
18 | function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
19 |
20 | var minWidth = 1200;
21 | var minHeight = 700;
22 |
23 | var ParticleLine =
24 | /*#__PURE__*/
25 | function () {
26 | function ParticleLine(tagId, options) {
27 | _classCallCheck(this, ParticleLine);
28 |
29 | this.tagId = tagId;
30 | this.options = options;
31 | this.init();
32 | }
33 |
34 | _createClass(ParticleLine, [{
35 | key: "init",
36 | value: function init() {
37 | var canvas = document.querySelector(this.tagId);
38 | var ctx = canvas.getContext('2d');
39 | canvas.width = document.body.clientWidth > minWidth ? document.body.clientWidth : minWidth;
40 | canvas.height = document.body.clientHeight > minHeight ? document.body.clientHeight : minHeight;
41 | ctx.lineWidth = this.options && this.options.lineWidth || 0.3;
42 | ctx.strokeStyle = new _color["default"](150).style;
43 | this.dots = {
44 | nb: this.options && this.options.dotsNumber || 100,
45 | distance: this.options && this.options.dotsDistance || 100,
46 | array: []
47 | };
48 | this.canvas = canvas;
49 | this.ctx = ctx;
50 | this.color = new _color["default"]();
51 | this.createDots(this.ctx, this.canvas.width, this.canvas.height);
52 | this.animateDots();
53 | this.hoverEffect();
54 | }
55 | }, {
56 | key: "hoverEffect",
57 | value: function hoverEffect() {
58 | var _this = this;
59 |
60 | if (this.options && this.options.hoverEffect) {
61 | this.canvas.addEventListener('mousemove', function (e) {
62 | if (_this.dots.array.length > _this.dots.nb) {
63 | _this.dots.array.pop();
64 | }
65 |
66 | _this.dots.array.push(new _dot["default"](_this.ctx, _this.canvas.width, _this.canvas.height, e.pageX, e.pageY));
67 | });
68 | }
69 | }
70 | }, {
71 | key: "resize",
72 | value: function resize() {
73 | var width = document.body.clientWidth > minWidth ? document.body.clientWidth : minWidth;
74 | var height = document.body.clientHeight > minHeight ? document.body.clientHeight : minHeight;
75 | this.canvas.width = width;
76 | this.canvas.height = height;
77 | this.createDots(this.ctx, width, height);
78 | }
79 | }, {
80 | key: "mixComponents",
81 | value: function mixComponents(comp1, weight1, comp2, weight2) {
82 | return (comp1 * weight1 + comp2 * weight2) / (weight1 + weight2);
83 | }
84 | }, {
85 | key: "averageColorStyles",
86 | value: function averageColorStyles(dot1, dot2) {
87 | var color1 = dot1.color;
88 | var color2 = dot2.color;
89 | var r = this.mixComponents(color1.r, dot1.radius, color2.r, dot2.radius);
90 | var g = this.mixComponents(color1.g, dot1.radius, color2.g, dot2.radius);
91 | var b = this.mixComponents(color1.b, dot1.radius, color2.b, dot2.radius);
92 | return this.color.createColorStyle(Math.floor(r), Math.floor(g), Math.floor(b));
93 | }
94 | }, {
95 | key: "createDots",
96 | value: function createDots(ctx, canvasWidth, canvasHeight) {
97 | this.dots.array = [];
98 |
99 | for (var i = 0; i < this.dots.nb; i++) {
100 | this.dots.array.push(new _dot["default"](ctx, canvasWidth, canvasHeight));
101 | }
102 | }
103 | }, {
104 | key: "moveDots",
105 | value: function moveDots() {
106 | for (var i = 0; i < this.dots.nb; i++) {
107 | var dot = this.dots.array[i];
108 |
109 | if (dot.y < 0 || dot.y > this.canvas.height) {
110 | dot.vx = dot.vx; // eslint-disable-line
111 |
112 | dot.vy = -dot.vy;
113 | } else if (dot.x < 0 || dot.x > this.canvas.width) {
114 | dot.vx = -dot.vx;
115 | dot.vy = dot.vy; // eslint-disable-line
116 | }
117 |
118 | dot.x += dot.vx;
119 | dot.y += dot.vy;
120 | }
121 | }
122 | }, {
123 | key: "connectDots",
124 | value: function connectDots() {
125 | for (var i = 0; i < this.dots.array.length; i++) {
126 | for (var j = 0; j < this.dots.array.length; j++) {
127 | var iDot = this.dots.array[i];
128 | var jDot = this.dots.array[j];
129 |
130 | if (iDot.x - jDot.x < this.dots.distance && iDot.y - jDot.y < this.dots.distance && iDot.x - jDot.x > -this.dots.distance && iDot.y - jDot.y > -this.dots.distance) {
131 | this.ctx.beginPath();
132 | this.ctx.strokeStyle = this.averageColorStyles(iDot, jDot);
133 | this.ctx.moveTo(iDot.x, iDot.y);
134 | this.ctx.lineTo(jDot.x, jDot.y);
135 | this.ctx.stroke();
136 | this.ctx.closePath();
137 | }
138 | }
139 | }
140 | }
141 | }, {
142 | key: "drawDots",
143 | value: function drawDots() {
144 | for (var i = 0; i < this.dots.array.length; i++) {
145 | var dot = this.dots.array[i];
146 | dot.draw();
147 | }
148 | }
149 | }, {
150 | key: "animateDots",
151 | value: function animateDots() {
152 | this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
153 | this.drawDots();
154 | this.connectDots();
155 | this.moveDots();
156 | requestAnimationFrame(this.animateDots.bind(this));
157 | }
158 | }]);
159 |
160 | return ParticleLine;
161 | }();
162 |
163 | exports["default"] = ParticleLine;
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports["default"] = void 0;
7 |
8 | var _react = _interopRequireWildcard(require("react"));
9 |
10 | var _propTypes = _interopRequireDefault(require("prop-types"));
11 |
12 | var _styledComponents = _interopRequireDefault(require("styled-components"));
13 |
14 | var _particleLine = _interopRequireDefault(require("./particle-line"));
15 |
16 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
17 |
18 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj["default"] = obj; return newObj; } }
19 |
20 | function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
21 |
22 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
23 |
24 | function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
25 |
26 | function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
27 |
28 | function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
29 |
30 | function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
31 |
32 | function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
33 |
34 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
35 |
36 | function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
37 |
38 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
39 |
40 | function _templateObject3() {
41 | var data = _taggedTemplateLiteral(["\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n"]);
42 |
43 | _templateObject3 = function _templateObject3() {
44 | return data;
45 | };
46 |
47 | return data;
48 | }
49 |
50 | function _templateObject2() {
51 | var data = _taggedTemplateLiteral(["\n z-index: 1;\n"]);
52 |
53 | _templateObject2 = function _templateObject2() {
54 | return data;
55 | };
56 |
57 | return data;
58 | }
59 |
60 | function _templateObject() {
61 | var data = _taggedTemplateLiteral(["\n position: relative;\n width: 100%;\n height: 100%;\n"]);
62 |
63 | _templateObject = function _templateObject() {
64 | return data;
65 | };
66 |
67 | return data;
68 | }
69 |
70 | function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
71 |
72 | var ParticleLineWraper = _styledComponents["default"].div(_templateObject());
73 |
74 | var ChildWraper = _styledComponents["default"].div(_templateObject2());
75 |
76 | var CanvasWraper = _styledComponents["default"].canvas.attrs({
77 | id: 'react-particle-line-canvas'
78 | })(_templateObject3());
79 |
80 | var ReactParticleLine =
81 | /*#__PURE__*/
82 | function (_Component) {
83 | _inherits(ReactParticleLine, _Component);
84 |
85 | function ReactParticleLine() {
86 | _classCallCheck(this, ReactParticleLine);
87 |
88 | return _possibleConstructorReturn(this, _getPrototypeOf(ReactParticleLine).apply(this, arguments));
89 | }
90 |
91 | _createClass(ReactParticleLine, [{
92 | key: "componentDidMount",
93 | value: function componentDidMount() {
94 | var _this$props = this.props,
95 | lineWidth = _this$props.lineWidth,
96 | dotsNumber = _this$props.dotsNumber,
97 | dotsDistance = _this$props.dotsDistance,
98 | hoverEffect = _this$props.hoverEffect;
99 | new _particleLine["default"]('#react-particle-line-canvas', {
100 | lineWidth: lineWidth,
101 | dotsNumber: dotsNumber,
102 | dotsDistance: dotsDistance,
103 | hoverEffect: hoverEffect
104 | });
105 | }
106 | }, {
107 | key: "render",
108 | value: function render() {
109 | return _react["default"].createElement(ParticleLineWraper, null, _react["default"].createElement(ChildWraper, null, this.props.children), _react["default"].createElement(CanvasWraper, null));
110 | }
111 | }]);
112 |
113 | return ReactParticleLine;
114 | }(_react.Component);
115 |
116 | exports["default"] = ReactParticleLine;
117 |
118 | _defineProperty(ReactParticleLine, "propTypes", {
119 | lineWidth: _propTypes["default"].number,
120 | dotsNumber: _propTypes["default"].number,
121 | dotsDistance: _propTypes["default"].number,
122 | hoverEffect: _propTypes["default"].bool
123 | });
124 |
125 | _defineProperty(ReactParticleLine, "defaultProps", {
126 | lineWidth: 0.3,
127 | dotsNumber: 100,
128 | dotsDistance: 100,
129 | hoverEffect: true
130 | });
--------------------------------------------------------------------------------