├── .babelrc ├── .gitignore ├── README.md ├── docs ├── app.d9a599697e67071509d7.css ├── app.d9a599697e67071509d7.js ├── index.html └── vendors.js ├── package.json ├── src ├── index.html ├── index.js ├── index.less └── js │ ├── config.js │ ├── down-up-mergesort.js │ ├── insert-sort.js │ ├── quick-sort.js │ ├── rx-sort.js │ ├── select-sort.js │ ├── sort-PQ-quick.js │ ├── up-down-mergesort.js │ └── util.js └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rxjs-sort-visualization 2 | ### sorting algorithm visualization build by Rxjs 3 | 4 | [online](https://xiyuyizhi.github.io/rxjs-sort-visualization/) 5 | -------------------------------------------------------------------------------- /docs/app.d9a599697e67071509d7.css: -------------------------------------------------------------------------------- 1 | #app .title{text-align:center}#app .chart-container{min-height:500px} -------------------------------------------------------------------------------- /docs/app.d9a599697e67071509d7.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([1],{0:function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}var i=n(146),o=r(i),u=n(324),s=r(u),f=n(145);n(574);var c=o["default"].init((0,f.query)(".chart-container")),a=void 0,l=s["default"].Observable.fromEvent((0,f.query)(".numberCreator"),"click").map(function(t){return(0,f.numberCreator)()})["do"](function(t){var e=(0,f.getOption)(t);c.setOption(e)}),h=s["default"].Observable.fromEvent((0,f.query)(".sortTypes"),"change").map(function(t){return t.target}).map(function(t){return t.options[t.selectedIndex].value}).map(function(t){return{type:t,timer:1}}).filter(function(t){return"0"!==t.type})["do"](function(t){a=t.type});s["default"].Observable.combineLatest(l,h).sort().flatMap(function(t){return s["default"].Observable.of(t).delay(100*t.select.timer++)}).filter(function(t){return t.select.type==a})["do"](function(t){var e=(0,f.getOption)(t.nums);c.setOption(e)}).subscribe(function(){},null,function(){})},145:function(t,e){"use strict";function n(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:300,e=new Array(t).fill(0);return e.map(function(e){return Math.ceil(Math.random()*t)})}function r(t){return document.querySelector(t)}function i(t){return{color:["#3398DB"],xAxis:[{type:"category",data:[],axisTick:{alignWithLabel:!0}}],yAxis:[{type:"value"}],series:[{type:"bar",data:t}]}}function o(t){return new Array(t.length).fill(0).map(function(e,n){return t[n]})}Object.defineProperty(e,"__esModule",{value:!0}),e.numberCreator=n,e.query=r,e.getOption=i,e.clone=o},320:function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0}),e.sortTypes=void 0;var i=n(325),o=r(i),u=n(323),s=r(u),f=n(322),c=r(f),a=n(327),l=r(a),h=n(321),p=r(h),d=n(326),v=r(d);e.sortTypes={1:o["default"],2:c["default"],3:l["default"],4:p["default"],5:s["default"],6:v["default"]}},321:function(t,e){"use strict";function n(t,e){return u[t]r?t[c]=u[f++]:f>i?t[c]=u[o++]:n(f,o)?t[c]=u[f++]:t[c]=u[o++];s&&s(t)}function i(t){for(var e=t.length,n=1;n0&&r(t[s],t[s-1]);s--)n(t,s,s-1);(u%2||u==t.length-1)&&e&&e(t)}),t}Object.defineProperty(e,"__esModule",{value:!0}),e["default"]=i},323:function(t,e){"use strict";function n(t,e,i,o){if(!(e>=i)){var u=r(t,e,i);o&&o(t),n(t,e,u-1,o),n(t,u+1,i,o)}}function r(t,e,n){for(var r=e,u=n+1,s=t[e];;){for(;i(s,t[++r])&&r!=n;);for(;i(t[--u],s)&&u!=e;);if(r>=u)break;o(t,r,u)}return o(t,e,u),u}function i(t,e){return t>=e}function o(t,e,n){var r=t[e];t[e]=t[n],t[n]=r}function u(t,e){n(t,0,t.length-1,e)}Object.defineProperty(e,"__esModule",{value:!0}),e["default"]=u},324:function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var i=n(199),o=r(i),u=n(145),s=n(320);o["default"].Observable.prototype.sort=function(){var t=this;return o["default"].Observable.create(function(e){t.subscribe(function(t){var n=(0,u.clone)(t[0]),r=t[1],i=s.sortTypes[r.type];i(n,function(t){e.next({nums:JSON.parse(JSON.stringify(t)),select:r})},function(t){e.error(t)})})})},e["default"]=o["default"]},325:function(t,e){"use strict";function n(t,e,n){var r=t[e];t[e]=t[n],t[n]=r}function r(t,e){var r=t.length;t.forEach(function(i,o){for(var u=o,s=o+1;st[s]&&(u=s);n(t,o,u),(o%3||o==t.length-1)&&e&&e(t)})}Object.defineProperty(e,"__esModule",{value:!0}),e["default"]=r},326:function(t,e){"use strict";function n(t,e){this.fn=e,this.container=[null].concat(t)}Object.defineProperty(e,"__esModule",{value:!0}),e["default"]=function(t,e){var r=new n(t,e);r.sort()},n.prototype.less=function(t,e){return this.container[t]=1;e--)this.sink(e,t);for(;t>1;)this.exch(1,t--),this.sink(1,t),(t%3||2==t)&&this.fn(this.container);return this.container.slice(1,this.container.length-1)}},327:function(t,e){"use strict";function n(t,e){this.source=t,this.render=e,this.tempArr=new Array(t.length).fill(0),this.init()}function r(t,e){new n(t,e)}Object.defineProperty(e,"__esModule",{value:!0}),e["default"]=r,n.prototype.init=function(){var t=this.source.length;this.sort(this.source,0,t-1)},n.prototype.less=function(t,e){return this.tempArr[t]n?t[u]=this.tempArr[o++]:o>r?t[u]=this.tempArr[i++]:this.less(o,i)?t[u]=this.tempArr[o++]:t[u]=this.tempArr[i++];this.render(t)},n.prototype.sort=function(t,e,n){if(!(e>=n)){var r=e+Math.floor((n-e)/2);this.sort(t,e,r),this.sort(t,r+1,n),this.merge(t,e,r,n)}}},574:function(t,e){}}); -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |

