├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── LICENSE
├── README.md
├── dist
├── materialImage.es5.js
└── materialImage.min.js
├── gulpfile.js
├── index.html
├── package.json
└── src
├── colors.js
└── index.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | index.html
2 | dist
3 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parser: 'babel-eslint',
4 | 'env': {
5 | 'browser': true,
6 | },
7 | parserOptions: {
8 | ecmaVersion: 6,
9 | sourceType: 'module'
10 | },
11 | extends: 'airbnb-base',
12 | plugins: [
13 | 'html'
14 | ],
15 | 'rules': {
16 | 'import/extensions': ['error', 'always', {
17 | 'js': 'never'
18 | }],
19 | 'arrow-parens': ["error", "as-needed"],
20 | // allow debugger during development
21 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
22 | 'no-console': process.env.NODE_ENV === 'production' ? 2 : 0,
23 | 'no-underscore-dangle': 0,
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Dependency directories
7 | node_modules
8 | jspm_packages
9 |
10 | # Optional npm cache directory
11 | .npm
12 |
13 | # Optional REPL history
14 | .node_repl_history
15 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Yusen
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MaterialImage
2 | Working!
3 |
4 | ```bash
5 | $ npm i material-image -S
6 | ```
7 |
8 | ## 使用方法
9 |
10 | ### ES6 Module:
11 | ``` javascript
12 | import MaterialImage from 'material-image';
13 |
14 | const myDom = document.querySelector('.my-dom');
15 | new MaterialImage({
16 | el: myDom,
17 | });
18 | ```
19 |
20 | ### Script:
21 | ``` html
22 |
23 |
24 |
30 | ```
31 |
32 | ### Configs:
33 | | 参数 | 类型 | 默认值 | 描述 |
34 | | ------------- |:-------------:|:-------:| :------------------:|
35 | | el | Element | body | 插入canvas的DOM节点 |
36 | | debug | Boolean | false | 调试模式开关 |
37 | | output | String | background | 三种输出模式,可选值:`background`、`image`、`canvas` |
38 | | imageType | String | jpeg | 输出为图片时(`background`、`image`)的图片类型 |
39 | | quality | Number | 1 | 输出为图片时(`background`、`image`)的图片质量,取值 `0~1` 之间 |
40 |
41 | ### Methods:
42 | | 名称 | 描述 |
43 | | ------------- |:--------------:|
44 | | protract | 重新绘制canvas |
45 | | adjust | 调整canvas尺寸 |
46 | | destroy | 移除canvas节点 |
47 | | toDataUrl | 生成 base64Url,参数 `(imageType, quality)` |
48 |
49 | ## 生成策略
50 |
51 | 随机一定数量的颜色,再随机画出不同尺寸、位置的图形(矩形和圆)。
52 |
53 | ## 开发计划
54 |
55 | 预定几种生成策略,比如同心圆、连续一定角度排列的矩形等。
56 | 添加元素移动效果。
57 |
58 | **Wait me!**
59 |
--------------------------------------------------------------------------------
/dist/materialImage.es5.js:
--------------------------------------------------------------------------------
1 | (function (global, factory) {
2 | if (typeof define === "function" && define.amd) {
3 | define(['module'], factory);
4 | } else if (typeof exports !== "undefined") {
5 | factory(module);
6 | } else {
7 | var mod = {
8 | exports: {}
9 | };
10 | factory(mod);
11 | global.MaterialImage = mod.exports;
12 | }
13 | })(this, function (module) {
14 | 'use strict';
15 |
16 | function _toArray(arr) {
17 | return Array.isArray(arr) ? arr : Array.from(arr);
18 | }
19 |
20 | function _classCallCheck(instance, Constructor) {
21 | if (!(instance instanceof Constructor)) {
22 | throw new TypeError("Cannot call a class as a function");
23 | }
24 | }
25 |
26 | var _createClass = function () {
27 | function defineProperties(target, props) {
28 | for (var i = 0; i < props.length; i++) {
29 | var descriptor = props[i];
30 | descriptor.enumerable = descriptor.enumerable || false;
31 | descriptor.configurable = true;
32 | if ("value" in descriptor) descriptor.writable = true;
33 | Object.defineProperty(target, descriptor.key, descriptor);
34 | }
35 | }
36 |
37 | return function (Constructor, protoProps, staticProps) {
38 | if (protoProps) defineProperties(Constructor.prototype, protoProps);
39 | if (staticProps) defineProperties(Constructor, staticProps);
40 | return Constructor;
41 | };
42 | }();
43 |
44 | /*!
45 | * yusen
46 | * https://github.com/yscoder/MaterialImage
47 | * MIT LICENSE
48 | */
49 |
50 | var colorPlate = ['#FFEBEE', '#FFCDD2', '#EF9A9A', '#E57373', '#EF5350', '#F44336', '#E53935', '#D32F2F', '#C62828', '#B71C1C', '#FF8A80', '#FF5252', '#FF1744', '#D50000', '#FCE4EC', '#F8BBD0', '#F48FB1', '#F06292', '#EC407A', '#E91E63', '#D81B60', '#C2185B', '#AD1457', '#880E4F', '#FF80AB', '#FF4081', '#F50057', '#C51162', '#F3E5F5', '#E1BEE7', '#CE93D8', '#BA68C8', '#AB47BC', '#9C27B0', '#8E24AA', '#7B1FA2', '#6A1B9A', '#4A148C', '#EA80FC', '#E040FB', '#D500F9', '#AA00FF', '#EDE7F6', '#D1C4E9', '#B39DDB', '#9575CD', '#7E57C2', '#673AB7', '#5E35B1', '#512DA8', '#4527A0', '#311B92', '#B388FF', '#7C4DFF', '#651FFF', '#6200EA', '#E8EAF6', '#C5CAE9', '#9FA8DA', '#7986CB', '#5C6BC0', '#3F51B5', '#3949AB', '#303F9F', '#283593', '#1A237E', '#8C9EFF', '#536DFE', '#3D5AFE', '#304FFE', '#E3F2FD', '#BBDEFB', '#90CAF9', '#64B5F6', '#42A5F5', '#2196F3', '#1E88E5', '#1976D2', '#1565C0', '#0D47A1', '#82B1FF', '#448AFF', '#2979FF', '#2962FF', '#E1F5FE', '#B3E5FC', '#81D4FA', '#4FC3F7', '#29B6F6', '#03A9F4', '#039BE5', '#0288D1', '#0277BD', '#01579B', '#80D8FF', '#40C4FF', '#00B0FF', '#0091EA', '#E0F2F1', '#B2DFDB', '#80CBC4', '#4DB6AC', '#26A69A', '#009688', '#00897B', '#00796B', '#00695C', '#004D40', '#A7FFEB', '#64FFDA', '#1DE9B6', '#00BFA5', '#E0F7FA', '#B2EBF2', '#80DEEA', '#4DD0E1', '#26C6DA', '#00BCD4', '#00ACC1', '#0097A7', '#00838F', '#006064', '#84FFFF', '#18FFFF', '#00E5FF', '#00B8D4', '#E8F5E9', '#C8E6C9', '#A5D6A7', '#81C784', '#66BB6A', '#4CAF50', '#43A047', '#388E3C', '#2E7D32', '#1B5E20', '#B9F6CA', '#69F0AE', '#00E676', '#00C853', '#F1F8E9', '#DCEDC8', '#C5E1A5', '#AED581', '#9CCC65', '#8BC34A', '#7CB342', '#689F38', '#558B2F', '#33691E', '#CCFF90', '#B2FF59', '#76FF03', '#64DD17', '#F9FBE7', '#F0F4C3', '#E6EE9C', '#DCE775', '#D4E157', '#CDDC39', '#C0CA33', '#AFB42B', '#9E9D24', '#827717', '#F4FF81', '#EEFF41', '#C6FF00', '#AEEA00', '#FFFDE7', '#FFF9C4', '#FFF59D', '#FFF176', '#FFEE58', '#FFEB3B', '#FDD835', '#FBC02D', '#F9A825', '#F57F17', '#FFFF8D', '#FFFF00', '#FFEA00', '#FFD600', '#FFF8E1', '#FFECB3', '#FFE082', '#FFD54F', '#FFCA28', '#FFC107', '#FFB300', '#FFA000', '#FF8F00', '#FF6F00', '#FFE57F', '#FFD740', '#FFC400', '#FFAB00', '#FFF3E0', '#FFE0B2', '#FFCC80', '#FFB74D', '#FFA726', '#FF9800', '#FB8C00', '#F57C00', '#EF6C00', '#E65100', '#FFD180', '#FFAB40', '#FF9100', '#FF6D00', '#FBE9E7', '#FFCCBC', '#FFAB91', '#FF8A65', '#FF7043', '#FF5722', '#F4511E', '#E64A19', '#D84315', '#BF360C', '#FF9E80', '#FF6E40', '#FF3D00', '#DD2C00', '#FAFAFA', '#F5F5F5', '#EEEEEE', '#E0E0E0', '#BDBDBD', '#9E9E9E', '#757575', '#616161', '#424242', '#212121', '#ECEFF1', '#CFD8DC', '#B0BEC5', '#90A4AE', '#78909C', '#607D8B', '#546E7A', '#455A64', '#37474F', '#263238', '#EFEBE9', '#D7CCC8', '#BCAAA4', '#A1887F', '#8D6E63', '#795548', '#6D4C41', '#5D4037', '#4E342E', '#3E2723'];
51 |
52 | var random = function random(min, max) {
53 | return Math.floor(Math.random() * (max - min + 1) + min);
54 | };
55 |
56 | var getRandomColor = function getRandomColor() {
57 | return colorPlate[random(0, colorPlate.length - 1)];
58 | };
59 |
60 | var getColors = function getColors(count) {
61 | var colors = [];
62 | for (var i = 0; i <= count;) {
63 | var color = getRandomColor();
64 | if (colors.indexOf(color) === -1) {
65 | colors.push(color);
66 | i += 1;
67 | }
68 | }
69 | return colors;
70 | };
71 |
72 | var createCanvas = function createCanvas(width, height) {
73 | var canvas = document.createElement('canvas');
74 | canvas.width = width;
75 | canvas.height = height;
76 | return canvas;
77 | };
78 |
79 | var getShape = function getShape() {
80 | return ['rect', 'arc'][random(0, 1)];
81 | };
82 |
83 | var Drawer = function () {
84 | function Drawer(canvas) {
85 | _classCallCheck(this, Drawer);
86 |
87 | this.ctx = canvas.getContext('2d');
88 | }
89 |
90 | _createClass(Drawer, [{
91 | key: 'shadow',
92 | value: function shadow(_ref) {
93 | var blur = _ref.blur,
94 | _ref$x = _ref.x,
95 | x = _ref$x === undefined ? 1 : _ref$x,
96 | _ref$y = _ref.y,
97 | y = _ref$y === undefined ? 1 : _ref$y,
98 | _ref$color = _ref.color,
99 | color = _ref$color === undefined ? 'rgba(0, 0, 0, .3)' : _ref$color;
100 |
101 | this.ctx.shadowBlur = blur;
102 | this.ctx.shadowOffsetX = x;
103 | this.ctx.shadowOffsetY = y;
104 | this.ctx.shadowColor = color;
105 | }
106 | }, {
107 | key: 'rect',
108 | value: function rect(_ref2) {
109 | var width = _ref2.width,
110 | height = _ref2.height;
111 |
112 | var r = random(10, 360) * Math.PI / 180;
113 | var w = random(100, Math.max(width, height)) * (random(-10, 10) || 1);
114 | var h = random(100, Math.min(width, height)) * (random(-10, 10) || 1);
115 | this.ctx.rotate(r);
116 | this.ctx.rect(0, 0, w, h);
117 | this.ctx.rotate(-r);
118 | }
119 | }, {
120 | key: 'arc',
121 | value: function arc(_ref3) {
122 | var width = _ref3.width,
123 | height = _ref3.height;
124 |
125 | var r = random(100, Math.min(width, height) / 2);
126 | this.ctx.arc(0, 0, r, 0, 2 * Math.PI);
127 | }
128 | }, {
129 | key: 'draw',
130 | value: function draw(sharp, option) {
131 | var width = option.width,
132 | height = option.height,
133 | color = option.color;
134 |
135 |
136 | this.ctx.beginPath();
137 | this.shadow({
138 | blur: 20
139 | });
140 |
141 | var x = random(0, width);
142 | var y = random(0, height);
143 | this.ctx.translate(x, y);
144 | this[sharp](option);
145 | this.ctx.closePath();
146 | this.ctx.fillStyle = color;
147 | this.ctx.fill();
148 | this.ctx.translate(-x, -y);
149 | }
150 | }, {
151 | key: 'fill',
152 | value: function fill(color, width, height) {
153 | this.ctx.fillStyle = color;
154 | this.ctx.fillRect(0, 0, width, height);
155 | }
156 | }]);
157 |
158 | return Drawer;
159 | }();
160 |
161 | var MaterialImage = function () {
162 | function MaterialImage() {
163 | var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
164 |
165 | _classCallCheck(this, MaterialImage);
166 |
167 | var _config$el = config.el,
168 | el = _config$el === undefined ? document.querySelector('body') : _config$el,
169 | _config$debug = config.debug,
170 | debug = _config$debug === undefined ? false : _config$debug,
171 | _config$output = config.output,
172 | output = _config$output === undefined ? 'background' : _config$output,
173 | imageType = config.imageType,
174 | quality = config.quality;
175 |
176 |
177 | var width = el.clientWidth;
178 | var height = el.clientHeight;
179 |
180 | this.debug = debug;
181 | this.element = el;
182 | this.width = width;
183 | this.height = height;
184 | this.outputType = output;
185 | this.outputOption = {
186 | imageType: imageType,
187 | quality: quality
188 | };
189 | this.canvas = createCanvas(width, height);
190 | this.render();
191 | this.protract();
192 | }
193 |
194 | _createClass(MaterialImage, [{
195 | key: 'output',
196 | value: function output() {
197 | if (this.outputType === 'canvas') return;
198 |
199 | var dataUrl = this.toDataUrl(this.outputOption);
200 | switch (this.outputType) {
201 | case 'background':
202 | this.element.style.backgroundImage = 'url("' + dataUrl + '")';
203 | break;
204 | case 'image':
205 | this.img.src = dataUrl;
206 | break;
207 | default:
208 | break;
209 | }
210 | }
211 | }, {
212 | key: 'protract',
213 | value: function protract() {
214 | var _this = this;
215 |
216 | var count = random(0, 8) + 6;
217 |
218 | var _getColors = getColors(count),
219 | _getColors2 = _toArray(_getColors),
220 | background = _getColors2[0],
221 | colors = _getColors2.slice(1);
222 |
223 | var drawer = new Drawer(this.canvas);
224 | var width = this.width;
225 | var height = this.height;
226 |
227 | drawer.fill(background, width, height);
228 |
229 | var i = 0;
230 | if (!this.debug) {
231 | while (i < count) {
232 | drawer.draw(getShape(), {
233 | color: colors[i],
234 | width: width,
235 | height: height
236 | });
237 | i += 1;
238 | }
239 | this.output();
240 | } else {
241 | var debugDraw = function debugDraw() {
242 | drawer.draw(getShape(), {
243 | color: colors[i],
244 | width: width,
245 | height: height
246 | });
247 | _this.output();
248 | i += 1;
249 | if (i < count) {
250 | setTimeout(debugDraw, 1000);
251 | }
252 | };
253 | setTimeout(debugDraw, 1000);
254 | }
255 | }
256 | }, {
257 | key: 'adjust',
258 | value: function adjust() {
259 | var canvas = this.canvas;
260 | var element = this.element;
261 |
262 | canvas.width = element.clientWidth;
263 | canvas.height = element.clientHeight;
264 |
265 | this.protract();
266 | }
267 | }, {
268 | key: 'toDataUrl',
269 | value: function toDataUrl() {
270 | var imageType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'jpeg';
271 | var quality = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
272 |
273 | return this.canvas.toDataURL('image/' + imageType, quality);
274 | }
275 | }, {
276 | key: 'render',
277 | value: function render() {
278 | switch (this.outputType) {
279 | case 'canvas':
280 | this.element.appendChild(this.canvas);
281 | break;
282 | case 'background':
283 | this.element.style.cssText += '\n background-repeat: no-repeat;\n background-size: cover;';
284 | break;
285 | case 'image':
286 | this.img = document.createElement('img');
287 | this.img.style.cssText = 'width: 100%; height: 100%';
288 | this.element.appendChild(this.img);
289 | break;
290 | default:
291 | break;
292 | }
293 | }
294 | }, {
295 | key: 'destroy',
296 | value: function destroy() {
297 | switch (this.outputType) {
298 | case 'canvas':
299 | this.canvas.remove();
300 | break;
301 | case 'background':
302 | {
303 | var cssText = this.element.style.cssText;
304 | this.element.style.cssText = cssText.replace(/background[^;]+;/g, '');
305 | break;
306 | }
307 | case 'image':
308 | this.img.remove();
309 | break;
310 | default:
311 | break;
312 | }
313 | }
314 | }]);
315 |
316 | return MaterialImage;
317 | }();
318 |
319 | module.exports = MaterialImage;
320 | });
--------------------------------------------------------------------------------
/dist/materialImage.min.js:
--------------------------------------------------------------------------------
1 | !function(t,F){if("function"==typeof define&&define.amd)define(["module"],F);else if("undefined"!=typeof exports)F(module);else{var e={exports:{}};F(e),t.MaterialImage=e.exports}}(this,function(t){"use strict";function F(t){return Array.isArray(t)?t:Array.from(t)}function e(t,F){if(!(t instanceof F))throw new TypeError("Cannot call a class as a function")}var i=function(){function t(t,F){for(var e=0;e0&&void 0!==arguments[0]?arguments[0]:{};e(this,t);var i=F.el,a=void 0===i?document.querySelector("body"):i,n=F.debug,r=void 0!==n&&n,s=F.output,h=void 0===s?"background":s,o=F.imageType,c=F.quality,u=a.clientWidth,C=a.clientHeight;this.debug=r,this.element=a,this.width=u,this.height=C,this.outputType=h,this.outputOption={imageType:o,quality:c},this.canvas=E(u,C),this.render(),this.protract()}return i(t,[{key:"output",value:function(){if("canvas"!==this.outputType){var t=this.toDataUrl(this.outputOption);switch(this.outputType){case"background":this.element.style.backgroundImage='url("'+t+'")';break;case"image":this.img.src=t}}}},{key:"protract",value:function(){var t=this,e=n(0,8)+6,i=s(e),a=F(i),r=a[0],E=a.slice(1),c=new o(this.canvas),u=this.width,C=this.height;c.fill(r,u,C);var l=0;if(this.debug){var A=function F(){c.draw(h(),{color:E[l],width:u,height:C}),t.output(),(l+=1)0&&void 0!==arguments[0]?arguments[0]:"jpeg",F=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;return this.canvas.toDataURL("image/"+t,F)}},{key:"render",value:function(){switch(this.outputType){case"canvas":this.element.appendChild(this.canvas);break;case"background":this.element.style.cssText+="\n background-repeat: no-repeat;\n background-size: cover;";break;case"image":this.img=document.createElement("img"),this.img.style.cssText="width: 100%; height: 100%",this.element.appendChild(this.img)}}},{key:"destroy",value:function(){switch(this.outputType){case"canvas":this.canvas.remove();break;case"background":var t=this.element.style.cssText;this.element.style.cssText=t.replace(/background[^;]+;/g,"");break;case"image":this.img.remove()}}}]),t}();t.exports=c});
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | const gulp = require('gulp');
2 | const babel = require('gulp-babel');
3 | const uglify = require('gulp-uglify');
4 | const rename = require('gulp-rename');
5 | const browserSync = require('browser-sync');
6 | const eslint = require('gulp-eslint');
7 |
8 | const src = './src/';
9 | const dist = './dist/';
10 |
11 | const buildEs5 = () => gulp.src(`${src}index.js`)
12 | .pipe(rename('MaterialImage.js'))
13 | .pipe(babel({
14 | presets: ['es2015'],
15 | plugins: [
16 | ['transform-es2015-modules-umd', {
17 | globals: {
18 | 'es6-promise': 'Promise',
19 | },
20 | }],
21 | ],
22 | }))
23 | .pipe(rename('materialImage.es5.js'))
24 | .pipe(gulp.dest('dist'));
25 |
26 | gulp.task('build', () => buildEs5()
27 | .pipe(uglify({
28 | preserveComments: 'license',
29 | }))
30 | .pipe(rename('materialImage.min.js'))
31 | .pipe(gulp.dest(dist)));
32 |
33 | gulp.task('es5', () => buildEs5());
34 |
35 | gulp.task('dev', () => {
36 | browserSync.init({
37 | server: {
38 | baseDir: './',
39 | },
40 | });
41 |
42 | gulp.watch('index.html', browserSync.reload);
43 | gulp.watch(`${src}*.*`, ['es5']).on('change', browserSync.reload);
44 | });
45 |
46 | gulp.task('lint', () => gulp.src(`${src}index.js`)
47 | .pipe(eslint())
48 | .pipe(eslint.format()));
49 |
50 | gulp.task('default', ['build']);
51 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | MaterialImage
6 |
20 |
21 |
22 |
23 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "material-image",
3 | "version": "0.2.5",
4 | "description": "Generate random material design background image.",
5 | "main": "dist/materialImage.min.js",
6 | "keywords": [
7 | "material",
8 | "design",
9 | "background",
10 | "random",
11 | "image"
12 | ],
13 | "author": "yusen",
14 | "license": "MIT",
15 | "devDependencies": {
16 | "babel-eslint": "^7.2.1",
17 | "babel-plugin-transform-es2015-modules-umd": "^6.24.0",
18 | "babel-preset-es2015": "^6.24.0",
19 | "browser-sync": "^2.18.2",
20 | "eslint-config-airbnb-base": "^11.1.3",
21 | "eslint-friendly-formatter": "^2.0.7",
22 | "eslint-import-resolver-webpack": "^0.8.1",
23 | "eslint-loader": "^1.6.1",
24 | "eslint-plugin-html": "^2.0.0",
25 | "eslint-plugin-import": "^2.2.0",
26 | "gulp": "^3.9.1",
27 | "gulp-babel": "^6.1.2",
28 | "gulp-eslint": "^3.0.1",
29 | "gulp-rename": "^1.2.2",
30 | "gulp-uglify": "^2.1.2"
31 | },
32 | "repository": {
33 | "type": "git",
34 | "url": "git+https://github.com/yscoder/MaterialImage.git"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/colors.js:
--------------------------------------------------------------------------------
1 | export default {
2 | "red": ["#FFEBEE", "#FFCDD2", "#EF9A9A", "#E57373", "#EF5350", "#F44336", "#E53935", "#D32F2F", "#C62828", "#B71C1C", "#FF8A80", "#FF5252", "#FF1744", "#D50000"],
3 | "pink": ["#FCE4EC", "#F8BBD0", "#F48FB1", "#F06292", "#EC407A", "#E91E63", "#D81B60", "#C2185B", "#AD1457", "#880E4F", "#FF80AB", "#FF4081", "#F50057", "#C51162"],
4 | "purple": ["#F3E5F5", "#E1BEE7", "#CE93D8", "#BA68C8", "#AB47BC", "#9C27B0", "#8E24AA", "#7B1FA2", "#6A1B9A", "#4A148C", "#EA80FC", "#E040FB", "#D500F9", "#AA00FF"],
5 | "deepPurple": ["#EDE7F6", "#D1C4E9", "#B39DDB", "#9575CD", "#7E57C2", "#673AB7", "#5E35B1", "#512DA8", "#4527A0", "#311B92", "#B388FF", "#7C4DFF", "#651FFF", "#6200EA"],
6 | "indigo": ["#E8EAF6", "#C5CAE9", "#9FA8DA", "#7986CB", "#5C6BC0", "#3F51B5", "#3949AB", "#303F9F", "#283593", "#1A237E", "#8C9EFF", "#536DFE", "#3D5AFE", "#304FFE"],
7 | "blue": ["#E3F2FD", "#BBDEFB", "#90CAF9", "#64B5F6", "#42A5F5", "#2196F3", "#1E88E5", "#1976D2", "#1565C0", "#0D47A1", "#82B1FF", "#448AFF", "#2979FF", "#2962FF"],
8 | "lightBlue": ["#E1F5FE", "#B3E5FC", "#81D4FA", "#4FC3F7", "#29B6F6", "#03A9F4", "#039BE5", "#0288D1", "#0277BD", "#01579B", "#80D8FF", "#40C4FF", "#00B0FF", "#0091EA"],
9 | "teal": ["#E0F2F1", "#B2DFDB", "#80CBC4", "#4DB6AC", "#26A69A", "#009688", "#00897B", "#00796B", "#00695C", "#004D40", "#A7FFEB", "#64FFDA", "#1DE9B6", "#00BFA5"],
10 | "cyan": ["#E0F7FA", "#B2EBF2", "#80DEEA", "#4DD0E1", "#26C6DA", "#00BCD4", "#00ACC1", "#0097A7", "#00838F", "#006064", "#84FFFF", "#18FFFF", "#00E5FF", "#00B8D4"],
11 | "green": ["#E8F5E9", "#C8E6C9", "#A5D6A7", "#81C784", "#66BB6A", "#4CAF50", "#43A047", "#388E3C", "#2E7D32", "#1B5E20", "#B9F6CA", "#69F0AE", "#00E676", "#00C853"],
12 | "lightGreen": ["#F1F8E9", "#DCEDC8", "#C5E1A5", "#AED581", "#9CCC65", "#8BC34A", "#7CB342", "#689F38", "#558B2F", "#33691E", "#CCFF90", "#B2FF59", "#76FF03", "#64DD17"],
13 | "lime": ["#F9FBE7", "#F0F4C3", "#E6EE9C", "#DCE775", "#D4E157", "#CDDC39", "#C0CA33", "#AFB42B", "#9E9D24", "#827717", "#F4FF81", "#EEFF41", "#C6FF00", "#AEEA00"],
14 | "yellow": ["#FFFDE7", "#FFF9C4", "#FFF59D", "#FFF176", "#FFEE58", "#FFEB3B", "#FDD835", "#FBC02D", "#F9A825", "#F57F17", "#FFFF8D", "#FFFF00", "#FFEA00", "#FFD600"],
15 | "amber": ["#FFF8E1", "#FFECB3", "#FFE082", "#FFD54F", "#FFCA28", "#FFC107", "#FFB300", "#FFA000", "#FF8F00", "#FF6F00", "#FFE57F", "#FFD740", "#FFC400", "#FFAB00"],
16 | "orange": ["#FFF3E0", "#FFE0B2", "#FFCC80", "#FFB74D", "#FFA726", "#FF9800", "#FB8C00", "#F57C00", "#EF6C00", "#E65100", "#FFD180", "#FFAB40", "#FF9100", "#FF6D00"],
17 | "deepOrange": ["#FBE9E7", "#FFCCBC", "#FFAB91", "#FF8A65", "#FF7043", "#FF5722", "#F4511E", "#E64A19", "#D84315", "#BF360C", "#FF9E80", "#FF6E40", "#FF3D00", "#DD2C00"],
18 | "grey": ["#FAFAFA", "#F5F5F5", "#EEEEEE", "#E0E0E0", "#BDBDBD", "#9E9E9E", "#757575", "#616161", "#424242", "#212121"],
19 | "blueGrey": ["#ECEFF1", "#CFD8DC", "#B0BEC5", "#90A4AE", "#78909C", "#607D8B", "#546E7A", "#455A64", "#37474F", "#263238"],
20 | "brown": ["#EFEBE9", "#D7CCC8", "#BCAAA4", "#A1887F", "#8D6E63", "#795548", "#6D4C41", "#5D4037", "#4E342E", "#3E2723"]
21 | }
22 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * yusen
3 | * https://github.com/yscoder/MaterialImage
4 | * MIT LICENSE
5 | */
6 |
7 | const colorPlate = [
8 | '#FFEBEE', '#FFCDD2', '#EF9A9A', '#E57373', '#EF5350', '#F44336', '#E53935', '#D32F2F', '#C62828', '#B71C1C', '#FF8A80', '#FF5252', '#FF1744', '#D50000', '#FCE4EC', '#F8BBD0', '#F48FB1', '#F06292', '#EC407A', '#E91E63', '#D81B60', '#C2185B', '#AD1457', '#880E4F', '#FF80AB', '#FF4081', '#F50057', '#C51162', '#F3E5F5', '#E1BEE7', '#CE93D8', '#BA68C8', '#AB47BC', '#9C27B0', '#8E24AA', '#7B1FA2', '#6A1B9A', '#4A148C', '#EA80FC', '#E040FB', '#D500F9', '#AA00FF', '#EDE7F6', '#D1C4E9', '#B39DDB', '#9575CD', '#7E57C2', '#673AB7', '#5E35B1', '#512DA8', '#4527A0', '#311B92', '#B388FF', '#7C4DFF', '#651FFF', '#6200EA', '#E8EAF6', '#C5CAE9', '#9FA8DA', '#7986CB', '#5C6BC0', '#3F51B5', '#3949AB', '#303F9F', '#283593', '#1A237E', '#8C9EFF', '#536DFE', '#3D5AFE', '#304FFE', '#E3F2FD', '#BBDEFB', '#90CAF9', '#64B5F6', '#42A5F5', '#2196F3', '#1E88E5', '#1976D2', '#1565C0', '#0D47A1', '#82B1FF', '#448AFF', '#2979FF', '#2962FF', '#E1F5FE', '#B3E5FC', '#81D4FA', '#4FC3F7', '#29B6F6', '#03A9F4', '#039BE5', '#0288D1', '#0277BD', '#01579B', '#80D8FF', '#40C4FF', '#00B0FF', '#0091EA', '#E0F2F1', '#B2DFDB', '#80CBC4', '#4DB6AC', '#26A69A', '#009688', '#00897B', '#00796B', '#00695C', '#004D40', '#A7FFEB', '#64FFDA', '#1DE9B6', '#00BFA5', '#E0F7FA', '#B2EBF2', '#80DEEA', '#4DD0E1', '#26C6DA', '#00BCD4', '#00ACC1', '#0097A7', '#00838F', '#006064', '#84FFFF', '#18FFFF', '#00E5FF', '#00B8D4', '#E8F5E9', '#C8E6C9', '#A5D6A7', '#81C784', '#66BB6A', '#4CAF50', '#43A047', '#388E3C', '#2E7D32', '#1B5E20', '#B9F6CA', '#69F0AE', '#00E676', '#00C853', '#F1F8E9', '#DCEDC8', '#C5E1A5', '#AED581', '#9CCC65', '#8BC34A', '#7CB342', '#689F38', '#558B2F', '#33691E', '#CCFF90', '#B2FF59', '#76FF03', '#64DD17', '#F9FBE7', '#F0F4C3', '#E6EE9C', '#DCE775', '#D4E157', '#CDDC39', '#C0CA33', '#AFB42B', '#9E9D24', '#827717', '#F4FF81', '#EEFF41', '#C6FF00', '#AEEA00', '#FFFDE7', '#FFF9C4', '#FFF59D', '#FFF176', '#FFEE58', '#FFEB3B', '#FDD835', '#FBC02D', '#F9A825', '#F57F17', '#FFFF8D', '#FFFF00', '#FFEA00', '#FFD600', '#FFF8E1', '#FFECB3', '#FFE082', '#FFD54F', '#FFCA28', '#FFC107', '#FFB300', '#FFA000', '#FF8F00', '#FF6F00', '#FFE57F', '#FFD740', '#FFC400', '#FFAB00', '#FFF3E0', '#FFE0B2', '#FFCC80', '#FFB74D', '#FFA726', '#FF9800', '#FB8C00', '#F57C00', '#EF6C00', '#E65100', '#FFD180', '#FFAB40', '#FF9100', '#FF6D00', '#FBE9E7', '#FFCCBC', '#FFAB91', '#FF8A65', '#FF7043', '#FF5722', '#F4511E', '#E64A19', '#D84315', '#BF360C', '#FF9E80', '#FF6E40', '#FF3D00', '#DD2C00', '#FAFAFA', '#F5F5F5', '#EEEEEE', '#E0E0E0', '#BDBDBD', '#9E9E9E', '#757575', '#616161', '#424242', '#212121', '#ECEFF1', '#CFD8DC', '#B0BEC5', '#90A4AE', '#78909C', '#607D8B', '#546E7A', '#455A64', '#37474F', '#263238', '#EFEBE9', '#D7CCC8', '#BCAAA4', '#A1887F', '#8D6E63', '#795548', '#6D4C41', '#5D4037', '#4E342E', '#3E2723',
9 | ];
10 |
11 | const random = (min, max) => Math.floor((Math.random() * ((max - min) + 1)) + min);
12 |
13 | const getRandomColor = () => colorPlate[random(0, colorPlate.length - 1)];
14 |
15 | const getColors = count => {
16 | const colors = [];
17 | for (let i = 0; i <= count;) {
18 | const color = getRandomColor();
19 | if (colors.indexOf(color) === -1) {
20 | colors.push(color);
21 | i += 1;
22 | }
23 | }
24 | return colors;
25 | };
26 |
27 | const createCanvas = (width, height) => {
28 | const canvas = document.createElement('canvas');
29 | canvas.width = width;
30 | canvas.height = height;
31 | return canvas;
32 | };
33 |
34 | const getShape = () => ['rect', 'arc'][random(0, 1)];
35 |
36 | class Drawer {
37 | constructor(canvas) {
38 | this.ctx = canvas.getContext('2d');
39 | }
40 |
41 | shadow({ blur, x = 1, y = 1, color = 'rgba(0, 0, 0, .3)' }) {
42 | this.ctx.shadowBlur = blur;
43 | this.ctx.shadowOffsetX = x;
44 | this.ctx.shadowOffsetY = y;
45 | this.ctx.shadowColor = color;
46 | }
47 |
48 | rect({ width, height }) {
49 | const r = (random(10, 360) * Math.PI) / 180;
50 | const w = random(100, Math.max(width, height)) * (random(-10, 10) || 1);
51 | const h = random(100, Math.min(width, height)) * (random(-10, 10) || 1);
52 | this.ctx.rotate(r);
53 | this.ctx.rect(0, 0, w, h);
54 | this.ctx.rotate(-r);
55 | }
56 |
57 | arc({ width, height }) {
58 | const r = random(100, Math.min(width, height) / 2);
59 | this.ctx.arc(0, 0, r, 0, 2 * Math.PI);
60 | }
61 |
62 | draw(sharp, option) {
63 | const { width, height, color } = option;
64 |
65 | this.ctx.beginPath();
66 | this.shadow({
67 | blur: 20,
68 | });
69 |
70 | const x = random(0, width);
71 | const y = random(0, height);
72 | this.ctx.translate(x, y);
73 | this[sharp](option);
74 | this.ctx.closePath();
75 | this.ctx.fillStyle = color;
76 | this.ctx.fill();
77 | this.ctx.translate(-x, -y);
78 | }
79 |
80 | fill(color, width, height) {
81 | this.ctx.fillStyle = color;
82 | this.ctx.fillRect(0, 0, width, height);
83 | }
84 | }
85 |
86 | class MaterialImage {
87 | constructor(config = {}) {
88 | const {
89 | el = document.querySelector('body'),
90 | debug = false,
91 | output = 'background',
92 | imageType,
93 | quality } = config;
94 |
95 | const width = el.clientWidth;
96 | const height = el.clientHeight;
97 |
98 | this.debug = debug;
99 | this.element = el;
100 | this.width = width;
101 | this.height = height;
102 | this.outputType = output;
103 | this.outputOption = {
104 | imageType,
105 | quality,
106 | };
107 | this.canvas = createCanvas(width, height);
108 | this.render();
109 | this.protract();
110 | }
111 |
112 | output() {
113 | if (this.outputType === 'canvas') return;
114 |
115 | const dataUrl = this.toDataUrl(this.outputOption);
116 | switch (this.outputType) {
117 | case 'background':
118 | this.element.style.backgroundImage = `url("${dataUrl}")`;
119 | break;
120 | case 'image':
121 | this.img.src = dataUrl;
122 | break;
123 | default:
124 | break;
125 | }
126 | }
127 |
128 | protract() {
129 | const count = random(0, 8) + 6;
130 | const [background, ...colors] = getColors(count);
131 | const drawer = new Drawer(this.canvas);
132 | const width = this.width;
133 | const height = this.height;
134 |
135 | drawer.fill(background, width, height);
136 |
137 | let i = 0;
138 | if (!this.debug) {
139 | while (i < count) {
140 | drawer.draw(getShape(), {
141 | color: colors[i],
142 | width,
143 | height,
144 | });
145 | i += 1;
146 | }
147 | this.output();
148 | } else {
149 | const debugDraw = () => {
150 | drawer.draw(getShape(), {
151 | color: colors[i],
152 | width,
153 | height,
154 | });
155 | this.output();
156 | i += 1;
157 | if (i < count) {
158 | setTimeout(debugDraw, 1000);
159 | }
160 | };
161 | setTimeout(debugDraw, 1000);
162 | }
163 | }
164 |
165 | adjust() {
166 | const canvas = this.canvas;
167 | const element = this.element;
168 |
169 | canvas.width = element.clientWidth;
170 | canvas.height = element.clientHeight;
171 |
172 | this.protract();
173 | }
174 |
175 | toDataUrl(imageType = 'jpeg', quality = 1) {
176 | return this.canvas.toDataURL(`image/${imageType}`, quality);
177 | }
178 |
179 | render() {
180 | switch (this.outputType) {
181 | case 'canvas':
182 | this.element.appendChild(this.canvas);
183 | break;
184 | case 'background':
185 | this.element.style.cssText += `
186 | background-repeat: no-repeat;
187 | background-size: cover;`;
188 | break;
189 | case 'image':
190 | this.img = document.createElement('img');
191 | this.img.style.cssText = 'width: 100%; height: 100%';
192 | this.element.appendChild(this.img);
193 | break;
194 | default:
195 | break;
196 | }
197 | }
198 |
199 | destroy() {
200 | switch (this.outputType) {
201 | case 'canvas':
202 | this.canvas.remove();
203 | break;
204 | case 'background': {
205 | const cssText = this.element.style.cssText;
206 | this.element.style.cssText = cssText.replace(/background[^;]+;/g, '');
207 | break;
208 | }
209 | case 'image':
210 | this.img.remove();
211 | break;
212 | default:
213 | break;
214 | }
215 | }
216 | }
217 |
218 | module.exports = MaterialImage;
219 |
--------------------------------------------------------------------------------