├── CHANGELOG.md
├── demos
├── assets
│ ├── codemirror-5.27.4
│ │ ├── .travis.yml
│ │ ├── .gitattributes
│ │ ├── .npmignore
│ │ ├── addon
│ │ │ ├── fold
│ │ │ │ ├── foldgutter.css
│ │ │ │ ├── comment-fold.js
│ │ │ │ ├── brace-fold.js
│ │ │ │ ├── foldgutter.js
│ │ │ │ ├── foldcode.js
│ │ │ │ └── xml-fold.js
│ │ │ └── hint
│ │ │ │ ├── show-hint.css
│ │ │ │ ├── anyword-hint.js
│ │ │ │ ├── css-hint.js
│ │ │ │ ├── xml-hint.js
│ │ │ │ ├── javascript-hint.js
│ │ │ │ └── html-hint.js
│ │ ├── mode
│ │ │ ├── htmlmixed
│ │ │ │ └── htmlmixed.js
│ │ │ └── xml
│ │ │ │ └── xml.js
│ │ └── lib
│ │ │ └── codemirror.css
│ ├── common.css
│ ├── lazyload-2.0.0-beta.2.min.js
│ ├── index.css
│ ├── routie-0.3.2.min.js
│ ├── index.js
│ ├── codemirror-5.29.0
│ │ └── codemirror-merged.min.css
│ ├── jquery.resizable-0.20.0.js
│ ├── popper.js-1.12.5
│ │ └── popper-utils.min.js
│ └── clipboard-1.7.1.min.js
├── interval.html
├── filter-shape.html
├── line.html
├── index.njk
├── ds-state.html
├── polygon.html
├── app.js
├── data
│ ├── sp500.json
│ └── iris.json
└── highlight.html
├── .eslintignore
├── index.js
├── bin
├── mkdir-dist.js
├── win-dev.js
├── gh-pages.js
└── screenshot.js
├── webpack-dev.config.js
├── .torch.compile.opts.js
├── .travis.yml
├── .editorconfig
├── .eslintrc
├── test
└── unit
│ └── index-spec.js
├── webpack.config.js
├── LICENSE
├── .gitignore
├── .npmignore
├── src
├── util.js
└── brush.js
├── package.json
├── README.md
├── docs
└── brush.md
├── CONTRIBUTING.zh-CN.md
└── CONTRIBUTING.md
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/demos/assets/codemirror-5.27.4/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - stable
4 | sudo: false
5 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | build/
2 | coverage/
3 | dist/
4 | mocks/
5 | node_modules/
6 | demos/assets/
7 | demos/index.html
8 |
--------------------------------------------------------------------------------
/demos/assets/common.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | overflow: hidden;
3 | }
4 | ::-webkit-scrollbar {
5 | display: none;
6 | }
7 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * g2-brush
3 | * @author sima.zhang1990@gmail.com
4 | */
5 | const Brush = require('./src/brush');
6 | module.exports = Brush;
7 |
--------------------------------------------------------------------------------
/demos/assets/codemirror-5.27.4/.gitattributes:
--------------------------------------------------------------------------------
1 | *.txt text
2 | *.js text
3 | *.html text
4 | *.md text
5 | *.json text
6 | *.yml text
7 | *.css text
8 | *.svg text
9 |
--------------------------------------------------------------------------------
/demos/assets/codemirror-5.27.4/.npmignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /demo
3 | /doc
4 | /test
5 | /test*.html
6 | /index.html
7 | /mode/*/*test.js
8 | /mode/*/*.html
9 | /mode/index.html
10 | .*
11 | bin
12 |
--------------------------------------------------------------------------------
/bin/mkdir-dist.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | const path = require('path');
3 | const shelljs = require('shelljs');
4 |
5 | const pathname = path.join(process.cwd(), './dist');
6 | shelljs.rm('-rf', pathname);
7 | shelljs.mkdir('-p', pathname);
8 |
9 |
--------------------------------------------------------------------------------
/webpack-dev.config.js:
--------------------------------------------------------------------------------
1 | const webpackConfig = require('./webpack.config');
2 | const _ = require('lodash');
3 |
4 | module.exports = _.merge({
5 | devtool: 'cheap-source-map',
6 | watch: true,
7 | watchOptions: {
8 | aggregateTimeout: 300,
9 | poll: 1000
10 | }
11 | }, webpackConfig);
12 |
--------------------------------------------------------------------------------
/.torch.compile.opts.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | babelrc: {
3 | presets: [
4 | 'es2015',
5 | 'stage-0'
6 | ],
7 | sourceMaps: 'inline'
8 | },
9 | extensions: ['.js'],
10 | include: [
11 | 'node_modules/**/src/gl-matrix/**/*.js '
12 | ],
13 | exclude: [
14 | 'bower_components/**/*.js',
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/bin/win-dev.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | const shelljs = require('shelljs');
3 | const exec = shelljs.exec;
4 |
5 | const childWatch = exec('npm run watch', {
6 | async: true
7 | });
8 | childWatch.stdout.on('data', data => {
9 | if (data.indexOf('Hash') === 0) {
10 | exec('npm run demos-web', {
11 | async: true
12 | });
13 | }
14 | });
15 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js:
4 | - "8"
5 |
6 | env:
7 | matrix:
8 | - TEST_TYPE=ci
9 |
10 | addons:
11 | apt:
12 | packages:
13 | - xvfb
14 |
15 | install:
16 | - export DISPLAY=':99.0'
17 | - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
18 | - npm install
19 |
20 | script:
21 | - |
22 | if [ "$TEST_TYPE" = ci ]; then
23 | npm run ci
24 | fi
25 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | # Unix-style newlines with a newline ending every file
7 | [*]
8 | end_of_line = lf
9 | charset = utf-8
10 | insert_final_newline = true
11 | trim_trailing_whitespace = true
12 | indent_style = space
13 | indent_size = 2
14 |
15 | [Makefile]
16 | indent_style = tab
17 | indent_size = 1
18 |
19 | [*.md]
20 | trim_trailing_whitespace = false
--------------------------------------------------------------------------------
/demos/assets/codemirror-5.27.4/addon/fold/foldgutter.css:
--------------------------------------------------------------------------------
1 | .CodeMirror-foldmarker {
2 | color: blue;
3 | text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px;
4 | font-family: arial;
5 | line-height: .3;
6 | cursor: pointer;
7 | }
8 | .CodeMirror-foldgutter {
9 | width: .7em;
10 | }
11 | .CodeMirror-foldgutter-open,
12 | .CodeMirror-foldgutter-folded {
13 | cursor: pointer;
14 | }
15 | .CodeMirror-foldgutter-open:after {
16 | content: "\25BE";
17 | }
18 | .CodeMirror-foldgutter-folded:after {
19 | content: "\25B8";
20 | }
21 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "egg"
4 | ],
5 | "globals": {
6 | "$": true,
7 | "DataSet": true,
8 | "G2": true,
9 | "Brush": true,
10 | "_": true
11 | },
12 | "parser": "babel-eslint",
13 | "parserOptions": {
14 | "sourceType": "module"
15 | },
16 | "plugins": [
17 | "html"
18 | ],
19 | "rules": {
20 | "no-bitwise": [
21 | 0
22 | ],
23 | "experimentalDecorators": [
24 | 0
25 | ],
26 | "comma-dangle": [
27 | "error",
28 | "never"
29 | ],
30 | "linebreak-style": [
31 | 0
32 | ]
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/test/unit/index-spec.js:
--------------------------------------------------------------------------------
1 | const expect = require('chai').expect;
2 | const isRenderer = require('is-electron-renderer');
3 | const brush = require('../../build/g2-brush');
4 |
5 | describe('sample', () => {
6 | it('test', () => {
7 | expect('test').to.be.a('string');
8 | expect(brush).to.be.an('function');
9 | });
10 | });
11 |
12 | after(() => {
13 | if (isRenderer && window.__coverage__) {
14 | const { remote } = require('electron');
15 | const fs = remote.require('fs');
16 | const path = remote.require('path');
17 | fs.writeFileSync(path.resolve(process.cwd(), './test/coverage/coverage.json'), JSON.stringify(window.__coverage__));
18 | }
19 | });
20 |
--------------------------------------------------------------------------------
/demos/assets/codemirror-5.27.4/addon/hint/show-hint.css:
--------------------------------------------------------------------------------
1 | .CodeMirror-hints {
2 | position: absolute;
3 | z-index: 10;
4 | overflow: hidden;
5 | list-style: none;
6 |
7 | margin: 0;
8 | padding: 2px;
9 |
10 | -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
11 | -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
12 | box-shadow: 2px 3px 5px rgba(0,0,0,.2);
13 | border-radius: 3px;
14 | border: 1px solid silver;
15 |
16 | background: white;
17 | font-size: 90%;
18 | font-family: monospace;
19 |
20 | max-height: 20em;
21 | overflow-y: auto;
22 | }
23 |
24 | .CodeMirror-hint {
25 | margin: 0;
26 | padding: 0 4px;
27 | border-radius: 2px;
28 | white-space: pre;
29 | color: black;
30 | cursor: pointer;
31 | }
32 |
33 | li.CodeMirror-hint-active {
34 | background: #08f;
35 | color: white;
36 | }
37 |
--------------------------------------------------------------------------------
/bin/gh-pages.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | process.env.DEBUG = 'app:*';
3 | const debug = require('debug')('app:pages');
4 | const fs = require('fs');
5 | const ghpages = require('gh-pages');
6 | const path = require('path');
7 | const shelljs = require('shelljs');
8 |
9 | const pathnames = [
10 | './build',
11 | './README.md',
12 | './dist',
13 | './demos'
14 | ];
15 |
16 | const tempDir = path.join(process.cwd(), './_home');
17 | shelljs.rm('-rf', tempDir);
18 | shelljs.mkdir('-p', tempDir);
19 | fs.writeFileSync(path.join(tempDir, '.gitignore'), ' ', 'utf8');
20 | pathnames.forEach(pathname => {
21 | shelljs.cp('-r', path.join(process.cwd(), pathname), tempDir);
22 | });
23 |
24 | ghpages.publish(tempDir, {
25 | add: true,
26 | dotfiles: true
27 | }, err => {
28 | debug(err);
29 | shelljs.rm('-rf', tempDir);
30 | });
31 |
32 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const resolve = require('path').resolve;
3 |
4 | module.exports = {
5 | entry: {
6 | 'g2-brush': './index.js'
7 | },
8 | output: {
9 | filename: '[name].js',
10 | library: 'Brush',
11 | libraryTarget: 'umd',
12 | path: resolve(__dirname, 'build/')
13 | },
14 | module: {
15 | rules: [
16 | {
17 | test: /\.js$/,
18 | // exclude: /(node_modules|bower_components)/,
19 | use: {
20 | loader: 'babel-loader',
21 | options: {
22 | babelrc: false,
23 | plugins: [
24 | 'transform-remove-strict-mode'
25 | ],
26 | presets: [
27 | [
28 | 'es2015', {
29 | loose: true
30 | // modules: false
31 | }
32 | ],
33 | 'stage-0'
34 | ]
35 | }
36 | }
37 | }
38 | ]
39 | },
40 | plugins: [
41 | new webpack.NoEmitOnErrorsPlugin(),
42 | new webpack.optimize.AggressiveMergingPlugin()
43 | ]
44 | };
45 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Alipay.inc
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 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # lock
9 | package-lock.json
10 |
11 | # Runtime data
12 | pids
13 | *.pid
14 | *.seed
15 | *.pid.lock
16 |
17 | # Directory for instrumented libs generated by jscoverage/JSCover
18 | lib-cov
19 |
20 | # Coverage directory used by tools like istanbul
21 | coverage
22 |
23 | # nyc test coverage
24 | .nyc_output
25 |
26 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
27 | .grunt
28 |
29 | # Bower dependency directory (https://bower.io/)
30 | bower_components
31 |
32 | # node-waf configuration
33 | .lock-wscript
34 |
35 | # Compiled binary addons (http://nodejs.org/api/addons.html)
36 | build/Release
37 |
38 | # Dependency directories
39 | node_modules/
40 | jspm_packages/
41 |
42 | # Typescript v1 declaration files
43 | typings/
44 |
45 | # Optional npm cache directory
46 | .npm
47 |
48 | # Optional eslint cache
49 | .eslintcache
50 |
51 | # Optional REPL history
52 | .node_repl_history
53 |
54 | # Output of 'npm pack'
55 | *.tgz
56 |
57 | # Yarn Integrity file
58 | .yarn-integrity
59 |
60 | # dotenv environment variables file
61 | .env
62 |
63 | build
64 | dist
65 | temp
66 | .DS_Store
67 | .idea
68 | demos/assets/screenshots
69 | demos/index.html
70 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # lock
9 | package-lock.json
10 |
11 | # Runtime data
12 | pids
13 | *.pid
14 | *.seed
15 | *.pid.lock
16 |
17 | # Directory for instrumented libs generated by jscoverage/JSCover
18 | lib-cov
19 |
20 | # Coverage directory used by tools like istanbul
21 | coverage
22 |
23 | # nyc test coverage
24 | .nyc_output
25 |
26 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
27 | .grunt
28 |
29 | # Bower dependency directory (https://bower.io/)
30 | bower_components
31 |
32 | # node-waf configuration
33 | .lock-wscript
34 |
35 | # Compiled binary addons (http://nodejs.org/api/addons.html)
36 | build/Release
37 |
38 | # Dependency directories
39 | node_modules/
40 | jspm_packages/
41 |
42 | # Typescript v1 declaration files
43 | typings/
44 |
45 | # Optional npm cache directory
46 | .npm
47 |
48 | # Optional eslint cache
49 | .eslintcache
50 |
51 | # Optional REPL history
52 | .node_repl_history
53 |
54 | # Output of 'npm pack'
55 | *.tgz
56 |
57 | # Yarn Integrity file
58 | .yarn-integrity
59 |
60 | # dotenv environment variables file
61 | .env
62 |
63 | .DS_Store
64 |
65 | # npmignore - content above this line is automatically generated and modifications may be omitted
66 | # see npmjs.com/npmignore for more details.
67 | test
68 |
--------------------------------------------------------------------------------
/demos/assets/codemirror-5.27.4/addon/hint/anyword-hint.js:
--------------------------------------------------------------------------------
1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 | // Distributed under an MIT license: http://codemirror.net/LICENSE
3 |
4 | (function(mod) {
5 | if (typeof exports == "object" && typeof module == "object") // CommonJS
6 | mod(require("../../lib/codemirror"));
7 | else if (typeof define == "function" && define.amd) // AMD
8 | define(["../../lib/codemirror"], mod);
9 | else // Plain browser env
10 | mod(CodeMirror);
11 | })(function(CodeMirror) {
12 | "use strict";
13 |
14 | var WORD = /[\w$]+/, RANGE = 500;
15 |
16 | CodeMirror.registerHelper("hint", "anyword", function(editor, options) {
17 | var word = options && options.word || WORD;
18 | var range = options && options.range || RANGE;
19 | var cur = editor.getCursor(), curLine = editor.getLine(cur.line);
20 | var end = cur.ch, start = end;
21 | while (start && word.test(curLine.charAt(start - 1))) --start;
22 | var curWord = start != end && curLine.slice(start, end);
23 |
24 | var list = options && options.list || [], seen = {};
25 | var re = new RegExp(word.source, "g");
26 | for (var dir = -1; dir <= 1; dir += 2) {
27 | var line = cur.line, endLine = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir;
28 | for (; line != endLine; line += dir) {
29 | var text = editor.getLine(line), m;
30 | while (m = re.exec(text)) {
31 | if (line == cur.line && m[0] === curWord) continue;
32 | if ((!curWord || m[0].lastIndexOf(curWord, 0) == 0) && !Object.prototype.hasOwnProperty.call(seen, m[0])) {
33 | seen[m[0]] = true;
34 | list.push(m[0]);
35 | }
36 | }
37 | }
38 | }
39 | return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)};
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/demos/interval.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Interval Chart(X)
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/src/util.js:
--------------------------------------------------------------------------------
1 | function _mix(dist, obj) {
2 | for (const k in obj) {
3 | if (obj.hasOwnProperty(k) && k !== 'constructor' && obj[k] !== undefined) {
4 | dist[k] = obj[k];
5 | }
6 | }
7 | }
8 |
9 | const Util = {
10 | mix(dist, obj1, obj2, obj3) {
11 | if (obj1) {
12 | _mix(dist, obj1);
13 | }
14 |
15 | if (obj2) {
16 | _mix(dist, obj2);
17 | }
18 |
19 | if (obj3) {
20 | _mix(dist, obj3);
21 | }
22 | return dist;
23 | },
24 | /**
25 | * 添加事件监听器
26 | * @param {Object} target DOM对象
27 | * @param {String} eventType 事件名
28 | * @param {Funtion} callback 回调函数
29 | * @return {Object} 返回对象
30 | */
31 | addEventListener(target, eventType, callback) {
32 | if (target.addEventListener) {
33 | target.addEventListener(eventType, callback, false);
34 | return {
35 | remove() {
36 | target.removeEventListener(eventType, callback, false);
37 | }
38 | };
39 | } else if (target.attachEvent) {
40 | target.attachEvent('on' + eventType, callback);
41 | return {
42 | remove() {
43 | target.detachEvent('on' + eventType, callback);
44 | }
45 | };
46 | }
47 | },
48 | /**
49 | * 封装事件,便于使用上下文this,和便于解除事件时使用
50 | * @protected
51 | * @param {Object} obj 对象
52 | * @param {String} action 事件名称
53 | * @return {Function} 返回事件处理函数
54 | */
55 | wrapBehavior(obj, action) {
56 | if (obj['_wrap_' + action]) {
57 | return obj['_wrap_' + action];
58 | }
59 | const method = e => {
60 | obj[action](e);
61 | };
62 | obj['_wrap_' + action] = method;
63 | return method;
64 | },
65 | /**
66 | * 获取封装的事件
67 | * @protected
68 | * @param {Object} obj 对象
69 | * @param {String} action 事件名称
70 | * @return {Function} 返回事件处理函数
71 | */
72 | getWrapBehavior(obj, action) {
73 | return obj['_wrap_' + action];
74 | }
75 | };
76 |
77 | module.exports = Util;
78 |
--------------------------------------------------------------------------------
/demos/assets/lazyload-2.0.0-beta.2.min.js:
--------------------------------------------------------------------------------
1 | /*! Lazy Load 2.0.0-beta.2 - MIT license - Copyright 2007-2017 Mika Tuupola */
2 | !function(t,e){"function"==typeof define&&define.amd?define([],e(t)):"object"==typeof exports?module.exports=e(t):t.LazyLoad=e(t)}("undefined"!=typeof global?global:this.window||this.global,function(t){"use strict";function e(t,e){this.settings=r(s,e||{}),this.images=t||document.querySelectorAll(this.settings.selector),this.observer=null,this.init()}const s={src:"data-src",srcset:"data-srcset",selector:".lazyload"},r=function(){let t={},e=!1,s=0,o=arguments.length;"[object Boolean]"===Object.prototype.toString.call(arguments[0])&&(e=arguments[0],s++);for(;s0){e.observer.unobserve(t.target);let s=t.target.getAttribute(e.settings.src),r=t.target.getAttribute(e.settings.srcset);"img"===t.target.tagName.toLowerCase()?(s&&(t.target.src=s),r&&(t.target.srcset=r)):t.target.style.backgroundImage="url("+s+")"}})},s),this.images.forEach(function(t){e.observer.observe(t)})},loadAndDestroy:function(){this.settings&&(this.loadImages(),this.destroy())},loadImages:function(){if(!this.settings)return;let t=this;this.images.forEach(function(e){let s=e.getAttribute(t.settings.src),r=e.getAttribute(t.settings.srcset);"img"===e.tagName.toLowerCase()?(s&&(e.src=s),r&&(e.srcset=r)):e.style.backgroundImage="url("+s+")"})},destroy:function(){this.settings&&(this.observer.disconnect(),this.settings=null)}},t.lazyload=function(t,s){return new e(t,s)},window.jQuery){const t=window.jQuery;t.fn.lazyload=function(s){return s=s||{},s.attribute=s.attribute||"data-src",new e(t.makeArray(this),s),this}}return e});
3 |
--------------------------------------------------------------------------------
/demos/assets/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | /*overflow: hidden;*/
3 | }
4 | ::-webkit-scrollbar {
5 | display: none;
6 | }
7 |
8 | .filter {
9 | padding: 15px;
10 | }
11 | .demo-thumbnails {
12 | padding: 15px;
13 | }
14 | .demo-thumbnail {
15 | margin-bottom: 30px;
16 | }
17 | .thumbnail-container {
18 | overflow: hidden;
19 | max-height: 202px;
20 | }
21 | .thumbnail-container img {
22 | width: 100%;
23 | }
24 | .card-body {
25 | padding: 8px;
26 | }
27 | iframe {
28 | border: none;
29 | }
30 | .scaled-frame {
31 | margin: 0 auto;
32 | width: 800px;
33 | height: 450px;
34 | -webkit-transform: scale(0.45);
35 | -webkit-transform-origin: 0 0;
36 | }
37 | #doc-container {
38 | display: -webkit-box;
39 | display: -webkit-flex;
40 | display: -ms-flexbox;
41 | display: flex;
42 | -webkit-box-flex: 1;
43 | -webkit-flex: 1 1 auto;
44 | -ms-flex: 1 1 auto;
45 | flex: 1 1 auto;
46 | position: fixed;
47 | top: 0;
48 | left: 0;
49 | height: 100%;
50 | width: 100%;
51 | background: white;
52 | }
53 | .code-panel {
54 | -webkit-overflow-scrolling: touch;
55 | -webkit-transform: translateZ(0);
56 | background-color: #fff;
57 | display: block;
58 | width: 400px;
59 | height: 100%;
60 | overflow: hidden;
61 | padding: 0 1rem 0 0;
62 | position: relative;
63 | right: 0;
64 | top: 0;
65 | border-right: 0.1rem solid #e8e8e8;
66 | transform: translateZ(0);
67 | white-space: nowrap;
68 | will-change: scroll-position;
69 | z-index: 1;
70 | }
71 |
72 | .code-banner {
73 | padding: .5rem 0;
74 | }
75 |
76 | .code-panel, .code-editor .CodeMirror {
77 | height: 100%;
78 | }
79 |
80 | .code-editor {
81 | height: calc(100% - 3.375rem);
82 | }
83 |
84 |
85 | #chart-panel {
86 | flex: 1;
87 | overflow: hidden;
88 | padding: 1rem;
89 | -webkit-transform: translateZ(0);
90 | transform: translateZ(0);
91 | will-change: scroll-position;
92 | -webkit-overflow-scrolling: touch;
93 | }
94 | #resize-handler {
95 | //background: #DEDEEB;
96 | border-right: 2px solid #DEDEEB;
97 | cursor: col-resize;
98 | }
99 | .chart-frame {
100 | height: 100%;
101 | width: 100%;
102 | }
103 |
104 | .btn {
105 | cursor: pointer;
106 | }
107 |
--------------------------------------------------------------------------------
/demos/filter-shape.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Filter Shape
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
81 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/demos/assets/codemirror-5.27.4/addon/fold/comment-fold.js:
--------------------------------------------------------------------------------
1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 | // Distributed under an MIT license: http://codemirror.net/LICENSE
3 |
4 | (function(mod) {
5 | if (typeof exports == "object" && typeof module == "object") // CommonJS
6 | mod(require("../../lib/codemirror"));
7 | else if (typeof define == "function" && define.amd) // AMD
8 | define(["../../lib/codemirror"], mod);
9 | else // Plain browser env
10 | mod(CodeMirror);
11 | })(function(CodeMirror) {
12 | "use strict";
13 |
14 | CodeMirror.registerGlobalHelper("fold", "comment", function(mode) {
15 | return mode.blockCommentStart && mode.blockCommentEnd;
16 | }, function(cm, start) {
17 | var mode = cm.getModeAt(start), startToken = mode.blockCommentStart, endToken = mode.blockCommentEnd;
18 | if (!startToken || !endToken) return;
19 | var line = start.line, lineText = cm.getLine(line);
20 |
21 | var startCh;
22 | for (var at = start.ch, pass = 0;;) {
23 | var found = at <= 0 ? -1 : lineText.lastIndexOf(startToken, at - 1);
24 | if (found == -1) {
25 | if (pass == 1) return;
26 | pass = 1;
27 | at = lineText.length;
28 | continue;
29 | }
30 | if (pass == 1 && found < start.ch) return;
31 | if (/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1))) &&
32 | (found == 0 || lineText.slice(found - endToken.length, found) == endToken ||
33 | !/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found))))) {
34 | startCh = found + startToken.length;
35 | break;
36 | }
37 | at = found - 1;
38 | }
39 |
40 | var depth = 1, lastLine = cm.lastLine(), end, endCh;
41 | outer: for (var i = line; i <= lastLine; ++i) {
42 | var text = cm.getLine(i), pos = i == line ? startCh : 0;
43 | for (;;) {
44 | var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos);
45 | if (nextOpen < 0) nextOpen = text.length;
46 | if (nextClose < 0) nextClose = text.length;
47 | pos = Math.min(nextOpen, nextClose);
48 | if (pos == text.length) break;
49 | if (pos == nextOpen) ++depth;
50 | else if (!--depth) { end = i; endCh = pos; break outer; }
51 | ++pos;
52 | }
53 | }
54 | if (end == null || line == end && endCh == startCh) return;
55 | return {from: CodeMirror.Pos(line, startCh),
56 | to: CodeMirror.Pos(end, endCh)};
57 | });
58 |
59 | });
60 |
--------------------------------------------------------------------------------
/demos/assets/codemirror-5.27.4/addon/hint/css-hint.js:
--------------------------------------------------------------------------------
1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 | // Distributed under an MIT license: http://codemirror.net/LICENSE
3 |
4 | (function(mod) {
5 | if (typeof exports == "object" && typeof module == "object") // CommonJS
6 | mod(require("../../lib/codemirror"), require("../../mode/css/css"));
7 | else if (typeof define == "function" && define.amd) // AMD
8 | define(["../../lib/codemirror", "../../mode/css/css"], mod);
9 | else // Plain browser env
10 | mod(CodeMirror);
11 | })(function(CodeMirror) {
12 | "use strict";
13 |
14 | var pseudoClasses = {link: 1, visited: 1, active: 1, hover: 1, focus: 1,
15 | "first-letter": 1, "first-line": 1, "first-child": 1,
16 | before: 1, after: 1, lang: 1};
17 |
18 | CodeMirror.registerHelper("hint", "css", function(cm) {
19 | var cur = cm.getCursor(), token = cm.getTokenAt(cur);
20 | var inner = CodeMirror.innerMode(cm.getMode(), token.state);
21 | if (inner.mode.name != "css") return;
22 |
23 | if (token.type == "keyword" && "!important".indexOf(token.string) == 0)
24 | return {list: ["!important"], from: CodeMirror.Pos(cur.line, token.start),
25 | to: CodeMirror.Pos(cur.line, token.end)};
26 |
27 | var start = token.start, end = cur.ch, word = token.string.slice(0, end - start);
28 | if (/[^\w$_-]/.test(word)) {
29 | word = ""; start = end = cur.ch;
30 | }
31 |
32 | var spec = CodeMirror.resolveMode("text/css");
33 |
34 | var result = [];
35 | function add(keywords) {
36 | for (var name in keywords)
37 | if (!word || name.lastIndexOf(word, 0) == 0)
38 | result.push(name);
39 | }
40 |
41 | var st = inner.state.state;
42 | if (st == "pseudo" || token.type == "variable-3") {
43 | add(pseudoClasses);
44 | } else if (st == "block" || st == "maybeprop") {
45 | add(spec.propertyKeywords);
46 | } else if (st == "prop" || st == "parens" || st == "at" || st == "params") {
47 | add(spec.valueKeywords);
48 | add(spec.colorKeywords);
49 | } else if (st == "media" || st == "media_parens") {
50 | add(spec.mediaTypes);
51 | add(spec.mediaFeatures);
52 | }
53 |
54 | if (result.length) return {
55 | list: result,
56 | from: CodeMirror.Pos(cur.line, start),
57 | to: CodeMirror.Pos(cur.line, end)
58 | };
59 | });
60 | });
61 |
--------------------------------------------------------------------------------
/demos/line.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Line Chart(XY)
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/demos/index.njk:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Demos
12 |
13 |
14 |
15 | {% for file in demoFiles %}
16 |
17 | {% endfor %}
18 |
19 |
20 |
21 |
22 |
23 |
24 | {% for file in demoFiles %}
25 |
26 |
27 |
28 |
29 |
30 |
31 |
{{ file.basename }}
32 |
33 |
34 |
35 | {% endfor %}
36 |
37 |
38 |
39 |
40 |
back
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/demos/assets/routie-0.3.2.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * routie - a tiny hash router
3 | * v0.3.2
4 | * http://projects.jga.me/routie
5 | * copyright Greg Allen 2016
6 | * MIT License
7 | */
8 | var Routie=function(a,b){var c=[],d={},e="routie",f=a[e],g=function(a,b){this.name=b,this.path=a,this.keys=[],this.fns=[],this.params={},this.regex=h(this.path,this.keys,!1,!1)};g.prototype.addHandler=function(a){this.fns.push(a)},g.prototype.removeHandler=function(a){for(var b=0,c=this.fns.length;c>b;b++){var d=this.fns[b];if(a==d)return void this.fns.splice(b,1)}},g.prototype.run=function(a){for(var b=0,c=this.fns.length;c>b;b++)this.fns[b].apply(this,a)},g.prototype.match=function(a,b){var c=this.regex.exec(a);if(!c)return!1;for(var d=1,e=c.length;e>d;++d){var f=this.keys[d-1],g="string"==typeof c[d]?decodeURIComponent(c[d]):c[d];f&&(this.params[f.name]=g),b.push(g)}return!0},g.prototype.toURL=function(a){var b=this.path;for(var c in a)b=b.replace("/:"+c,"/"+a[c]);if(b=b.replace(/\/:.*\?/g,"/").replace(/\?/g,""),-1!=b.indexOf(":"))throw new Error("missing parameters for url: "+b);return b};var h=function(a,b,c,d){return a instanceof RegExp?a:(a instanceof Array&&(a="("+a.join("|")+")"),a=a.concat(d?"":"/?").replace(/\/\(/g,"(?:/").replace(/\+/g,"__plus__").replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?/g,function(a,c,d,e,f,g){return b.push({name:e,optional:!!g}),c=c||"",""+(g?"":c)+"(?:"+(g?c:"")+(d||"")+(f||d&&"([^/.]+?)"||"([^/]+?)")+")"+(g||"")}).replace(/([\/.])/g,"\\$1").replace(/__plus__/g,"(.+)").replace(/\*/g,"(.*)"),new RegExp("^"+a+"$",c?"":"i"))},i=function(a,b){var e=a.split(" "),f=2==e.length?e[0]:null;a=2==e.length?e[1]:e[0],d[a]||(d[a]=new g(a,f),c.push(d[a])),d[a].addHandler(b)},j=function(a,b){if("function"==typeof b)i(a,b),j.reload();else if("object"==typeof a){for(var c in a)i(c,a[c]);j.reload()}else"undefined"==typeof b&&j.navigate(a)};j.lookup=function(a,b){for(var d=0,e=c.length;e>d;d++){var f=c[d];if(f.name==a)return f.toURL(b)}},j.remove=function(a,b){var c=d[a];c&&c.removeHandler(b)},j.removeAll=function(){d={},c=[]},j.navigate=function(a,b){b=b||{};var c=b.silent||!1;c&&o(),setTimeout(function(){window.location.hash=a,c&&setTimeout(function(){n()},1)},1)},j.noConflict=function(){return a[e]=f,j};var k=function(){return window.location.hash.substring(1)},l=function(a,b){var c=[];return b.match(a,c)?(b.run(c),!0):!1},m=j.reload=function(){for(var a=k(),b=0,d=c.length;d>b;b++){var e=c[b];if(l(a,e))return}},n=function(){a.addEventListener?a.addEventListener("hashchange",m,!1):a.attachEvent("onhashchange",m)},o=function(){a.removeEventListener?a.removeEventListener("hashchange",m):a.detachEvent("onhashchange",m)};return n(),b?j:void(a[e]=j)};"undefined"==typeof module?Routie(window):module.exports=Routie(window,!0);
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@antv/g2-brush",
3 | "version": "0.0.2",
4 | "description": "Select a one-, two-dimensional or irregular region using the mouse.",
5 | "main": "build/g2-brush.js",
6 | "browser": "build/g2-brush.js",
7 | "module": "index.js",
8 | "repository": {
9 | "type": "git",
10 | "url": "git@github.com:antvis/g2-brush.git"
11 | },
12 | "keywords": [
13 | "antv",
14 | "g2-brush",
15 | "g2"
16 | ],
17 | "author": "sima.zhang1990@gmail.com",
18 | "license": "MIT",
19 | "devDependencies": {
20 | "@lite-js/torch": "~0.2.6",
21 | "babel-core": "~6.25.0",
22 | "babel-eslint": "~7.2.3",
23 | "babel-loader": "~7.1.1",
24 | "babel-plugin-transform-remove-strict-mode": "~0.0.2",
25 | "babel-preset-es2015": "~6.24.1",
26 | "babel-preset-stage-0": "~6.24.1",
27 | "chai": "~4.0.1",
28 | "commander": "~2.9.0",
29 | "connect": "~3.6.3",
30 | "d3-queue": "~3.0.7",
31 | "debug": "~3.1.0",
32 | "electron": "~1.6.11",
33 | "eslint": "^3.19.0",
34 | "eslint-config-airbnb": "~15.0.1",
35 | "eslint-config-egg": "~4.2.0",
36 | "eslint-plugin-html": "~3.1.1",
37 | "get-port": "~3.1.0",
38 | "gh-pages": "~1.1.0",
39 | "nightmare": "~2.10.0",
40 | "nunjucks": "~3.0.1",
41 | "open": "~0.0.5",
42 | "parseurl": "~1.3.1",
43 | "pre-commit": "~1.2.2",
44 | "serve-static": "~1.12.4",
45 | "shelljs": "~0.7.8",
46 | "uglify-js": "~3.0.15",
47 | "webpack": "~3.3.0"
48 | },
49 | "scripts": {
50 | "build": "webpack",
51 | "ci": "npm run lint && npm run test",
52 | "compress": "uglifyjs -c -m -o dist/g2-brush.min.js -- build/g2-brush.js",
53 | "coverage": "npm run coverage-generator && npm run coverage-viewer",
54 | "coverage-generator": "torch --compile --coverage --renderer --recursive test/unit",
55 | "coverage-viewer": "torch-coverage",
56 | "demos": "electron ./demos/app.js",
57 | "demos-web": "node ./demos/app.js --web --port 2046",
58 | "dev": "npm run watch & npm run demos-web",
59 | "dist": "npm run mkdir-dist && npm run build && npm run compress",
60 | "lint": "eslint --ext .html,.js ./",
61 | "lint-fix": "eslint --ext .html,.js --fix ./",
62 | "mkdir-dist": "node ./bin/mkdir-dist.js",
63 | "prepublishOnly": "npm run dist",
64 | "screenshot": "node ./bin/screenshot.js",
65 | "test": "torch --compile --renderer --recursive ./test/unit",
66 | "test-live": "torch --compile --interactive --watch --recursive ./test/unit",
67 | "watch": "webpack --config webpack-dev.config.js",
68 | "win-dev": "node ./bin/win-dev.js"
69 | },
70 | "pre-commit": {
71 | "run": [
72 | "lint",
73 | "build",
74 | "test"
75 | ],
76 | "silent": false
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/bin/screenshot.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | process.env.DEBUG = 'app:*';
3 | const debug = require('debug')('app:screenshot');
4 | const MAX_POOL_SIZE = require('os').cpus().length;
5 | const Nightmare = require('nightmare');
6 | const _ = require('lodash');
7 | const commander = require('commander');
8 | const connect = require('connect');
9 | const getPort = require('get-port');
10 | const http = require('http');
11 | const path = require('path');
12 | const basename = path.basename;
13 | const extname = path.extname;
14 | const join = path.join;
15 | const queue = require('d3-queue').queue;
16 | const serveStatic = require('serve-static');
17 | const shelljs = require('shelljs');
18 | const ls = shelljs.ls;
19 | const mkdir = shelljs.mkdir;
20 | const pkg = require('../package.json');
21 |
22 | commander
23 | .version(pkg.version)
24 | .option('-p, --port ', 'specify a port number to run on', parseInt)
25 | .option('-n, --name ', 'specify the name for demos')
26 | .parse(process.argv);
27 |
28 | // assets
29 | const src = join(process.cwd(), './demos');
30 | const dest = join(process.cwd(), './demos/assets/screenshots');
31 | mkdir('-p', dest);
32 |
33 | const app = connect();
34 | app.use('/', serveStatic(process.cwd()));
35 |
36 | const DELAY = 6000;
37 |
38 | getPort().then(port => {
39 | http.createServer(app).listen(port);
40 | const url = 'http://127.0.0.1:' + port;
41 | debug('server is ready on port ' + port + '! url: ' + url);
42 |
43 | const q = queue(MAX_POOL_SIZE > 2 ? MAX_POOL_SIZE - 1 : MAX_POOL_SIZE);
44 | const files = ls(src).filter(filename => (extname(filename) === '.html'));
45 | files.forEach(filename => {
46 | const name = basename(filename, '.html');
47 | if (_.isString(commander.name) && filename.indexOf(commander.name) === -1) {
48 | debug(`>>>>>>>>> skipping because filename not matched: ${name}`);
49 | return;
50 | }
51 | q.defer(callback => {
52 | const t0 = Date.now();
53 | const nightmare = Nightmare({
54 | gotoTimeout: 600000,
55 | show: false
56 | });
57 | const url = `http://127.0.0.1:${port}/demos/${name}.html`;
58 | const target = join(dest, `./${name}.png`);
59 | nightmare.viewport(800, 450) // 16 x 9
60 | .goto(url)
61 | .wait(DELAY)
62 | .screenshot(target, () => {
63 | debug(name + ' took ' + (Date.now() - t0) + ' to take a screenshot.');
64 | callback(null);
65 | })
66 | .end()
67 | .catch(e => {
68 | debug(url);
69 | debug(target);
70 | debug(name + ' failed to take a screenshot: ' + e);
71 | });
72 | });
73 | });
74 | q.awaitAll(error => {
75 | if (error) {
76 | debug(error);
77 | process.exit(1);
78 | }
79 | debug('screenshots are all captured!');
80 | process.exit();
81 | });
82 | });
83 |
--------------------------------------------------------------------------------
/demos/ds-state.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | DataSet State
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
102 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/demos/assets/index.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | // filtering
3 | const $query = $('#query');
4 | function filter() {
5 | const str = $query.val();
6 | if (!str) {
7 | $('.demo-thumbnail').show();
8 | } else {
9 | $('.demo-thumbnail').each(function () {
10 | const $thumbnail = $(this);
11 | const basename = $thumbnail.data('basename');
12 | if (basename.indexOf(str) === -1) {
13 | $thumbnail.hide();
14 | } else {
15 | $thumbnail.show();
16 | }
17 | });
18 | }
19 | }
20 | $query.on('input', _.debounce(filter));
21 |
22 | // router
23 | let currentId;
24 | const $code = $('#code');
25 | const htmlEditor = CodeMirror.fromTextArea($code[0], {
26 | mode: "text/html",
27 | extraKeys: {
28 | 'Ctrl-Space': 'autocomplete'
29 | },
30 | foldGutter: true,
31 | gutters: [
32 | 'CodeMirror-linenumbers',
33 | 'CodeMirror-foldgutter'
34 | ],
35 | lineNumbers: true,
36 | lineWrapping: false
37 | });
38 |
39 | const $docContainer = $('#doc-container');
40 | const $chartPanel = $('#chart-panel');
41 | const $codePanel = $('#code-panel');
42 |
43 | function syncCode(code) {
44 | $chartPanel.html('');
45 | $chartPanel.find('iframe')[0].contentWindow.document.write(code);
46 | htmlEditor.getDoc().setValue(code);
47 | }
48 |
49 | routie({
50 | '/:id': id => {
51 | $docContainer.show();
52 | const $htmlCode = $(`#code-${id}`);
53 | const code = $htmlCode.text();
54 | syncCode(code)
55 | },
56 | '': () => {
57 | $docContainer.hide();
58 | }
59 | });
60 |
61 | // resizable
62 | $codePanel.resizable({
63 | handleSelector: '#resize-handler',
64 | resizeWidthFrom: 'right',
65 | resizeHeight: false,
66 | onDragStart() {
67 | $docContainer.css('pointer-events', 'none');
68 | $docContainer.css('cursor', 'col-resize');
69 | $codePanel.find('.CodeMirror-gutter-elt').css('cursor', 'col-resize');
70 | },
71 | onDragEnd() {
72 | $docContainer.css('pointer-events', 'auto');
73 | $docContainer.css('cursor', 'default');
74 | $codePanel.find('.CodeMirror-gutter-elt').css('cursor', 'default');
75 | },
76 | });
77 |
78 | // copy code
79 | const BTN_COPY_SELECTOR = '#copy-code';
80 | const clipboard = new Clipboard(BTN_COPY_SELECTOR, {
81 | text: () => htmlEditor.getValue(),
82 | });
83 | let timer;
84 | clipboard.on('success', e => {
85 | e.clearSelection();
86 | $(BTN_COPY_SELECTOR).text('Succeed!');
87 | clearTimeout(timer);
88 | timer = setTimeout(() => {
89 | $(BTN_COPY_SELECTOR).text('Copy');
90 | }, 2000);
91 | });
92 | clipboard.on('error', e => {
93 | e.clearSelection();
94 | $(BTN_COPY_SELECTOR).text('Failed!');
95 | clearTimeout(timer);
96 | timer = setTimeout(() => {
97 | $(BTN_COPY_SELECTOR).text('Copy');
98 | }, 2000);
99 | });
100 |
101 | // run code
102 | $('#execute').on('click', () => {
103 | syncCode(htmlEditor.getValue());
104 | });
105 | })();
106 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # g2-brush
2 |
3 | 
4 | 
5 |
6 | [](https://www.npmjs.com/package/@antv/g2-brush)
7 | [](https://npmjs.org/package/@antv/g2-brush)
8 | [](http://isitmaintained.com/project/antvis/g2-brush "Percentage of issues still open")
9 |
10 | Chart's interaction enhancement tool for [G2](https://github.com/antvis/g2)(Please use a version greater than 3.0.1).
11 |
12 | ## Install
13 |
14 | ```bash
15 | $ npm install @antv/g2-brush
16 | ```
17 |
18 | or use cdn:
19 |
20 | ```html
21 |
22 | ```
23 |
24 | ## Usage
25 |
26 | First of all, the brush instance must be created after the chart be rendered.
27 |
28 | ```js
29 | import Brush from '@antv/g2-brush';
30 | // ...
31 | chart.render();
32 |
33 | new Brush({
34 | canvas: chart.get('canvas'), // must be set
35 | chart, // if you want to filter data by default, please set the chart
36 | type: 'X', // set the brush type, default value is 'XY'
37 | });
38 | ```
39 |
40 | ### Example
41 |
42 | online demos: [https://antvis.github.io/g2-brush/demos/#](https://antvis.github.io/g2-brush/demos/#)
43 |
44 | 
45 |
46 | ```js
47 | $.getJSON('./data/top2000.json', data => {
48 | const ds = new DataSet();
49 | const dv = ds.createView('test')
50 | .source(data)
51 | .transform({
52 | as: [ 'count' ],
53 | groupBy: [ 'release' ],
54 | operations: [ 'count' ],
55 | type: 'aggregate'
56 | });
57 |
58 | const chart = new G2.Chart({
59 | container: 'canvas',
60 | forceFit: true,
61 | height: window.innerHeight
62 | });
63 | chart.source(dv);
64 | chart.scale({
65 | count: {
66 | alias: 'top2000 唱片总量'
67 | },
68 | release: {
69 | tickInterval: 5,
70 | alias: '唱片发行年份'
71 | }
72 | });
73 | chart.interval()
74 | .position('release*count')
75 | .color('#e50000');
76 |
77 | chart.render();
78 |
79 | new Brush({
80 | canvas: chart.get('canvas'),
81 | chart,
82 | type: 'X',
83 | onBrushstart() {
84 | chart.hideTooltip();
85 | },
86 | onBrushmove() {
87 | chart.hideTooltip();
88 | }
89 | });
90 | chart.on('plotdblclick', () => {
91 | chart.get('options').filters = {};
92 | chart.repaint();
93 | });
94 | });
95 | ```
96 |
97 | ## API
98 |
99 | [API DOCS](https://github.com/antvis/g2-brush/blob/master/docs/brush.md)
100 |
101 | ## Development
102 |
103 | ```bash
104 | $ npm install
105 |
106 | $ npm run dev
107 | ```
108 |
109 | ## How to Contribute
110 |
111 | Please let us know how can we help. Do check out [issues](https://github.com/antvis/g2-brush/issues) for bug reports or suggestions first.
112 |
113 | To become a contributor, please follow our [contributing guide](https://github.com/antvis/g2-brush/blob/master/CONTRIBUTING.md).
114 |
--------------------------------------------------------------------------------
/docs/brush.md:
--------------------------------------------------------------------------------
1 | # API
2 |
3 | First of all, the brush instance must be created after the chart be rendered.
4 |
5 |
6 | ```js
7 | import Brush from '@antv/brush';
8 |
9 | const brush = new Brush({
10 | // properties
11 | });
12 | ```
13 |
14 | ## Properties
15 |
16 | - `canvas`
17 |
18 | An instance of G.Canvas. **Must be set**. If use it for G2 chart, just get it by `chart.get('canvas')`.
19 |
20 | ```js
21 | canvas: chart.get('canvas')
22 | ```
23 |
24 | - `chart`
25 |
26 | An instance of G2.Chart. Set the brush target, then after brush action end,
27 | data will be automatically filtered when the `filter` property is true.
28 |
29 | - `type`
30 |
31 | String. Set the brush type, default is **'XY'**, also you can set **'X'**, **'Y'**, **'POLYGON'**. Case insensitive.
32 |
33 | - `style`
34 |
35 | Object. It's for setting the brush style. Default value is:
36 |
37 | ```js
38 | {
39 | fill: '#C5D4EB',
40 | opacity: 0.3,
41 | lineWidth: 1,
42 | stroke: '#82A6DD'
43 | }
44 | ```
45 |
46 | - `inPlot`
47 |
48 | Boolean. Decide if the selection range is limited to the drawing area. Default value is true.
49 |
50 | - `filter`
51 |
52 | Boolean. Decide if automatically filter the data, default value is decided by `dragable` value,!dragable. But still set by the user.
53 |
54 | - `dragable`
55 |
56 | Boolean. Set whether the shape can be dragged, default is `false`, then `filter` is true.
57 |
58 | - `xField`
59 |
60 | String. Set the selected x-axis field name, used to get the scale instance of the x-axis. Optional.
61 |
62 | - `yField`
63 |
64 | String. Set the selected y-axis field name, used to get the scale instance of the y-axis. Optional.
65 |
66 | - `onBrushstart`
67 |
68 | Function. [examples](https://antvis.github.io/g2-brush/demos/#/highlight)
69 |
70 | ```js
71 | onBrushstart(ev) {
72 | // at the begining of the selection, you can define some properties, like chart xScale etc.
73 | const me = this; // On behalf of the object itself
74 | me.chart = chart;
75 | }
76 | ```
77 |
78 | - `onBrushmove`
79 |
80 | Function. [examples](https://antvis.github.io/g2-brush/demos/#/highlight)
81 |
82 | ```js
83 | onBrushmove(ev) {
84 | // during selection
85 | const { data, shapes, x, y, ...others } = ev;
86 | }
87 | ```
88 |
89 | - `onBrushend`
90 |
91 | Function. [examples]()
92 |
93 | ```js
94 | onBrushend(ev) {
95 | // selection stoped
96 | const { data, shapes, x, y, ...others } = ev;
97 | }
98 | ```
99 |
100 | - `onDragstart`
101 |
102 | Function. Only `dragable` is true.
103 |
104 | ```js
105 | onDragstart(ev) {
106 | // at the begining of the drag, you can define some properties, like chart xScale etc.
107 | }
108 | ```
109 |
110 | - `onDragmove`
111 |
112 | Function. Only `dragable` is true.
113 |
114 | [examples](https://antvis.github.io/g2-brush/demos/#/highlight)
115 |
116 | ```js
117 | onDragmove(ev) {
118 | // during drag
119 | const { data, shapes, x, y, ...others } = ev;
120 | }
121 | ```
122 |
123 | - `onDragend`
124 |
125 | Function. Only `dragable` is true.
126 |
127 | [examples](https://antvis.github.io/g2-brush/demos/#/highlight)
128 |
129 | ```js
130 | onDragend(ev) {
131 | // drag stoped
132 | const { data, shapes, x, y, ...others } = ev;
133 | }
134 | ```
135 |
136 | ## Function
137 |
138 | - `setType(type)`
139 |
140 | used for change brush type, see [examples](https://antvis.github.io/g2-brush/demos/#/highlight).
141 |
--------------------------------------------------------------------------------
/demos/polygon.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Polygon brush
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/CONTRIBUTING.zh-CN.md:
--------------------------------------------------------------------------------
1 | # 代码贡献规范
2 |
3 | 有任何疑问,欢迎提交 [issue](https://github.com/antvis/g2-brush/issues),
4 | 或者直接修改提交 [PR](https://github.com/antvis/g2-brush/pulls)!
5 |
6 | ## 提交 issue
7 |
8 | - 请确定 issue 的类型。
9 | - 请避免提交重复的 issue,在提交之前搜索现有的 issue。
10 | - 在标签(分类参考**标签分类**), 标题 或者内容中体现明确的意图。
11 |
12 | 随后 AntV 负责人会确认 issue 意图,更新合适的标签,关联 milestone,指派开发者。
13 |
14 | ## 提交代码
15 |
16 | ### 提交 Pull Request
17 |
18 | 如果你有仓库的开发者权限,而且希望贡献代码,那么你可以创建分支修改代码提交 PR,AntV 开发团队会 review 代码合并到主干。
19 |
20 | ```bash
21 | # 先创建开发分支开发,分支名应该有含义,避免使用 update、tmp 之类的
22 | $ git checkout -b branch-name
23 |
24 | # 开发完成后跑下测试是否通过,必要时需要新增或修改测试用例
25 | $ npm test
26 |
27 | # 测试通过后,提交代码,message 见下面的规范
28 |
29 | $ git add . # git add -u 删除文件
30 | $ git commit -m "fix(role): role.use must xxx"
31 | $ git push origin branch-name
32 | ```
33 |
34 | 提交后就可以在 [g2-brush](https://github.com/antvis/g2-brush/pulls) 创建 Pull Request 了。
35 |
36 | 由于谁也无法保证过了多久之后还记得多少,为了后期回溯历史的方便,请在提交 MR 时确保提供了以下信息。
37 |
38 | 1. 需求点(一般关联 issue 或者注释都算)
39 | 2. 升级原因(不同于 issue,可以简要描述下为什么要处理)
40 | 3. 框架测试点(可以关联到测试文件,不用详细描述,关键点即可)
41 | 4. 关注点(针对用户而言,可以没有,一般是不兼容更新等,需要额外提示)
42 |
43 | ### 代码风格
44 |
45 | 你的代码风格必须通过 eslint,你可以运行 `$ npm run lint` 本地测试。
46 |
47 | ### Commit 提交规范
48 |
49 | 根据 [angular 规范](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit-message-format)提交 commit,
50 | 这样 history 看起来更加清晰,还可以自动生成 changelog。
51 |
52 | ```xml
53 | ():
54 |
55 |
56 |
57 |