排序执行可视化展示

20 | 21 |

注意:排序动画过程只展示排序过程中数组中数据的变化,并不反应排序的速度,因为chart图表的渲染是异步的,每种算法渲染的次数也控制的不尽相同

22 | 23 | 24 | 25 | 34 | 35 |
36 | 37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "data_structure", 3 | "version": "1.0.0", 4 | "description": "排序算法", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "webpack-dev-server --inline --hot --watch --colors --progress --display-error-details", 8 | "build": "rm -rf docs && webpack -p --progresss" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "babel": "6.5.2", 14 | "babel-core": "6.2.1", 15 | "babel-eslint": "6.1.2", 16 | "babel-loader": "6.2.0", 17 | "babel-plugin-transform-object-rest-spread": "6.19.0", 18 | "babel-plugin-transform-runtime": "6.15.0", 19 | "babel-preset-es2015": "6.14.0", 20 | "babel-preset-stage-0": "6.5.0", 21 | "babel-runtime": "6.9.2", 22 | "cb": "0.1.0", 23 | "chromedriver": "2.21.2", 24 | "copy-webpack-plugin": "2.1.1", 25 | "css-loader": "0.23.0", 26 | "css-mqpacker": "4.0.0", 27 | "extract-text-webpack-plugin": "1.0.1", 28 | "file-loader": "0.8.4", 29 | "html-loader": "0.4.3", 30 | "html-webpack-plugin": "2.7.1", 31 | "isparta-instrumenter-loader": "1.0.0", 32 | "less": "^3.0.0-alpha.3", 33 | "less-loader": "^4.0.5", 34 | "node-libs-browser": "1.0.0", 35 | "null-loader": "0.1.1", 36 | "postcss-discard-comments": "2.0.4", 37 | "protractor": "3.1.1", 38 | "raw-loader": "0.5.1", 39 | "rimraf": "2.5.1", 40 | "style-loader": "0.13.0", 41 | "webpack": "1.12.13", 42 | "webpack-dev-server": "1.14.1" 43 | }, 44 | "dependencies": { 45 | "echarts": "^3.7.2", 46 | "rxjs": "^5.5.0" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |

排序执行可视化展示

20 | 21 |

注意:排序动画过程只展示排序过程中数组中数据的变化,并不反应排序的速度,因为chart图表的渲染是异步的,每种算法渲染的次数也控制的不尽相同

22 | 23 | 24 | 25 | 34 | 35 |
36 | 37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 2 | import echarts from "echarts" 3 | import Rx from "./js/rx-sort" 4 | import { 5 | query, 6 | numberCreator, 7 | getOption 8 | } from "./js/util" 9 | 10 | import "./index.less" 11 | 12 | const echartInstance = echarts.init(query('.chart-container')) 13 | 14 | let currentType 15 | 16 | const createNumber$ = Rx.Observable.fromEvent(query('.numberCreator'), 'click') 17 | .map(e => { 18 | return numberCreator() 19 | }) 20 | .do(nums => { 21 | const option = getOption(nums) 22 | echartInstance.setOption(option) 23 | }) 24 | 25 | const select$ = Rx.Observable.fromEvent(query('.sortTypes'), 'change') 26 | .map(e => e.target) 27 | .map(x => x.options[x.selectedIndex].value) 28 | .map(type => { 29 | return { 30 | type, 31 | timer: 1 32 | } 33 | }) 34 | .filter(x => { 35 | return x.type !== '0' 36 | }) 37 | .do(x => { 38 | currentType = x.type 39 | }) 40 | 41 | /** 42 | * 43 | * -createNumber$---- 44 | * 45 | * ---------------select$------ 46 | * combineLatest() 47 | * 48 | * ---------------------------combine$------ 49 | * sort() 50 | * -----------------------------v1 v2 v3 v4 .......v11 v22 v33------ 51 | * flatMap() 52 | * -----------------------------delay1 delay2 delay3 delay4 ....delay11 delay22 delay33------ 53 | * filter(currentType==type) 54 | * -----------------------------delay1 delay2 delay11 delay22 delay33 55 | */ 56 | 57 | Rx.Observable.combineLatest( 58 | createNumber$, 59 | select$ 60 | ) 61 | .sort() 62 | .flatMap(obj => { 63 | return Rx.Observable.of(obj).delay(100 * obj.select.timer++) 64 | }) 65 | .filter(x => { 66 | return x.select.type == currentType 67 | }) 68 | .do(x => { 69 | const option = getOption(x.nums) 70 | echartInstance.setOption(option) 71 | }) 72 | .subscribe(() => { }, null, () => { 73 | console.log('complete') 74 | }) 75 | 76 | 77 | -------------------------------------------------------------------------------- /src/index.less: -------------------------------------------------------------------------------- 1 | 2 | 3 | #app{ 4 | 5 | .title{ 6 | text-align: center 7 | } 8 | 9 | .chart-container{ 10 | min-height: 500px; 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /src/js/config.js: -------------------------------------------------------------------------------- 1 | 2 | import select_sort from "./select-sort" 3 | import quick_sort from "./quick-sort" 4 | import insert_sort from "./insert-sort" 5 | import up_down_merge_sort from "./up-down-mergesort" 6 | import down_up_merge_sort from "./down-up-mergesort" 7 | import PQ_sort from "./sort-PQ-quick" 8 | export const sortTypes = { 9 | 1: select_sort, 10 | 2: insert_sort, 11 | 3: up_down_merge_sort, 12 | 4: down_up_merge_sort, 13 | 5: quick_sort, 14 | 6: PQ_sort 15 | } -------------------------------------------------------------------------------- /src/js/down-up-mergesort.js: -------------------------------------------------------------------------------- 1 | 2 | let tempArr 3 | let render 4 | 5 | function less(j, i) { 6 | return tempArr[j] < tempArr[i] 7 | } 8 | 9 | function merge(arr, start, min, end) { 10 | var i = start 11 | var j = min + 1 12 | for (var k = 0; k <= end; k++) { 13 | tempArr[k] = arr[k] 14 | tempArr.push(arr[k]) 15 | } 16 | for (var k = start; k <= end; k++) { 17 | if (i > min) { 18 | arr[k] = tempArr[j++] 19 | } else if (j > end) { 20 | arr[k] = tempArr[i++] 21 | } else if (less(j, i)) { 22 | arr[k] = tempArr[j++] 23 | } else { 24 | arr[k] = tempArr[i++] 25 | } 26 | } 27 | render && render(arr) 28 | } 29 | 30 | 31 | function sort(arr) { 32 | var n = arr.length 33 | for (var sz = 1; sz < n; sz += sz) { 34 | for (var i = 0; i < n - sz; i += sz + sz) { 35 | merge(arr, i, i + sz - 1, Math.min(i + sz + sz - 1, n - 1)) 36 | } 37 | } 38 | 39 | } 40 | 41 | 42 | 43 | export default function down_up_merge_sort(arr, fn) { 44 | render = fn 45 | tempArr = new Array(arr.length).fill(0) 46 | sort(arr) 47 | } -------------------------------------------------------------------------------- /src/js/insert-sort.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * 左边的元素都是有序的,但最终位置还不确定 4 | * 5 | */ 6 | 7 | 8 | /** 9 | * 10 | * @param {array} arr 11 | * @param {number} x 12 | * @param {number} y 13 | */ 14 | function exchange(arr, x, y) { 15 | var t = arr[x] 16 | arr[x] = arr[y] 17 | arr[y] = t 18 | } 19 | 20 | /** 21 | * 判断两个值的大小 22 | * @param {*} x 23 | * @param {*} y 24 | */ 25 | function less(x, y) { 26 | return x < y 27 | } 28 | 29 | /** 30 | * @param {array} arr 31 | */ 32 | export default function insertsort(arr, fn) { 33 | 34 | var n = arr.length 35 | 36 | arr.forEach((x, i) => { 37 | for (var j = i + 1; j < n && j > 0 && less(arr[j], arr[j - 1]); j--) { 38 | exchange(arr, j, j - 1) 39 | } 40 | if (i % 2 || i == (arr.length - 1)) { 41 | fn && fn(arr) 42 | } 43 | }) 44 | 45 | return arr 46 | } 47 | 48 | /** 49 | * 最好的情况,顺序排列 ,比较n-1次,交换0次 50 | * 51 | * 最坏的情况 52 | * 53 | * 5 4 3 2 1 54 | * 4 5 3 2 1 55 | * 3 4 5 2 1 56 | * 57 | * i j 比较 交换 58 | * 0 1 1 1 59 | * 1 2 2 2 60 | * 2 3 3 3 61 | * . 62 | * . 63 | * . 64 | * N-2 N-1 N-1 N-1 65 | * 66 | * 对于N个值的排好序, 67 | * 比较 (1+N-1)(N-1)/2 = N(N-1)/2 ~ N^2/2 68 | * 交换 和 比较一样 69 | * 70 | */ 71 | 72 | -------------------------------------------------------------------------------- /src/js/quick-sort.js: -------------------------------------------------------------------------------- 1 | 2 | function quicksort(arr, start, end, fn) { 3 | 4 | if (start >= end) return 5 | var j = partition(arr, start, end) //确定切分 6 | 7 | fn && fn(arr) 8 | 9 | quicksort(arr, start, j - 1, fn) 10 | 11 | quicksort(arr, j + 1, end, fn) 12 | 13 | } 14 | 15 | function partition(arr, start, end) { 16 | 17 | var i = start 18 | var j = end + 1 19 | var v = arr[start] 20 | while (true) { 21 | 22 | while (less(v, arr[++i])) { 23 | if (i == end) { 24 | break; 25 | } 26 | } 27 | while (less(arr[--j], v)) { 28 | if (j == start) { 29 | break 30 | } 31 | } 32 | if (i >= j) break 33 | exchange(arr, i, j) 34 | } 35 | exchange(arr, start, j) 36 | return j 37 | } 38 | 39 | function less(x, y) { 40 | return x >= y 41 | } 42 | 43 | function exchange(arr, i, j) { 44 | var t = arr[i] 45 | arr[i] = arr[j] 46 | arr[j] = t 47 | } 48 | 49 | 50 | export default function quick_sort(arr, fn) { 51 | quicksort(arr, 0, arr.length - 1, fn) 52 | } -------------------------------------------------------------------------------- /src/js/rx-sort.js: -------------------------------------------------------------------------------- 1 | 2 | import Rx from "rxjs" 3 | import { 4 | clone 5 | } from "./util" 6 | import { 7 | sortTypes 8 | } from "./config" 9 | 10 | Rx.Observable.prototype.sort = function () { 11 | const input = this 12 | return Rx.Observable.create((observer) => { 13 | input.subscribe((arr) => { 14 | const nums = clone(arr[0]) 15 | const select = arr[1] 16 | const sortMethod = sortTypes[select.type] 17 | sortMethod(nums, function (arr) { 18 | observer.next({ 19 | nums: JSON.parse(JSON.stringify(arr)), 20 | select 21 | }) 22 | }, error => { 23 | observer.error(error) 24 | }) 25 | }, ) 26 | 27 | }) 28 | } 29 | 30 | export default Rx -------------------------------------------------------------------------------- /src/js/select-sort.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * 5 | * @param {array} arr 6 | * @param {number} x 7 | * @param {number} y 8 | */ 9 | function exchange(arr, x, y) { 10 | var t = arr[x] 11 | arr[x] = arr[y] 12 | arr[y] = t 13 | } 14 | 15 | /** 16 | * 17 | * @param {array} arr 18 | */ 19 | export default function selectsort(arr, fn) { 20 | 21 | var n = arr.length 22 | 23 | arr.forEach(function (x, i) { 24 | var min = i 25 | for (var j = i + 1; j < n; j++) { 26 | if (arr[min] > arr[j]) { 27 | min = j 28 | } 29 | } 30 | exchange(arr, i, min) 31 | if (i % 3 || i == (arr.length - 1)) { 32 | fn && fn(arr) 33 | } 34 | }) 35 | } 36 | 37 | 38 | 39 | /**交换 比较 40 | * i 内循环 41 | * 0 N-1 42 | * 1 N-2 43 | * . 44 | * . 45 | * . 46 | * N-2 1 47 | * N-1 无 48 | * 49 | * N (N-1)(1+N-1)/2 = N(N-1)/2 ~ n^2/2 50 | */ 51 | 52 | -------------------------------------------------------------------------------- /src/js/sort-PQ-quick.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | function Sort(arr, fn) { 6 | this.fn = fn 7 | this.container = [null].concat(arr) 8 | } 9 | 10 | Sort.prototype.less = function (i, j) { 11 | return this.container[i] < this.container[j] 12 | } 13 | 14 | Sort.prototype.exch = function (i, j) { 15 | var t = this.container[i] 16 | this.container[i] = this.container[j] 17 | this.container[j] = t 18 | } 19 | 20 | //下沉 21 | Sort.prototype.sink = function (k, N) { 22 | while (2 * k <= N) { 23 | var j = 2 * k 24 | if (j < N && this.less(j, j + 1)) { 25 | j++ 26 | } 27 | if (!this.less(k, j)) break; 28 | this.exch(k, j) 29 | k = j 30 | } 31 | } 32 | 33 | Sort.prototype.sort = function () { 34 | var n = this.container.length - 1 35 | for (var i = Math.floor(n / 2); i >= 1; i--) { 36 | this.sink(i, n) 37 | } 38 | //已经是堆有序 39 | while (n > 1) { 40 | this.exch(1, n--) 41 | this.sink(1, n) 42 | if (n % 3 || n == 2) { 43 | this.fn(this.container) 44 | } 45 | } 46 | return this.container.slice(1, this.container.length - 1) 47 | } 48 | 49 | 50 | export default function (arr, fn) { 51 | const s = new Sort(arr, fn) 52 | s.sort() 53 | } 54 | -------------------------------------------------------------------------------- /src/js/up-down-mergesort.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | function MergeSort(arr, render) { 4 | this.source = arr 5 | this.render = render 6 | this.tempArr = new Array(arr.length).fill(0) 7 | this.init() 8 | } 9 | 10 | MergeSort.prototype.init = function () { 11 | var len = this.source.length 12 | this.sort(this.source, 0, len - 1) 13 | } 14 | 15 | /** 16 | * 判断两个值的大小 17 | * @param {number} j 18 | * @param {number} i 19 | */ 20 | MergeSort.prototype.less = function (j, i) { 21 | return this.tempArr[j] < this.tempArr[i] 22 | } 23 | 24 | /** 25 | * 将两个有序数组合并成一个 26 | * @param {array} arr 27 | * @param {number} start 28 | * @param {number} min 29 | * @param {number} end 30 | */ 31 | MergeSort.prototype.merge = function (arr, start, min, end) { 32 | var i = start 33 | var j = min + 1 34 | for (var k = 0; k <= end; k++) { 35 | this.tempArr[k] = arr[k] 36 | this.tempArr.push(arr[k]) 37 | } 38 | for (var k = start; k <= end; k++) { 39 | if (i > min) { 40 | arr[k] = this.tempArr[j++] 41 | } else if (j > end) { 42 | arr[k] = this.tempArr[i++] 43 | } else if (this.less(j, i)) { 44 | arr[k] = this.tempArr[j++] 45 | } else { 46 | arr[k] = this.tempArr[i++] 47 | } 48 | } 49 | this.render(arr) 50 | } 51 | /** 52 | * 自顶向下的归并排序 53 | */ 54 | MergeSort.prototype.sort = function (arr, start, end) { 55 | if (start >= end) return 56 | var min = start + Math.floor((end - start) / 2) 57 | this.sort(arr, start, min) 58 | this.sort(arr, min + 1, end) 59 | this.merge(arr, start, min, end) 60 | } 61 | 62 | 63 | 64 | 65 | export default function up_down_merge_sort(arr, fn) { 66 | new MergeSort(arr, fn) 67 | } 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /src/js/util.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | export function numberCreator(size = 300) { 4 | const container = new Array(size).fill(0) 5 | return container.map(x => { 6 | return Math.ceil(Math.random() * size) 7 | }) 8 | } 9 | 10 | export function query(selector) { 11 | return document.querySelector(selector) 12 | } 13 | 14 | export function getOption(data) { 15 | return { 16 | color: ['#3398DB'], 17 | xAxis: [ 18 | { 19 | type: 'category', 20 | data: [], 21 | axisTick: { 22 | alignWithLabel: true 23 | } 24 | } 25 | ], 26 | yAxis: [ 27 | { 28 | type: 'value' 29 | } 30 | ], 31 | series: [ 32 | { 33 | type: 'bar', 34 | data 35 | } 36 | ] 37 | }; 38 | } 39 | 40 | //浅复制 41 | export function clone(arr) { 42 | return new Array(arr.length).fill(0).map((x, index) => arr[index]) 43 | } -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | 2 | var webpack = require('webpack'); 3 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 5 | 6 | var isPro = process.env.npm_lifecycle_event == 'build' 7 | 8 | var config = { 9 | 10 | entry: { 11 | app: './src/index', 12 | vendors:['echarts','rxjs'] 13 | }, 14 | output: { 15 | path: __dirname + '/docs', 16 | filename: '[name].[hash].js', 17 | //publicPath: isPro ? '/react-demo/' : '' 18 | }, 19 | resolve: { 20 | modulesDirectories: ['node_modules', './'], 21 | alias: { 22 | 'npm': __dirname + '/node_modules' 23 | 24 | }, 25 | extensions: ['', '.js', '.html', '.css', '.jsx'] 26 | }, 27 | devtool: isPro ? '/rxjs-sort-visualization' : 'eval-source-map', 28 | module: { 29 | loaders: [ 30 | { 31 | test: /\.js$/, 32 | loaders: ['babel'], 33 | exclude: /node_modules/ 34 | }, 35 | { 36 | test: /\.less$/, 37 | loader: ExtractTextPlugin.extract( 38 | 'style-loader', 39 | 'css-loader?sourceMap!less?sourceMap' 40 | ) 41 | 42 | }, { 43 | test: /\.css/, 44 | loader: ExtractTextPlugin.extract( 45 | 'style-loader', 46 | 'css-loader?sourceMap' 47 | ) 48 | }, { 49 | test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$/, 50 | loader: 'file' 51 | } 52 | ], 53 | }, 54 | plugins: [ 55 | new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js'), 56 | new ExtractTextPlugin('[name].[hash].css'), 57 | new HtmlWebpackPlugin({ 58 | template: 'src/index.html', 59 | inject: true 60 | }), 61 | ], 62 | devServer: { 63 | historyApiFallback:true, 64 | port: 7777, 65 | } 66 | } 67 | 68 | if (isPro) { 69 | config.plugins.unshift(new webpack.optimize.UglifyJsPlugin({ 70 | compress: { 71 | warnings: false, 72 | drop_debugger: true, 73 | drop_console: true 74 | } 75 | })) 76 | } 77 | 78 | 79 | module.exports = config 80 | --------------------------------------------------------------------------------