├── src ├── assets │ ├── colors.css │ ├── logo.png │ └── ant-theme.less ├── shims-vue.d.ts ├── views │ ├── index.vue │ ├── About.vue │ ├── Home.vue │ ├── charts │ │ ├── components │ │ │ ├── circle.vue │ │ │ ├── bar.vue │ │ │ ├── line.vue │ │ │ └── relation.vue │ │ └── index.vue │ ├── graphics │ │ ├── components │ │ │ ├── circle.vue │ │ │ ├── bar.vue │ │ │ ├── line.vue │ │ │ └── relation.vue │ │ └── index.vue │ ├── others │ │ └── 404.vue │ ├── charts.vue │ └── layout │ │ └── index.vue ├── store.ts ├── shims-tsx.d.ts ├── App.vue ├── main.ts ├── registerServiceWorker.ts ├── router │ └── index.ts └── components │ └── HelloWorld.vue ├── .browserslistrc ├── colors.js ├── public ├── robots.txt ├── img │ └── favicon.ico ├── manifest.json └── index.html ├── babel.config.js ├── postcss.config.js ├── README.md ├── .gitignore ├── tests ├── unit │ └── example.spec.ts └── e2e │ ├── specs │ └── test.js │ └── custom-assertions │ └── elementCount.js ├── tslint.json ├── tsconfig.json ├── package.json └── vue.config.js /src/assets/colors.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | -------------------------------------------------------------------------------- /colors.js: -------------------------------------------------------------------------------- 1 | export default colors ={ 2 | 3 | } -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calamus0427/vue-d3/master/src/assets/logo.png -------------------------------------------------------------------------------- /public/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calamus0427/vue-d3/master/public/img/favicon.ico -------------------------------------------------------------------------------- /src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import Vue from 'vue'; 3 | export default Vue; 4 | } 5 | -------------------------------------------------------------------------------- /src/views/index.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /src/store.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | 4 | Vue.use(Vuex); 5 | 6 | export default new Vuex.Store({ 7 | state: { 8 | 9 | }, 10 | mutations: { 11 | 12 | }, 13 | actions: { 14 | 15 | }, 16 | }); 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-d3 2 | > 基于vue-cli3 实现的d3.js demo项目,在vue中使用d3 3 | 4 | [示例](http://calamus.wiki/vue-d3/) 5 | 6 | ## Project setup 7 | ``` 8 | # 安装依赖 9 | npm install 10 | # 启动 11 | npm run serve 12 | # 打包部署 13 | npm run build 14 | # 测试 15 | npm run test 16 | npm run lint 17 | npm run test:e2e 18 | npm run test:unit 19 | 20 | ``` 21 | -------------------------------------------------------------------------------- /src/views/About.vue: -------------------------------------------------------------------------------- 1 | 6 | 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | /tests/e2e/reports/ 6 | selenium-debug.log 7 | 8 | # local env files 9 | .env.local 10 | .env.*.local 11 | 12 | # Log files 13 | npm-debug.log* 14 | yarn-debug.log* 15 | yarn-error.log* 16 | 17 | # Editor directories and files 18 | .idea 19 | .vscode 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /src/shims-tsx.d.ts: -------------------------------------------------------------------------------- 1 | import Vue, { VNode } from 'vue'; 2 | 3 | declare global { 4 | namespace JSX { 5 | // tslint:disable no-empty-interface 6 | interface Element extends VNode {} 7 | // tslint:disable no-empty-interface 8 | interface ElementClass extends Vue {} 9 | interface IntrinsicElements { 10 | [elem: string]: any; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 18 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App.vue'; 3 | import router from './router/index'; 4 | import store from './store'; 5 | import Antd from 'ant-design-vue' ; 6 | import 'ant-design-vue/dist/antd.less' ; 7 | import './registerServiceWorker'; 8 | 9 | 10 | Vue.config.productionTip = false; 11 | Vue.use(Antd) ; 12 | 13 | new Vue({ 14 | router, 15 | store, 16 | render: (h) => h(App), 17 | }).$mount('#app'); 18 | -------------------------------------------------------------------------------- /tests/unit/example.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { shallowMount } from '@vue/test-utils'; 3 | import HelloWorld from '@/components/HelloWorld.vue'; 4 | 5 | describe('HelloWorld.vue', () => { 6 | it('renders props.msg when passed', () => { 7 | const msg = 'new message'; 8 | const wrapper = shallowMount(HelloWorld, { 9 | propsData: { msg }, 10 | }); 11 | expect(wrapper.text()).to.include(msg); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "warning", 3 | "extends": [ 4 | "tslint:recommended" 5 | ], 6 | "linterOptions": { 7 | "exclude": [ 8 | "node_modules/**" 9 | ] 10 | }, 11 | "rules": { 12 | "quotemark": [true, "single"], 13 | "indent": [true, "spaces", 2], 14 | "interface-name": false, 15 | "ordered-imports": false, 16 | "object-literal-sort-keys": false, 17 | "no-consecutive-blank-lines": false 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'default e2e tests': browser => { 6 | browser 7 | .url(process.env.VUE_DEV_SERVER_URL) 8 | .waitForElementVisible('#app', 5000) 9 | .assert.elementPresent('.hello') 10 | .assert.containsText('h1', 'Welcome to Your Vue.js + TypeScript App') 11 | .assert.elementCount('img', 1) 12 | .end() 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-d3", 3 | "short_name": "vue-d3", 4 | "icons": [ 5 | { 6 | "src": "https://cdn.calamus.xyz/favicon.ico", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "https://cdn.calamus.xyz/favicon.ico", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "start_url": "./index.html", 17 | "display": "standalone", 18 | "background_color": "#000000", 19 | "theme_color": "#4DBA87" 20 | } 21 | -------------------------------------------------------------------------------- /src/assets/ant-theme.less: -------------------------------------------------------------------------------- 1 | /* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */ 2 | 3 | // The prefix to use on all css classes from ant. 4 | 5 | // -------- Colors ----------- 6 | @primary-color :pink; 7 | // @info-color : @blue-6; 8 | // @success-color : @green-6; 9 | // @processing-color : @blue-6; 10 | // @error-color : @red-6; 11 | // @highlight-color : @red-6; 12 | // @warning-color : @gold-6; 13 | // @normal-color : #d9d9d9; 14 | // @white: #fff; 15 | // @black: #000; 16 | 17 | -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 19 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | vue-d3 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/views/charts/components/circle.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 30 | 36 | 37 | -------------------------------------------------------------------------------- /src/views/graphics/components/circle.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 30 | 36 | 37 | -------------------------------------------------------------------------------- /tests/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // The assertion name is the filename. 3 | // Example usage: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // For more information on custom assertions see: 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | 10 | exports.assertion = function elementCount (selector, count) { 11 | this.message = `Testing if element <${selector}> has count: ${count}` 12 | this.expected = count 13 | this.pass = val => val === count 14 | this.value = res => res.value 15 | function evaluator (_selector) { 16 | return document.querySelectorAll(_selector).length 17 | } 18 | this.command = cb => this.api.execute(evaluator, [selector], cb) 19 | } 20 | -------------------------------------------------------------------------------- /src/views/charts/index.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 32 | -------------------------------------------------------------------------------- /src/views/graphics/index.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 32 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "experimentalDecorators": true, 10 | "esModuleInterop": true, 11 | "allowSyntheticDefaultImports": true, 12 | "sourceMap": true, 13 | "baseUrl": ".", 14 | "types": [ 15 | "webpack-env", 16 | "mocha", 17 | "chai" 18 | ], 19 | "paths": { 20 | "@/*": [ 21 | "src/*" 22 | ] 23 | }, 24 | "lib": [ 25 | "esnext", 26 | "dom", 27 | "dom.iterable", 28 | "scripthost" 29 | ] 30 | }, 31 | "include": [ 32 | "src/**/*.ts", 33 | "src/**/*.tsx", 34 | "src/**/*.vue", 35 | "tests/**/*.ts", 36 | "tests/**/*.tsx" 37 | ], 38 | "exclude": [ 39 | "node_modules" 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /src/views/charts/components/bar.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 31 | 45 | 46 | -------------------------------------------------------------------------------- /src/views/graphics/components/bar.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 31 | 45 | 46 | -------------------------------------------------------------------------------- /src/registerServiceWorker.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-console */ 2 | 3 | import { register } from 'register-service-worker'; 4 | 5 | if (process.env.NODE_ENV === 'production') { 6 | register(`${process.env.BASE_URL}service-worker.js`, { 7 | ready() { 8 | console.log( 9 | 'App is being served from cache by a service worker.\n' + 10 | 'For more details, visit https://goo.gl/AFskqB', 11 | ); 12 | }, 13 | registered() { 14 | console.log('Service worker has been registered.'); 15 | }, 16 | cached() { 17 | console.log('Content has been cached for offline use.'); 18 | }, 19 | updatefound() { 20 | console.log('New content is downloading.'); 21 | }, 22 | updated() { 23 | console.log('New content is available; please refresh.'); 24 | }, 25 | offline() { 26 | console.log('No internet connection found. App is running in offline mode.'); 27 | }, 28 | error(error) { 29 | console.error('Error during service worker registration:', error); 30 | }, 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /src/views/others/404.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 20 | 21 | 47 | -------------------------------------------------------------------------------- /src/router/index.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Router from 'vue-router'; 3 | import Home from '../views/Home.vue'; 4 | import layout from '../views/layout/index.vue'; 5 | 6 | Vue.use(Router); 7 | 8 | export default new Router({ 9 | mode: 'hash', 10 | base: process.env.BASE_URL, 11 | routes: [ 12 | { 13 | path: '/', 14 | name: 'layout', 15 | component: layout, 16 | redirect:'/home', 17 | children:[ 18 | { 19 | path: '/home', 20 | name: 'home', 21 | component:() => import('../views/index.vue') 22 | }, 23 | { 24 | path: '/graphics', 25 | name: 'graphics', 26 | component:() => import('../views/graphics/index.vue') 27 | }, 28 | { 29 | path: '/charts', 30 | name: 'charts', 31 | component:() => import('../views/charts/index.vue') 32 | } 33 | ] 34 | }, 35 | { 36 | path: '/about', 37 | name: 'about', 38 | component: () => import('../views/About.vue'), 39 | }, 40 | { 41 | path: '*', 42 | component: () => import('../views/others/404.vue'), 43 | } 44 | ], 45 | }); 46 | -------------------------------------------------------------------------------- /src/views/charts.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 42 | 52 | 53 | -------------------------------------------------------------------------------- /src/views/charts/components/line.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 42 | 52 | 53 | -------------------------------------------------------------------------------- /src/views/graphics/components/line.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 42 | 52 | 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-d3", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint", 9 | "test:e2e": "vue-cli-service test:e2e", 10 | "test:unit": "vue-cli-service test:unit" 11 | }, 12 | "dependencies": { 13 | "@babel/polyfill": "^7.4.4", 14 | "ant-design-vue": "^1.3.8", 15 | "core-js": "^2.6.5", 16 | "register-service-worker": "^1.6.2", 17 | "transform-runtime": "0.0.0", 18 | "vue": "^2.6.10", 19 | "vue-class-component": "^7.0.2", 20 | "vue-property-decorator": "^8.1.0", 21 | "vue-router": "^3.0.3", 22 | "vuex": "^3.0.1" 23 | }, 24 | "devDependencies": { 25 | "@types/chai": "^4.1.0", 26 | "@types/mocha": "^5.2.4", 27 | "@vue/cli-plugin-babel": "^3.7.0", 28 | "@vue/cli-plugin-e2e-nightwatch": "^3.7.0", 29 | "@vue/cli-plugin-pwa": "^3.7.0", 30 | "@vue/cli-plugin-typescript": "^3.7.0", 31 | "@vue/cli-plugin-unit-mocha": "^3.7.0", 32 | "@vue/cli-service": "^3.7.0", 33 | "@vue/test-utils": "1.0.0-beta.29", 34 | "babel-plugin-transform-object-rest-spread": "^6.26.0", 35 | "chai": "^4.1.2", 36 | "d3": "^5.9.2", 37 | "less": "^3.0.4", 38 | "less-loader": "^4.1.0", 39 | "typescript": "^3.4.3", 40 | "vue-template-compiler": "^2.5.21" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 44 | 45 | 46 | 62 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | // vue.config.js 2 | module.exports = { 3 | publicPath: process.env.NODE_ENV === 'production' ? './' : '/', 4 | pages: { 5 | index: { 6 | // page 的入口 7 | entry: 'src/main.ts', 8 | // 模板来源 9 | template: 'public/index.html', 10 | // 在 dist/index.html 的输出 11 | filename: 'index.html', 12 | // 当使用 title 选项时, 13 | // template 中的 title 标签需要是 <%= htmlWebpackPlugin.options.title %> 14 | title: 'Index Page', 15 | // 在这个页面中包含的块,默认情况下会包含 16 | // 提取出来的通用 chunk 和 vendor chunk。 17 | chunks: ['chunk-vendors', 'chunk-common', 'index'] 18 | }, 19 | // 当使用只有入口的字符串格式时, 20 | // 模板会被推导为 `public/subpage.html` 21 | // 并且如果找不到的话,就回退到 `public/index.html`。 22 | // 输出文件名会被推导为 `subpage.html`。 23 | }, 24 | //loader 25 | css: { 26 | loaderOptions: { 27 | css: { 28 | "style": true, 29 | // 这里的选项会传递给 css-loader 30 | }, 31 | postcss: { 32 | // 这里的选项会传递给 postcss-loader 33 | }, 34 | less:{ 35 | modifyVars: { 36 | 'primary-color':'#94c5f3', // 全局主色 37 | 'link-color':' #1890ff', // 链接色 38 | 'success-color':' #52c41a', // 成功色 39 | 'warning-color':' #faad14', // 警告色 40 | 'error-color':' #f5222d', // 错误色 41 | 'font-size-base': '14px', // 主字号 42 | 'heading-color': 'rgba(0, 0, 0, .85)', // 标题色 43 | 'text-color': 'rgba(0, 0, 0, .65)', // 主文本色 44 | 'text-color-secondary' : 'rgba(0, 0, 0, .45)', // 次文本色 45 | 'disabled-color' : 'rgba(0, 0, 0, .25)', // 失效色 46 | 'border-radius-base': '4px', // 组件/浮层圆角 47 | 'border-color-base':' #d9d9d9', // 边框色 48 | 'box-shadow-base': '0 2px 8px rgba(0, 0, 0, .15)', // 浮层阴影 49 | // dark theme 50 | // 'menu-dark-color': '#B9D5FA', 51 | 'menu-dark-bg': '#B9D5FA', 52 | // 'menu-dark-arrow-color': 'fff', 53 | // 'menu-dark-submenu-bg':' #000c17', 54 | // 'menu-dark-highlight-color':' #fff', 55 | // 'menu-dark-item-active-bg': 'primary-color' 56 | }, 57 | javascriptEnabled: true 58 | } 59 | } 60 | }, 61 | pwa: { 62 | iconPaths: { 63 | favicon32: 'img/favicon.ico', 64 | favicon16: 'img/favicon.ico', 65 | appleTouchIcon: 'img/favicon.ico', 66 | maskIcon: 'img/favicon.ico', 67 | msTileImage: 'img/favicon.ico' 68 | } 69 | } 70 | 71 | } -------------------------------------------------------------------------------- /src/views/layout/index.vue: -------------------------------------------------------------------------------- 1 | 55 | 56 | 82 | 83 | 175 | 176 | -------------------------------------------------------------------------------- /src/views/charts/components/relation.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 362 | 363 | -------------------------------------------------------------------------------- /src/views/graphics/components/relation.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 362 | 363 | --------------------------------------------------------------------------------