├── .gitignore ├── screenshot.png ├── src ├── index.js ├── iife.js ├── utils.js └── CanvasNest.js ├── .babelrc ├── lib ├── index.js ├── iife.js ├── utils.js └── CanvasNest.js ├── rollup.config.iife.js ├── rollup.config.umd.js ├── LICENSE ├── index.html ├── package.json ├── README-zh.md ├── README.md └── dist ├── canvas-nest.umd.js └── canvas-nest.js /.gitignore: -------------------------------------------------------------------------------- 1 | .project 2 | .settings 3 | .idea 4 | node_modules/* 5 | 6 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNBBXX/canvas-nest.js/master/screenshot.png -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hustcc on 18/6/23. 3 | * Contract: i@hust.cc 4 | */ 5 | 6 | import CanvasNest from './CanvasNest'; 7 | 8 | export default CanvasNest; 9 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "rollup": { 4 | "presets": [ 5 | [ 6 | "env", 7 | { 8 | "modules": false 9 | } 10 | ] 11 | ], 12 | "plugins": [ 13 | "transform-class-properties", 14 | "transform-object-rest-spread" 15 | ] 16 | }, 17 | "babel": { 18 | "presets": ["env"], 19 | "plugins": [ 20 | "transform-class-properties", 21 | "add-module-exports", 22 | "transform-object-rest-spread" 23 | ] 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _CanvasNest = require('./CanvasNest'); 8 | 9 | var _CanvasNest2 = _interopRequireDefault(_CanvasNest); 10 | 11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 12 | 13 | exports.default = _CanvasNest2.default; /** 14 | * Created by hustcc on 18/6/23. 15 | * Contract: i@hust.cc 16 | */ 17 | 18 | module.exports = exports['default']; -------------------------------------------------------------------------------- /src/iife.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hustcc on 18/6/23. 3 | * Contract: i@hust.cc 4 | */ 5 | 6 | import CanvasNest from './CanvasNest'; 7 | 8 | const getScriptConfig = () => { 9 | const scripts = document.getElementsByTagName('script'); 10 | const len = scripts.length; 11 | const script = scripts[len - 1]; // 当前加载的script 12 | return { 13 | zIndex: script.getAttribute('zIndex'), 14 | opacity: script.getAttribute('opacity'), 15 | color: script.getAttribute('color'), 16 | count: Number(script.getAttribute('count')) || 99, 17 | }; 18 | }; 19 | 20 | new CanvasNest(document.body, getScriptConfig()); 21 | -------------------------------------------------------------------------------- /rollup.config.iife.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hustcc on 18/6/23. 3 | * Contract: i@hust.cc 4 | */ 5 | 6 | import uglify from 'rollup-plugin-uglify'; 7 | import babel from 'rollup-plugin-babel'; 8 | import resolve from 'rollup-plugin-node-resolve'; 9 | import commonjs from 'rollup-plugin-commonjs'; 10 | 11 | export default { 12 | input: 'src/iife.js', 13 | output: { 14 | file: 'dist/canvas-nest.js', 15 | format: 'iife', 16 | }, 17 | plugins: [ 18 | resolve(), 19 | babel({ 20 | exclude: 'node_modules/**', 21 | }), 22 | commonjs(), 23 | uglify({ 24 | output: { comments: false }, 25 | compress: { warnings: false } 26 | }), 27 | ], 28 | external: [], 29 | }; 30 | -------------------------------------------------------------------------------- /rollup.config.umd.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hustcc on 18/6/23. 3 | * Contract: i@hust.cc 4 | */ 5 | 6 | import uglify from 'rollup-plugin-uglify'; 7 | import babel from 'rollup-plugin-babel'; 8 | import resolve from 'rollup-plugin-node-resolve'; 9 | import commonjs from 'rollup-plugin-commonjs'; 10 | 11 | export default { 12 | input: 'src/index.js', 13 | output: { 14 | file: 'dist/canvas-nest.umd.js', 15 | name: 'CanvasNest', 16 | format: 'umd', 17 | }, 18 | plugins: [ 19 | resolve(), 20 | babel({ 21 | exclude: 'node_modules/**', 22 | }), 23 | commonjs(), 24 | uglify({ 25 | output: { comments: false }, 26 | compress: { warnings: false } 27 | }), 28 | ], 29 | external: [], 30 | }; 31 | -------------------------------------------------------------------------------- /lib/iife.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _CanvasNest = require('./CanvasNest'); 4 | 5 | var _CanvasNest2 = _interopRequireDefault(_CanvasNest); 6 | 7 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 8 | 9 | var getScriptConfig = function getScriptConfig() { 10 | var scripts = document.getElementsByTagName('script'); 11 | var len = scripts.length; 12 | var script = scripts[len - 1]; // 当前加载的script 13 | return { 14 | zIndex: script.getAttribute('zIndex'), 15 | opacity: script.getAttribute('opacity'), 16 | color: script.getAttribute('color'), 17 | count: Number(script.getAttribute('count')) || 99 18 | }; 19 | }; /** 20 | * Created by hustcc on 18/6/23. 21 | * Contract: i@hust.cc 22 | */ 23 | 24 | new _CanvasNest2.default(document.body, getScriptConfig()); -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hustcc on 18/6/23. 3 | * Contract: i@hust.cc 4 | */ 5 | 6 | export const requestAnimationFrame = window.requestAnimationFrame || 7 | window.webkitRequestAnimationFrame || 8 | window.mozRequestAnimationFrame || 9 | window.msRequestAnimationFrame || 10 | window.oRequestAnimationFrame || 11 | function(func) { 12 | return window.setTimeout(func, 1000 / 60); 13 | }; 14 | 15 | export const cancelAnimationFrame = window.cancelAnimationFrame || 16 | window.webkitCancelAnimationFrame || 17 | window.mozCancelAnimationFrame || 18 | window.msCancelAnimationFrame || 19 | window.oCancelAnimationFrame || 20 | window.clearTimeout; 21 | 22 | export const range = n => 23 | new Array(n).fill(0).map((e, idx) => idx); 24 | 25 | export const canvasStyle = config => 26 | `display:block;position:absolute;top:0;left:0;height:100%;width:100%;overflow:hidden;pointer-events:none;z-index:${config.zIndex};opacity:${config.opacity}`; 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Hust.cc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /lib/utils.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | /** 7 | * Created by hustcc on 18/6/23. 8 | * Contract: i@hust.cc 9 | */ 10 | 11 | var requestAnimationFrame = exports.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame || function (func) { 12 | return window.setTimeout(func, 1000 / 60); 13 | }; 14 | 15 | var cancelAnimationFrame = exports.cancelAnimationFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.msCancelAnimationFrame || window.oCancelAnimationFrame || window.clearTimeout; 16 | 17 | var range = exports.range = function range(n) { 18 | return new Array(n).fill(0).map(function (e, idx) { 19 | return idx; 20 | }); 21 | }; 22 | 23 | var canvasStyle = exports.canvasStyle = function canvasStyle(config) { 24 | return "display:block;position:absolute;top:0;left:0;height:100%;width:100%;overflow:hidden;pointer-events:none;z-index:" + config.zIndex + ";opacity:" + config.opacity; 25 | }; -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | canvas-nest.js 7 | 33 | 34 | 35 |
36 | 37 |
38 | 39 | 40 | 41 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "canvas-nest.js", 3 | "officialName": "canvas-nest.js", 4 | "version": "2.0.2", 5 | "main": "lib/index.js", 6 | "summary": "A nest backgroud of website draw on canvas use javascript, do not depends on jQuery.", 7 | "description": "A nest backgroud of website draw on canvas use javascript, do not depends on jQuery.", 8 | "scripts": { 9 | "test": "npm run size", 10 | "size": "size-limit", 11 | "build:lib": "rimraf ./lib && cross-env NODE_ENV=babel babel src -d lib", 12 | "build:umd": "cross-env NODE_ENV=rollup rollup -c rollup.config.umd.js", 13 | "build:iife": "cross-env NODE_ENV=rollup rollup -c rollup.config.iife.js", 14 | "build": "npm run build:umd && npm run build:iife && npm run build:lib && npm run test" 15 | }, 16 | "dependencies": { 17 | "size-sensor": "^0.2.0" 18 | }, 19 | "size-limit": [ 20 | { 21 | "limit": "2.5 KB", 22 | "path": "dist/canvas-nest.umd.js" 23 | }, 24 | { 25 | "limit": "2.5 KB", 26 | "path": "dist/canvas-nest.js" 27 | } 28 | ], 29 | "author": { 30 | "name": "hustcc", 31 | "url": "https://github.com/hustcc" 32 | }, 33 | "homepage": "https://atool.vip", 34 | "license": "MIT", 35 | "keywords": [ 36 | "canvas", 37 | "html5", 38 | "nest" 39 | ], 40 | "repository": { 41 | "type": "git", 42 | "url": "https://github.com/hustcc/canvas-nest.js" 43 | }, 44 | "bugs": { 45 | "url": "https://github.com/hustcc/canvas-nest.js/issues" 46 | }, 47 | "devDependencies": { 48 | "babel-cli": "^6.26.0", 49 | "babel-plugin-add-module-exports": "^0.2.1", 50 | "babel-plugin-transform-class-properties": "^6.24.1", 51 | "babel-plugin-transform-object-rest-spread": "^6.26.0", 52 | "babel-preset-env": "^1.6.1", 53 | "cross-env": "^5.1.3", 54 | "rimraf": "^2.6.2", 55 | "rollup": "^0.58.1", 56 | "rollup-plugin-babel": "^3.0.4", 57 | "rollup-plugin-commonjs": "^9.1.3", 58 | "rollup-plugin-node-resolve": "^3.3.0", 59 | "rollup-plugin-uglify": "^3.0.0", 60 | "size-limit": "^0.18.0" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /README-zh.md: -------------------------------------------------------------------------------- 1 | # canvas-nest.js 2 | 3 | > 一个基于 html5 canvas 绘制的网页背景效果,非常赞! 4 | 5 | [![npm](https://img.shields.io/badge/demo-online-brightgreen.svg)](https://git.hust.cc/canvas-nest.js) 6 | [![npm](https://img.shields.io/npm/v/canvas-nest.js.svg)](https://www.npmjs.com/package/canvas-nest.js) 7 | [![npm](https://img.shields.io/npm/dm/canvas-nest.js.svg)](https://www.npmjs.com/package/canvas-nest.js) 8 | [![gzip](http://img.badgesize.io/https://unpkg.com/canvas-nest.js/dist/canvas-nest.js?compression=gzip)](https://unpkg.com/canvas-nest.js/dist/canvas-nest.js) 9 | 10 | > **npm i --save canvas-nest.js** 11 | 12 | 13 | ## 特性 14 | 15 | - 不依赖 jQuery,使用原生的 javascript。 16 | - 非常小,只有 2 Kb。 17 | - 非常容易实现,配置简单,即使你不是 web 开发者,也能简单搞定。 18 | - 模块化 & 区域渲染。 19 | 20 | 21 | ## 使用 22 | 23 | - 快捷使用 24 | 25 | 将下面的代码插入到 ` 和 之间`. 26 | 27 | ```html 28 | 29 | ``` 30 | 31 | 强烈建议在 ``标签上方. 例如下面的代码结构: 32 | 33 | ```html 34 | 35 | 36 | ... 37 | 38 | 39 | ... 40 | ... 41 | 42 | 43 | 44 | ``` 45 | 46 | 然后就完成了,打开网页即可看到效果!`请注意不要将代码置于 里面`. 47 | 48 | 49 | - 模块化区域绘制(定制开发) 50 | 51 | > npm i --save canvas-nest.js 52 | 53 | 然后可以使用 script 方式引入 umd 包,当然也可使用模块化方式 import。 54 | 55 | 并且只有一个 API,使用如下: 56 | 57 | ```js 58 | import CanvasNest from 'canvas-nest.js'; 59 | 60 | const config = { 61 | color: '255,0,0', 62 | count: 88, 63 | }; 64 | 65 | // 在 element 地方使用 config 渲染效果 66 | const cn = new CanvasNest(element, config); 67 | 68 | // destroy 69 | cn.destroy(); 70 | ``` 71 | 72 | 73 | ## 配置和配置项 74 | 75 | - **`color`**: 线条颜色, 默认: `'0,0,0'` ;三个数字分别为(R,G,B),注意用,分割 76 | - **`opacity`**: 线条透明度(0~1), 默认: `0.5` 77 | - **`count`**: 线条的总数量, 默认: `150` 78 | - **`zIndex`**: 背景的z-index属性,css属性用于控制所在层的位置, 默认: `-1` 79 | 80 | 81 | Example: 82 | 83 | ```html 84 | 85 | ``` 86 | 87 | 这些属性配置在引用 js 的 script 标签中,作为它的一个属性值。所有的配置项都有默认值,如果你不知道怎么设置,可以先不设置这些配置项,就使用默认值看看效果也可以的。 88 | 89 | 或者模块化调用的时候,config 参数写成: 90 | 91 | ```js 92 | { 93 | color: '0,0,255', 94 | opacity: 0.7, 95 | zIndex: -2, 96 | count: 99, 97 | }; 98 | ``` 99 | 100 | 101 | ## 相关项目 102 | 103 | - [canvas-nest-for-wp](https://github.com/aTool-org/canvas-nest-for-wp): WP 插件,在插件市场搜索 `canvas-nest` 即可安装。 104 | - [vue-canvas-nest](https://github.com/ZYSzys/vue-canvas-nest): VUE 组件包装。 105 | 106 | 107 | ## 使用项目 108 | 109 | - [A Tool](https://atools.vip/): 一个好用的工具集合. 110 | 111 | 112 | ## License 113 | 114 | MIT@[hustcc](https://github.com/hustcc). 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # canvas-nest.js 2 | 3 | > A nest backgroud of website draw on canvas. [中文 Readme 帮助文档](README-zh.md). 4 | 5 | [![npm](https://img.shields.io/badge/demo-online-brightgreen.svg)](https://git.hust.cc/canvas-nest.js) 6 | [![npm](https://img.shields.io/npm/v/canvas-nest.js.svg)](https://www.npmjs.com/package/canvas-nest.js) 7 | [![npm](https://img.shields.io/npm/dm/canvas-nest.js.svg)](https://www.npmjs.com/package/canvas-nest.js) 8 | [![gzip](http://img.badgesize.io/https://unpkg.com/canvas-nest.js/dist/canvas-nest.js?compression=gzip)](https://unpkg.com/canvas-nest.js/dist/canvas-nest.js) 9 | 10 | > **npm i --save canvas-nest.js** 11 | 12 | 13 | ## Feature 14 | 15 | - No need jQuery. 16 | - Light, only 2 Kb. 17 | - Easy to use, even you are not a web developer. 18 | - Modular & area render. 19 | 20 | 21 | ## Usage 22 | 23 | - Script tag 24 | 25 | Insert the code below `between and `. 26 | 27 | ```html 28 | 29 | ``` 30 | 31 | Suggest before the tag ``, like below: 32 | 33 | ```html 34 | 35 | 36 | ... 37 | 38 | 39 | ... 40 | ... 41 | 42 | 43 | 44 | ``` 45 | 46 | Then ok! `Please do not add the code in the `. 47 | 48 | 49 | - Module usage (Area render) 50 | 51 | > npm i --save canvas-nest.js 52 | 53 | Or import the `umd` package use `script` tag. 54 | 55 | There is only one API, use it like: 56 | 57 | ```js 58 | import CanvasNest from 'canvas-nest.js'; 59 | 60 | const config = { 61 | color: '255,0,0', 62 | count: 88, 63 | }; 64 | 65 | // render nest on element with config. 66 | const cn = new CanvasNest(element, config); 67 | 68 | // destroy 69 | cn.destroy(); 70 | ``` 71 | 72 | 73 | ## Config 74 | 75 | - **`color`**: the canvas line color, default: `'0,0,0'`; the color is (R,G,B). 76 | - **`opacity`**: the opacity of line (0~1), default: `0.5`. 77 | - **`count`**: the number of lines, default: `99`. 78 | - **`zIndex`**: the index of z space, default: `-1`. 79 | 80 | Example: 81 | 82 | ```html 83 | 84 | ``` 85 | 86 | Or 87 | 88 | ```js 89 | { 90 | color: '0,0,255', 91 | opacity: 0.7, 92 | zIndex: -2, 93 | count: 99, 94 | }; 95 | ``` 96 | 97 | 98 | ## Related projects 99 | 100 | - [canvas-nest-for-wp](https://github.com/aTool-org/canvas-nest-for-wp): a wordpress plugin, search `canvas-nest` in wordpress store. 101 | - [vue-canvas-nest](https://github.com/ZYSzys/vue-canvas-nest): vue component wrapper. 102 | 103 | 104 | ## Used by 105 | 106 | - [A Tool](https://atools.vip/): Tools for human. 107 | 108 | 109 | 110 | ## License 111 | 112 | MIT@[hustcc](https://github.com/hustcc). 113 | -------------------------------------------------------------------------------- /src/CanvasNest.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hustcc on 18/6/23. 3 | * Contract: i@hust.cc 4 | */ 5 | 6 | import { bind, clear } from 'size-sensor'; 7 | import { requestAnimationFrame, cancelAnimationFrame, range, canvasStyle } from './utils'; 8 | 9 | export default class CanvasNest { 10 | constructor(el, config) { 11 | this.el = el; 12 | 13 | this.c = { 14 | zIndex: -1, // z-index 15 | opacity: 0.5, // opacity 16 | color: '0,0,0', // color 17 | count: 99, // count 18 | ...config, 19 | }; 20 | 21 | this.canvas = this.newCanvas(); 22 | this.context = this.canvas.getContext('2d'); 23 | 24 | this.points = this.randomPoints(); 25 | this.current = { 26 | x: null, // 当前鼠标x 27 | y: null, // 当前鼠标y 28 | max: 20000 // 圈半径的平方 29 | }; 30 | this.all = this.points.concat([this.current]); 31 | 32 | this.bindEvent(); 33 | 34 | this.requestFrame(this.drawCanvas); 35 | } 36 | 37 | bindEvent() { 38 | bind(this.el, () => { 39 | this.canvas.width = this.el.clientWidth; 40 | this.canvas.height = this.el.clientHeight; 41 | }); 42 | 43 | this.onmousemove = window.onmousemove; 44 | window.onmousemove = e => { 45 | this.current.x = e.clientX - this.el.offsetLeft; 46 | this.current.y = e.clientY - this.el.offsetTop; 47 | this.onmousemove && this.onmousemove(e); 48 | }; 49 | 50 | this.onmouseout = window.onmouseout; 51 | window.onmouseout = () => { 52 | this.current.x = null; 53 | this.current.y = null; 54 | this.onmouseout && this.onmouseout(); 55 | }; 56 | } 57 | 58 | randomPoints = () => { 59 | return range(this.c.count).map(() => ({ 60 | x: Math.random() * this.canvas.width, 61 | y: Math.random() * this.canvas.height, 62 | xa: 2 * Math.random() - 1, // 随机运动返现 63 | ya: 2 * Math.random() - 1, 64 | max: 6000 //沾附距离 65 | })); 66 | }; 67 | 68 | newCanvas() { 69 | if (getComputedStyle(this.el).position === 'static') { 70 | this.el.style.position = 'relative' 71 | } 72 | const canvas = document.createElement('canvas'); // 画布 73 | canvas.style.cssText = canvasStyle(this.c); 74 | 75 | canvas.width = this.el.clientWidth; 76 | canvas.height = this.el.clientHeight; 77 | 78 | this.el.appendChild(canvas); 79 | return canvas; 80 | } 81 | 82 | requestFrame(func) { 83 | this.tid = requestAnimationFrame(() => func.call(this)); 84 | } 85 | 86 | drawCanvas() { 87 | const context = this.context; 88 | const width = this.canvas.width; 89 | const height = this.canvas.height; 90 | const current = this.current; 91 | const points = this.points; 92 | const all = this.all; 93 | 94 | context.clearRect(0, 0, width, height); 95 | // 随机的线条和当前位置联合数组 96 | let e, i, d, x_dist, y_dist, dist; // 临时节点 97 | // 遍历处理每一个点 98 | points.forEach((r, idx) => { 99 | r.x += r.xa; 100 | r.y += r.ya; // 移动 101 | r.xa *= r.x > width || r.x < 0 ? -1 : 1; 102 | r.ya *= r.y > height || r.y < 0 ? -1 : 1; // 碰到边界,反向反弹 103 | context.fillRect(r.x - 0.5, r.y - 0.5, 1, 1); // 绘制一个宽高为1的点 104 | // 从下一个点开始 105 | for (i = idx + 1; i < all.length; i ++) { 106 | e = all[i]; 107 | // 当前点存在 108 | if (null !== e.x && null !== e.y) { 109 | x_dist = r.x - e.x; // x轴距离 l 110 | y_dist = r.y - e.y; // y轴距离 n 111 | dist = x_dist * x_dist + y_dist * y_dist; // 总距离, m 112 | 113 | dist < e.max && (e === current && dist >= e.max / 2 && (r.x -= 0.03 * x_dist, r.y -= 0.03 * y_dist), // 靠近的时候加速 114 | d = (e.max - dist) / e.max, 115 | context.beginPath(), 116 | context.lineWidth = d / 2, 117 | context.strokeStyle = `rgba(${this.c.color},${d + 0.2})`, 118 | context.moveTo(r.x, r.y), 119 | context.lineTo(e.x, e.y), 120 | context.stroke()); 121 | } 122 | } 123 | }); 124 | this.requestFrame(this.drawCanvas); 125 | } 126 | 127 | destroy() { 128 | // 清楚事件 129 | clear(this.el); 130 | 131 | // mouse 事件清楚 132 | window.onmousemove = this.onmousemove; // 回滚方法 133 | window.onmouseout = this.onmouseout; 134 | 135 | // 删除轮询 136 | cancelAnimationFrame(this.tid); 137 | 138 | // 删除 dom 139 | this.canvas.parentNode.removeChild(this.canvas); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /dist/canvas-nest.umd.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.CanvasNest=t()}(this,function(){"use strict";function e(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function t(e,t){return e(t={exports:{}},t.exports),t.exports}var n=t(function(e,t){Object.defineProperty(t,"__esModule",{value:!0});var n=1;t.default=function(){return""+n++},e.exports=t.default});e(n);var o=t(function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:30,n=null;return function(){for(var o=this,i=arguments.length,r=Array(i),a=0;an||r.x<0?-1:1,r.ya*=r.y>o||r.y<0?-1:1,t.fillRect(r.x-.5,r.y-.5,1,1),u=v+1;u=s.max/2&&(r.x-=.03*l,r.y-=.03*d),c=(s.max-f)/s.max,t.beginPath(),t.lineWidth=c/2,t.strokeStyle="rgba("+e.c.color+","+(c+.2)+")",t.moveTo(r.x,r.y),t.lineTo(s.x,s.y),t.stroke()))}),this.requestFrame(this.drawCanvas)}},{key:"destroy",value:function(){l(this.el),window.onmousemove=this.onmousemove,window.onmouseout=this.onmouseout,v(this.tid),this.canvas.parentNode.removeChild(this.canvas)}}]),e}()}); 2 | -------------------------------------------------------------------------------- /dist/canvas-nest.js: -------------------------------------------------------------------------------- 1 | !function(){"use strict";function e(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function t(e,t){return e(t={exports:{}},t.exports),t.exports}var n=t(function(e,t){Object.defineProperty(t,"__esModule",{value:!0});var n=1;t.default=function(){return""+n++},e.exports=t.default});e(n);var o=t(function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:30,n=null;return function(){for(var o=this,i=arguments.length,r=Array(i),a=0;an||r.x<0?-1:1,r.ya*=r.y>o||r.y<0?-1:1,t.fillRect(r.x-.5,r.y-.5,1,1),u=f+1;u=s.max/2&&(r.x-=.03*l,r.y-=.03*d),c=(s.max-v)/s.max,t.beginPath(),t.lineWidth=c/2,t.strokeStyle="rgba("+e.c.color+","+(c+.2)+")",t.moveTo(r.x,r.y),t.lineTo(s.x,s.y),t.stroke()))}),this.requestFrame(this.drawCanvas)}},{key:"destroy",value:function(){l(this.el),window.onmousemove=this.onmousemove,window.onmouseout=this.onmouseout,f(this.tid),this.canvas.parentNode.removeChild(this.canvas)}}]),e}())(document.body,(p=document.getElementsByTagName("script"),{zIndex:(w=p[p.length-1]).getAttribute("zIndex"),opacity:w.getAttribute("opacity"),color:w.getAttribute("color"),count:Number(w.getAttribute("count"))||99}))}(); 2 | -------------------------------------------------------------------------------- /lib/CanvasNest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 8 | 9 | var _createClass = function () { 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** 10 | * Created by hustcc on 18/6/23. 11 | * Contract: i@hust.cc 12 | */ 13 | 14 | var _sizeSensor = require('size-sensor'); 15 | 16 | var _utils = require('./utils'); 17 | 18 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 19 | 20 | var CanvasNest = function () { 21 | function CanvasNest(el, config) { 22 | var _this = this; 23 | 24 | _classCallCheck(this, CanvasNest); 25 | 26 | this.randomPoints = function () { 27 | return (0, _utils.range)(_this.c.count).map(function () { 28 | return { 29 | x: Math.random() * _this.canvas.width, 30 | y: Math.random() * _this.canvas.height, 31 | xa: 2 * Math.random() - 1, // 随机运动返现 32 | ya: 2 * Math.random() - 1, 33 | max: 6000 //沾附距离 34 | }; 35 | }); 36 | }; 37 | 38 | this.el = el; 39 | 40 | this.c = _extends({ 41 | zIndex: -1, // z-index 42 | opacity: 0.5, // opacity 43 | color: '0,0,0', // color 44 | count: 99 }, config); 45 | 46 | this.canvas = this.newCanvas(); 47 | this.context = this.canvas.getContext('2d'); 48 | 49 | this.points = this.randomPoints(); 50 | this.current = { 51 | x: null, // 当前鼠标x 52 | y: null, // 当前鼠标y 53 | max: 20000 // 圈半径的平方 54 | }; 55 | this.all = this.points.concat([this.current]); 56 | 57 | this.bindEvent(); 58 | 59 | this.requestFrame(this.drawCanvas); 60 | } 61 | 62 | _createClass(CanvasNest, [{ 63 | key: 'bindEvent', 64 | value: function bindEvent() { 65 | var _this2 = this; 66 | 67 | (0, _sizeSensor.bind)(this.el, function () { 68 | _this2.canvas.width = _this2.el.clientWidth; 69 | _this2.canvas.height = _this2.el.clientHeight; 70 | }); 71 | 72 | this.onmousemove = window.onmousemove; 73 | window.onmousemove = function (e) { 74 | _this2.current.x = e.clientX - _this2.el.offsetLeft; 75 | _this2.current.y = e.clientY - _this2.el.offsetTop; 76 | _this2.onmousemove && _this2.onmousemove(e); 77 | }; 78 | 79 | this.onmouseout = window.onmouseout; 80 | window.onmouseout = function () { 81 | _this2.current.x = null; 82 | _this2.current.y = null; 83 | _this2.onmouseout && _this2.onmouseout(); 84 | }; 85 | } 86 | }, { 87 | key: 'newCanvas', 88 | value: function newCanvas() { 89 | if (getComputedStyle(this.el).position === 'static') { 90 | this.el.style.position = 'relative'; 91 | } 92 | var canvas = document.createElement('canvas'); // 画布 93 | canvas.style.cssText = (0, _utils.canvasStyle)(this.c); 94 | 95 | canvas.width = this.el.clientWidth; 96 | canvas.height = this.el.clientHeight; 97 | 98 | this.el.appendChild(canvas); 99 | return canvas; 100 | } 101 | }, { 102 | key: 'requestFrame', 103 | value: function requestFrame(func) { 104 | var _this3 = this; 105 | 106 | this.tid = (0, _utils.requestAnimationFrame)(function () { 107 | return func.call(_this3); 108 | }); 109 | } 110 | }, { 111 | key: 'drawCanvas', 112 | value: function drawCanvas() { 113 | var _this4 = this; 114 | 115 | var context = this.context; 116 | var width = this.canvas.width; 117 | var height = this.canvas.height; 118 | var current = this.current; 119 | var points = this.points; 120 | var all = this.all; 121 | 122 | context.clearRect(0, 0, width, height); 123 | // 随机的线条和当前位置联合数组 124 | var e = void 0, 125 | i = void 0, 126 | d = void 0, 127 | x_dist = void 0, 128 | y_dist = void 0, 129 | dist = void 0; // 临时节点 130 | // 遍历处理每一个点 131 | points.forEach(function (r, idx) { 132 | r.x += r.xa; 133 | r.y += r.ya; // 移动 134 | r.xa *= r.x > width || r.x < 0 ? -1 : 1; 135 | r.ya *= r.y > height || r.y < 0 ? -1 : 1; // 碰到边界,反向反弹 136 | context.fillRect(r.x - 0.5, r.y - 0.5, 1, 1); // 绘制一个宽高为1的点 137 | // 从下一个点开始 138 | for (i = idx + 1; i < all.length; i++) { 139 | e = all[i]; 140 | // 当前点存在 141 | if (null !== e.x && null !== e.y) { 142 | x_dist = r.x - e.x; // x轴距离 l 143 | y_dist = r.y - e.y; // y轴距离 n 144 | dist = x_dist * x_dist + y_dist * y_dist; // 总距离, m 145 | 146 | dist < e.max && (e === current && dist >= e.max / 2 && (r.x -= 0.03 * x_dist, r.y -= 0.03 * y_dist), // 靠近的时候加速 147 | d = (e.max - dist) / e.max, context.beginPath(), context.lineWidth = d / 2, context.strokeStyle = 'rgba(' + _this4.c.color + ',' + (d + 0.2) + ')', context.moveTo(r.x, r.y), context.lineTo(e.x, e.y), context.stroke()); 148 | } 149 | } 150 | }); 151 | this.requestFrame(this.drawCanvas); 152 | } 153 | }, { 154 | key: 'destroy', 155 | value: function destroy() { 156 | // 清楚事件 157 | (0, _sizeSensor.clear)(this.el); 158 | 159 | // mouse 事件清楚 160 | window.onmousemove = this.onmousemove; // 回滚方法 161 | window.onmouseout = this.onmouseout; 162 | 163 | // 删除轮询 164 | (0, _utils.cancelAnimationFrame)(this.tid); 165 | 166 | // 删除 dom 167 | this.canvas.parentNode.removeChild(this.canvas); 168 | } 169 | }]); 170 | 171 | return CanvasNest; 172 | }(); 173 | 174 | exports.default = CanvasNest; 175 | module.exports = exports['default']; --------------------------------------------------------------------------------