├── .eslintrc.js ├── .gitignore ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── public ├── icons │ ├── 24px │ │ ├── close.png │ │ ├── crosshairs-gps.png │ │ ├── download.png │ │ ├── fit-to-page-outline.png │ │ ├── redo.png │ │ └── undo.png │ └── 36px │ │ ├── code-json.png │ │ ├── image.png │ │ └── markdown.png ├── index.html ├── learn.json └── mindmap.jpg ├── src ├── App.vue ├── components │ ├── MindMap.vue │ └── Outline.vue ├── css │ └── MindMap.scss ├── index.d.ts ├── main.ts ├── plugins │ └── vuetify.ts ├── shims-tsx.d.ts ├── shims-vue.d.ts ├── ts │ ├── History.ts │ ├── ImData.ts │ ├── d3.ts │ └── toMarkdown.ts └── types │ ├── d3-zoom.d.ts │ └── flextree.d.ts ├── tsconfig.json └── vue.config.js /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es2020: true, 5 | }, 6 | extends: [ 7 | 'plugin:vue/essential', 8 | 'standard', 9 | ], 10 | parserOptions: { 11 | ecmaVersion: 11, 12 | parser: '@typescript-eslint/parser', 13 | sourceType: 'module', 14 | }, 15 | plugins: [ 16 | 'vue', 17 | '@typescript-eslint', 18 | ], 19 | rules: { 20 | 'lines-between-class-members': 0, 21 | 'space-before-function-paren': ['error', 'never'], 22 | 'comma-dangle': ['error', 'always-multiline'], 23 | 'operator-linebreak': ['error', 'before'], 24 | semi: ['error', 'never'], 25 | }, 26 | } 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | .npmrc 4 | dist 5 | coverage 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | 15 | # Editor directories and files 16 | .idea 17 | .vscode 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | *.sw? 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 思维导图Vue2组件 ![npm](https://img.shields.io/npm/v/@hellowuxin/mindmap) ![npm](https://img.shields.io/npm/dm/@hellowuxin/mindmap) 4 | 5 | > 一个由[MindNode](https://mindnode.com)启发的思维导图Vue组件,基于d3.js实现 6 | > 目前实现的功能有基本的编辑、拖移、缩放、撤销、上下文菜单、折叠... 7 | 8 | ## 近期更新 9 | 10 | > 该项目基本不会再维护 11 | > 目前正在开发Vue3、d3v6版本的[思维导图组件](https://github.com/hellowuxin/vue3-mindmap),欢迎支持 12 | 13 | ## 安装 14 | 15 | ```sh 16 | npm install @hellowuxin/mindmap 17 | ``` 18 | 19 | ## PROPS 20 | 21 | | Name | Type | Default | Description | 22 | | --- | --- | --- | --- | 23 | | v-model | Array | undefined | 设置思维导图数据 | 24 | | width | Number | 100% | 设置组件宽度 | 25 | | height | Number | undefined | 设置组件高度 | 26 | | xSpacing | Number | 80 | 设置节点横向间隔 | 27 | | ySpacing | Number | 20 | 设置节点纵向间隔 | 28 | | strokeWidth | Number | 4 | 设置连线的宽度 | 29 | | draggable | Boolean| true | 设置节点是否可拖拽 | 30 | | gps | Boolean| true | 是否显示居中按钮 | 31 | | fitView | Boolean| true | 是否显示缩放按钮 | 32 | | showNodeAdd | Boolean| true | 是否显示添加节点按钮 | 33 | | keyboard | Boolean| true | 是否响应键盘事件 | 34 | | contextMenu | Boolean| true | 是否响应右键菜单 | 35 | | zoomable | Boolean| true | 是否可缩放、拖移 | 36 | | showUndo | Boolean| true | 是否显示撤销重做按钮 | 37 | | download | Boolean| true | 是否显示下载按钮 | 38 | 39 | ## EVENTS 40 | 41 | | Name | arguments | Description | 42 | | --- | --- | --- | 43 | | updateNodeName | data, id | 更新节点名称时,传入节点数据和节点id | 44 | | click | data, id | 点击节点时,传入节点数据和节点id | 45 | 46 | ## 样例 47 | 48 | ```html 49 | 52 | 53 | 86 | ``` 87 | 88 | ## 键盘事件 89 | 90 | ⇥ tab⏎ enter⌫ backspace⌘ cmd+z⌘ cmd+y 91 | 92 | ## 交互逻辑 93 | 94 | **鼠标**:space+左键移动、右键菜单、ctrl+滚轮缩放、左键选中 95 | 96 | **触控板**:双指滚动移动、双指菜单、双指捏合缩放、单指选中 97 | 98 | ## 待解决 99 | 100 | - [ ] 导出多种格式 101 | - [ ] 设置节点的宽高 102 | - [ ] 多个根节点 103 | - [ ] ... 104 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@hellowuxin/mindmap", 3 | "version": "2.1.4", 4 | "description": "Mindmap Vue Component", 5 | "author": "伍鑫", 6 | "scripts": { 7 | "serve": "vue-cli-service serve", 8 | "build": "vue-cli-service build", 9 | "test:unit": "vue-cli-service test:unit", 10 | "lint": "vue-cli-service lint", 11 | "build-lib": "vue-cli-service build --target lib --name mindmap ./src/components/MindMap.vue", 12 | "test": "jest" 13 | }, 14 | "main": "./dist/mindmap.umd.min.js", 15 | "files": [ 16 | "dist" 17 | ], 18 | "dependencies": { 19 | "d3-drag": "^1.2.5", 20 | "d3-ease": "^1.0.6", 21 | "d3-flextree": "^2.1.1", 22 | "d3-scale": "^3.2.1", 23 | "d3-scale-chromatic": "^1.5.0", 24 | "d3-selection": "^1.4.2", 25 | "d3-shape": "^1.3.7", 26 | "d3-transition": "^1.3.2", 27 | "d3-zoom": "^1.8.3" 28 | }, 29 | "devDependencies": { 30 | "@mdi/font": "^5.3.45", 31 | "@types/d3-interpolate": "^1.3.1", 32 | "@types/d3-drag": "^1.2.3", 33 | "@types/d3-ease": "^1.0.9", 34 | "@types/d3-scale": "^2.2.0", 35 | "@types/d3-scale-chromatic": "^1.5.0", 36 | "@types/d3-shape": "^1.3.2", 37 | "@types/d3-transition": "^1.1.6", 38 | "@types/resize-observer-browser": "^0.1.3", 39 | "@typescript-eslint/eslint-plugin": "^3.8.0", 40 | "@typescript-eslint/parser": "^3.8.0", 41 | "@vue/cli-plugin-babel": "^4.4.6", 42 | "@vue/cli-plugin-eslint": "^4.4.6", 43 | "@vue/cli-plugin-typescript": "^4.4.6", 44 | "@vue/cli-service": "^4.4.6", 45 | "@vue/eslint-config-typescript": "^5.0.2", 46 | "@vue/test-utils": "^1.0.3", 47 | "babel-core": "^7.0.0-bridge.0", 48 | "babel-eslint": "^10.1.0", 49 | "babel-jest": "^26.1.0", 50 | "eslint": "^7.6.0", 51 | "eslint-config-standard": "^14.1.1", 52 | "eslint-plugin-import": "^2.22.0", 53 | "eslint-plugin-node": "^11.1.0", 54 | "eslint-plugin-promise": "^4.2.1", 55 | "eslint-plugin-standard": "^4.0.1", 56 | "eslint-plugin-vue": "^6.2.2", 57 | "jest": "^26.1.0", 58 | "sass": "^1.26.10", 59 | "sass-loader": "^9.0.2", 60 | "typescript": "~3.9.7", 61 | "vue": "^2.6.11", 62 | "vue-class-component": "^7.2.5", 63 | "vue-cli-plugin-vuetify": "^2.0.7", 64 | "vue-jest": "^3.0.6", 65 | "vue-property-decorator": "^9.0.0", 66 | "vue-template-compiler": "^2.6.11", 67 | "vuetify": "^2.3.6", 68 | "vuetify-loader": "^1.6.0" 69 | }, 70 | "eslintConfig": { 71 | "root": true, 72 | "env": { 73 | "node": true 74 | }, 75 | "extends": [ 76 | "plugin:vue/essential", 77 | "eslint:recommended", 78 | "@vue/typescript" 79 | ], 80 | "rules": {}, 81 | "parserOptions": { 82 | "parser": "@typescript-eslint/parser" 83 | }, 84 | "overrides": [ 85 | { 86 | "files": [ 87 | "**/__tests__/*.{j,t}s?(x)", 88 | "**/tests/unit/**/*.spec.{j,t}s?(x)" 89 | ], 90 | "env": { 91 | "mocha": true 92 | } 93 | } 94 | ] 95 | }, 96 | "browserslist": [ 97 | "> 1%", 98 | "last 2 versions" 99 | ], 100 | "jest": { 101 | "collectCoverage": true, 102 | "collectCoverageFrom": [ 103 | "**/*.{js,vue}", 104 | "!**/node_modules/**" 105 | ], 106 | "coverageReporters": [ 107 | "html", 108 | "text-summary" 109 | ], 110 | "moduleFileExtensions": [ 111 | "js", 112 | "json", 113 | "vue" 114 | ], 115 | "transform": { 116 | ".*\\.(vue)$": "vue-jest", 117 | "^.+\\.js$": "/node_modules/babel-jest" 118 | } 119 | }, 120 | "bugs": { 121 | "url": "https://github.com/hellowuxin/mindmap/issues" 122 | }, 123 | "homepage": "https://github.com/hellowuxin/mindmap#readme", 124 | "keywords": [ 125 | "mindmap", 126 | "vue", 127 | "d3" 128 | ], 129 | "license": "ISC", 130 | "repository": { 131 | "type": "git", 132 | "url": "git+https://github.com/hellowuxin/mindmap.git" 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /public/icons/24px/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellowuxin/mindmap/3723a44c54d87bae3832e7a4c1c1982755d5de0e/public/icons/24px/close.png -------------------------------------------------------------------------------- /public/icons/24px/crosshairs-gps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellowuxin/mindmap/3723a44c54d87bae3832e7a4c1c1982755d5de0e/public/icons/24px/crosshairs-gps.png -------------------------------------------------------------------------------- /public/icons/24px/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellowuxin/mindmap/3723a44c54d87bae3832e7a4c1c1982755d5de0e/public/icons/24px/download.png -------------------------------------------------------------------------------- /public/icons/24px/fit-to-page-outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellowuxin/mindmap/3723a44c54d87bae3832e7a4c1c1982755d5de0e/public/icons/24px/fit-to-page-outline.png -------------------------------------------------------------------------------- /public/icons/24px/redo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellowuxin/mindmap/3723a44c54d87bae3832e7a4c1c1982755d5de0e/public/icons/24px/redo.png -------------------------------------------------------------------------------- /public/icons/24px/undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellowuxin/mindmap/3723a44c54d87bae3832e7a4c1c1982755d5de0e/public/icons/24px/undo.png -------------------------------------------------------------------------------- /public/icons/36px/code-json.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellowuxin/mindmap/3723a44c54d87bae3832e7a4c1c1982755d5de0e/public/icons/36px/code-json.png -------------------------------------------------------------------------------- /public/icons/36px/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellowuxin/mindmap/3723a44c54d87bae3832e7a4c1c1982755d5de0e/public/icons/36px/image.png -------------------------------------------------------------------------------- /public/icons/36px/markdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellowuxin/mindmap/3723a44c54d87bae3832e7a4c1c1982755d5de0e/public/icons/36px/markdown.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | d3-网页思维导图 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /public/learn.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name":"如何学习D3", 4 | "children": 5 | [ 6 | { 7 | "name":"预备知识", 8 | "children": [ 9 | { "name":"HTML & CSS" }, 10 | { "name":"JavaScript" }, 11 | { "name":"DOM" }, 12 | { "name":"SVG" }, 13 | { "name":"test" } 14 | ] 15 | }, 16 | { 17 | "name":"安装", 18 | "_children": [ 19 | { "name": "折叠节点" } 20 | ] 21 | }, 22 | { 23 | "name":"入门", 24 | "children":[ 25 | { "name":"选择集" }, 26 | { "name":"test" }, 27 | { "name":"绑定数据" }, 28 | { "name":"添加删除元素" }, 29 | { 30 | "name":"简单图形", 31 | "children": 32 | [ 33 | { "name":"柱形图" }, 34 | { "name":"折线图" }, 35 | { "name":"散点图" }] 36 | }, 37 | { "name":"比例尺" }, 38 | { "name":"生成器" }, 39 | { "name":"过渡" } 40 | ], 41 | "left": true 42 | }, 43 | { 44 | "name":"进阶", 45 | "left": true 46 | }, 47 | { 48 | "name":"一级节点", 49 | "children": [ 50 | { "name":"子节点1" }, 51 | { "name":"子节点2" }, 52 | { "name":"子节点3" } 53 | ] 54 | } 55 | ] 56 | } 57 | ] -------------------------------------------------------------------------------- /public/mindmap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellowuxin/mindmap/3723a44c54d87bae3832e7a4c1c1982755d5de0e/public/mindmap.jpg -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 95 | 96 | 135 | 136 | 139 | -------------------------------------------------------------------------------- /src/components/MindMap.vue: -------------------------------------------------------------------------------- 1 | 77 | 78 | 1059 | 1060 | 1063 | -------------------------------------------------------------------------------- /src/components/Outline.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 144 | 145 | -------------------------------------------------------------------------------- /src/css/MindMap.scss: -------------------------------------------------------------------------------- 1 | $seleColor: rgba($color: blue, $alpha: 0.15); 2 | $strokeWidths: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10; 3 | $minTextWidth: 16px; 4 | $minTextHeight: 21px; 5 | 6 | button:focus { outline: none; } 7 | 8 | button.icon { 9 | position: relative; 10 | cursor: pointer; 11 | width: 36px; 12 | height: 36px; 13 | border-radius: 50%; 14 | background-repeat: no-repeat; 15 | background-color: transparent; 16 | display: flex; 17 | align-items: center; 18 | justify-content: center; 19 | padding: 0; 20 | border: 0; 21 | color: #3f51b5; 22 | 23 | &::before { 24 | background-color: currentColor; 25 | border-radius: inherit; 26 | bottom: 0; 27 | color: inherit; 28 | content: ""; 29 | left: 0; 30 | opacity: 0; 31 | pointer-events: none; 32 | position: absolute; 33 | right: 0; 34 | top: 0; 35 | transition: opacity 0.2s cubic-bezier(0.4, 0, 0.6, 1); 36 | } 37 | 38 | &:hover::before { opacity: 0.1; } 39 | 40 | &.disabled { 41 | cursor: default; 42 | &:hover::before { opacity: 0; } 43 | } 44 | 45 | i { 46 | width: 24px; 47 | height: 24px; 48 | 49 | &.gps { background-image: url(../../public/icons/24px/crosshairs-gps.png); } 50 | &.fitView { background-image: url(../../public/icons/24px/fit-to-page-outline.png); } 51 | &.download { background-image: url(../../public/icons/24px/download.png); } 52 | &.undo { background-image: url(../../public/icons/24px/undo.png); } 53 | &.redo { background-image: url(../../public/icons/24px/redo.png); } 54 | &.close { background-image: url(../../public/icons/24px/close.png); } 55 | } 56 | } 57 | 58 | div#mindmap { 59 | font-size: 14px; 60 | position: relative; 61 | display: flex; 62 | 63 | div.rightClickTrigger { 64 | position: absolute; 65 | width: 100%; 66 | height: 100% 67 | } 68 | 69 | div#dummy { 70 | div { 71 | white-space:pre-wrap; 72 | width: max-content; 73 | } 74 | } 75 | 76 | svg { 77 | flex: auto; 78 | outline: none; 79 | background-color: rgb(238, 238, 243); 80 | 81 | &.grab { cursor: grab; } 82 | 83 | foreignObject { 84 | cursor: default; 85 | border-radius: 3px; 86 | border: 2px solid transparent; 87 | 88 | &:focus { outline: none; } 89 | 90 | div { 91 | text-align: left; 92 | box-sizing: content-box; 93 | border: 1px solid transparent; 94 | width: max-content; 95 | min-width: $minTextWidth; 96 | min-height: $minTextHeight; 97 | white-space: pre-wrap; 98 | color: rgb(109, 109, 109); 99 | 100 | &:focus { 101 | border-color: rgb(154, 154, 154); 102 | outline: none; 103 | } 104 | } 105 | } 106 | 107 | g.depth_0.node > foreignObject { 108 | background-color: white; 109 | border-radius: 5px; 110 | 111 | div { 112 | color: rgb(75, 75, 75); 113 | } 114 | } 115 | 116 | g.gButton { 117 | opacity: 0; 118 | > { 119 | path { 120 | fill: #8685FF; 121 | } 122 | rect { 123 | fill: white; 124 | stroke: grey; 125 | stroke-width: 0.5; 126 | } 127 | } 128 | } 129 | 130 | g.gEllipsis { 131 | opacity: 0; 132 | 133 | &.show { opacity: 1;} 134 | circle { 135 | fill: black; 136 | } 137 | &:hover { 138 | > rect.btn { 139 | stroke: #808080; 140 | fill: white 141 | } 142 | 143 | circle { 144 | fill: #5A5AD2; 145 | } 146 | } 147 | } 148 | 149 | @each $sw in $strokeWidths { 150 | &.stroke-width-#{$sw} { 151 | path { 152 | stroke-width: $sw; 153 | } 154 | } 155 | } 156 | 157 | path { 158 | fill: none; 159 | stroke-linecap: round; 160 | } 161 | 162 | #selectedNode:not(.depth_0) > foreignObject { 163 | background-color: $seleColor; 164 | } 165 | 166 | #selectedNode.depth_0 > foreignObject { 167 | outline: 3px solid; 168 | outline-color: $seleColor; 169 | } 170 | 171 | .multiSelectedNode:not(.depth_0) > foreignObject { 172 | background-color: $seleColor; 173 | } 174 | 175 | .multiSelectedNode.depth_0 > foreignObject { 176 | outline: 3px solid; 177 | outline-color: $seleColor; 178 | } 179 | 180 | #newParentNode > foreignObject { 181 | border-color: $seleColor; 182 | } 183 | 184 | #editing > foreignObject > div { 185 | background-color: white; 186 | } 187 | 188 | #selectedBox { 189 | color: #393936; 190 | opacity: 0.1; 191 | stroke: black; 192 | stroke-width: 2; 193 | } 194 | } 195 | 196 | #menu { 197 | position: absolute; 198 | border-radius: 4px; 199 | box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.2), 200 | 0px 8px 10px 1px rgba(0, 0, 0, 0.14), 201 | 0px 3px 14px 2px rgba(0, 0, 0, 0.12); 202 | background-color: #EAE9ED; 203 | padding: 4px 0; 204 | font-weight: 500; 205 | color: #3A353D; 206 | 207 | &:focus { 208 | outline: none; 209 | } 210 | 211 | .menu-item { 212 | position: relative; 213 | padding: 0px 20px; 214 | cursor: pointer; 215 | 216 | &::before { 217 | background-color: black; 218 | bottom: 0; 219 | content: ""; 220 | left: 0; 221 | opacity: 0; 222 | pointer-events: none; 223 | position: absolute; 224 | right: 0; 225 | top: 0; 226 | transition: 0.3s cubic-bezier(0.25, 0.8, 0.5, 1); 227 | } 228 | 229 | &:not(.disabled):hover::before { 230 | opacity: 0.09; 231 | } 232 | 233 | &.disabled { 234 | color: #AEB2B5; 235 | cursor: not-allowed; 236 | } 237 | } 238 | } 239 | 240 | div.buttonList { 241 | position: absolute; 242 | 243 | &.right-bottom { bottom: 0; right: 0; } 244 | &.top-right { top: 0; right: 0; display: flex; flex-direction: row; } 245 | 246 | i { filter: invert(25%) sepia(40%) saturate(5050%) hue-rotate(227deg) brightness(78%) contrast(74%); } 247 | 248 | button.icon.disabled { 249 | i { filter: invert(85%) sepia(20%) saturate(0%) hue-rotate(125deg) brightness(86%) contrast(93%); } 250 | } 251 | } 252 | 253 | div.pop-ups { 254 | position: absolute; 255 | left: 0; 256 | top: 0; 257 | bottom: 0; 258 | right: 0; 259 | 260 | display: flex; 261 | align-items: center; 262 | justify-content: center; 263 | 264 | div.layer { 265 | position: absolute; 266 | left: 0; 267 | top: 0; 268 | bottom: 0; 269 | right: 0; 270 | 271 | opacity: 0.46; 272 | background-color: rgb(33, 33, 33); 273 | } 274 | 275 | .content { 276 | position: relative; 277 | box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.2), 278 | 0px 8px 10px 1px rgba(0, 0, 0, 0.14), 279 | 0px 3px 14px 2px rgba(0, 0, 0, 0.12); 280 | 281 | div.exportTo { 282 | background-color: #ECECEC; 283 | border-radius: 4px; 284 | width: min-content; 285 | 286 | .optionList { 287 | padding: 5px; 288 | background-color: white; 289 | border-top-left-radius: inherit; 290 | border-top-right-radius: inherit; 291 | display: flex; 292 | 293 | .option { 294 | cursor: pointer; 295 | display: flex; 296 | flex-direction: column; 297 | justify-content: center; 298 | align-items: center; 299 | width: 84px; 300 | height: 84px; 301 | border-radius: 4px; 302 | color: #747474; 303 | 304 | &.select { background-color: #E8E8E8; } 305 | &.disabled { 306 | cursor: not-allowed; 307 | .icon { background-color: rgba(0,0,0,.12)!important; } 308 | } 309 | 310 | .icon { 311 | padding: 2px; 312 | border-radius: 6px; 313 | margin-bottom: 10px; 314 | 315 | &.purpleOpt { background-color: #C38EFC; } 316 | &.greenOpt { background-color: #4BD964; } 317 | &.grassOpt { background-color: #97D439; } 318 | 319 | i { 320 | display: block; 321 | width: 36px; 322 | height: 36px; 323 | 324 | &.code-json { background-image: url(../../public/icons/36px/code-json.png); } 325 | &.image { background-image: url(../../public/icons/36px/image.png); } 326 | &.markdown { background-image: url(../../public/icons/36px/markdown.png); } 327 | } 328 | } 329 | 330 | .text { 331 | font-size: 12px; 332 | } 333 | } 334 | } 335 | 336 | .optionTip { 337 | padding: 10px 30px; 338 | border-top: 1px solid #DDDDDE; 339 | border-bottom: 1px solid #DDDDDE; 340 | } 341 | 342 | .action { 343 | padding: 10px; 344 | display: flex; 345 | 346 | .spacer { 347 | flex-grow: 1; 348 | } 349 | 350 | button { 351 | height: 24px; 352 | width: 64px; 353 | margin: 0 5px; 354 | background-color: #3C89FD; 355 | color: white; 356 | border-radius: 4px; 357 | 358 | &.cancel { 359 | background-color: white; 360 | color: black; 361 | } 362 | } 363 | } 364 | } 365 | } 366 | } 367 | } -------------------------------------------------------------------------------- /src/index.d.ts: -------------------------------------------------------------------------------- 1 | interface Data { 2 | name: string 3 | children?: Array 4 | _children?: Array 5 | left?: boolean 6 | } 7 | 8 | interface Mdata { 9 | name: string 10 | id: string 11 | color: string 12 | gKey: number 13 | size: number[] 14 | children?: Array 15 | _children?: Array 16 | left: boolean 17 | } 18 | 19 | interface FlexNode { 20 | children: FlexNode[] 21 | data: Mdata 22 | depth: number 23 | dx: number 24 | dy: number 25 | height: number 26 | length: number 27 | parent: FlexNode | null 28 | x: number 29 | y: number 30 | each: Function 31 | size: number[] 32 | px: number 33 | py: number 34 | } 35 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import vuetify from './plugins/vuetify' 4 | 5 | Vue.config.productionTip = false 6 | 7 | new Vue({ 8 | vuetify, 9 | render: h => h(App), 10 | }).$mount('#app') 11 | -------------------------------------------------------------------------------- /src/plugins/vuetify.ts: -------------------------------------------------------------------------------- 1 | import '@mdi/font/css/materialdesignicons.css' 2 | import Vue from 'vue' 3 | import Vuetify from 'vuetify/lib' 4 | 5 | Vue.use(Vuetify) 6 | 7 | export default new Vuetify({ 8 | icons: { 9 | iconfont: 'mdi', 10 | }, 11 | }) 12 | -------------------------------------------------------------------------------- /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/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import Vue from 'vue' 3 | export default Vue 4 | } 5 | -------------------------------------------------------------------------------- /src/ts/History.ts: -------------------------------------------------------------------------------- 1 | class History { 2 | maxSnapshots: number 3 | snapshots: Array 4 | cursor: number 5 | constructor(maxSnapshots = 20) { 6 | this.maxSnapshots = maxSnapshots 7 | this.snapshots = [] 8 | this.cursor = -1 9 | } 10 | 11 | get canUndo() { return this.cursor > 0 } 12 | get canClear() { return this.snapshots.length >= 0 } 13 | get canRedo() { return this.snapshots.length > this.cursor + 1 } 14 | 15 | record(snapshot: Mdata) { // 记录数据快照 16 | while (this.cursor < this.snapshots.length - 1) { // 去除旧分支 17 | this.snapshots.pop() 18 | } 19 | this.snapshots.push(snapshot) 20 | // 确保历史记录条数限制 21 | if (this.snapshots.length > this.maxSnapshots) { this.snapshots.shift() } 22 | this.cursor = this.snapshots.length - 1 23 | } 24 | 25 | undo() { 26 | if (this.canUndo) { 27 | this.cursor -= 1 28 | return this.snapshots[this.cursor] 29 | } 30 | return null 31 | } 32 | 33 | redo() { 34 | if (this.canRedo) { 35 | this.cursor += 1 36 | return this.snapshots[this.cursor] 37 | } 38 | return null 39 | } 40 | 41 | move(cursor: number) { 42 | if (this.snapshots.length > cursor) { 43 | this.cursor = cursor 44 | return this.snapshots[this.cursor] 45 | } 46 | } 47 | 48 | clear() { 49 | this.cursor = -1 50 | this.snapshots = [] 51 | } 52 | } 53 | 54 | export default History 55 | -------------------------------------------------------------------------------- /src/ts/ImData.ts: -------------------------------------------------------------------------------- 1 | import * as d3ScaleChromatic from 'd3-scale-chromatic' 2 | import * as d3Scale from 'd3-scale' 3 | 4 | const colorScale = d3Scale.scaleOrdinal(d3ScaleChromatic.schemePaired) // 颜色列表 5 | let colorNumber = 0 6 | let size: Function // 生成size的函数 7 | let gKey = 0 8 | 9 | function initColor(d: Mdata, c?: string) { // 初始化颜色 10 | let color 11 | if (d.id !== '0') { 12 | color = c || colorScale(`${colorNumber += 1}`) 13 | d.color = color 14 | } 15 | const { children, _children } = d 16 | if (children) { 17 | for (let i = 0; i < children.length; i += 1) { 18 | initColor(children[i], color) 19 | } 20 | } 21 | if (_children) { 22 | for (let i = 0; i < _children.length; i += 1) { 23 | initColor(_children[i], color) 24 | } 25 | } 26 | } 27 | 28 | function initSize(d: Mdata) { // 初始化size 29 | d.size = size(d.name, d.id === '0') 30 | const { children, _children } = d 31 | if (children) { 32 | for (let i = 0; i < children.length; i += 1) { 33 | initSize(children[i]) 34 | } 35 | } 36 | if (_children) { 37 | for (let i = 0; i < _children.length; i += 1) { 38 | initSize(_children[i]) 39 | } 40 | } 41 | } 42 | 43 | function _getSource(d: Mdata) { // 返回源数据 44 | const { children, _children } = d 45 | const nd: Data = { name: d.name } 46 | nd.left = d.left 47 | if (children) { 48 | const { length } = children 49 | nd.children = new Array(length) 50 | for (let i = 0; i < length; i++) { 51 | nd.children[i] = _getSource(children[i]) 52 | } 53 | } 54 | if (_children) { 55 | const { length } = _children 56 | nd._children = new Array(length) 57 | for (let i = 0; i < length; i++) { 58 | nd._children[i] = _getSource(_children[i]) 59 | } 60 | } 61 | return nd 62 | } 63 | 64 | function initId(d: Mdata, id = '0') { // 初始化唯一标识:待优化 65 | d.id = id 66 | d.gKey = d.gKey || (gKey += 1) 67 | const { children, _children } = d 68 | 69 | if (children?.length && _children?.length) { 70 | console.error('[Mindmap warn]: Error in data: data.children and data._children cannot contain data at the same time') 71 | } else { 72 | if (children) { 73 | for (let i = 0; i < children.length;) { 74 | if (children[i].id === 'del') { 75 | children.splice(i, 1) 76 | } else { 77 | initId(children[i], `${id}-${i}`) 78 | i += 1 79 | } 80 | } 81 | } 82 | if (_children) { 83 | for (let i = 0; i < _children.length;) { 84 | if (_children[i].id === 'del') { 85 | _children.splice(i, 1) 86 | } else { 87 | initId(_children[i], `${id}-${i}`) 88 | i += 1 89 | } 90 | } 91 | } 92 | } 93 | } 94 | 95 | function initLeft(d: Mdata, left = false) { 96 | d.left = left 97 | const { children, _children } = d 98 | if (children) { 99 | for (let i = 0; i < children.length; i += 1) { 100 | initLeft(children[i], d.left) 101 | } 102 | } 103 | if (_children) { 104 | for (let i = 0; i < _children.length; i += 1) { 105 | initLeft(_children[i], d.left) 106 | } 107 | } 108 | } 109 | 110 | class ImData { 111 | data: Mdata 112 | constructor(d: Data, fn: Function) { 113 | size = fn 114 | this.data = JSON.parse(JSON.stringify(d)) 115 | initId(this.data) 116 | initColor(this.data) 117 | initSize(this.data) 118 | 119 | this.data.left = false 120 | const { children, _children } = this.data 121 | if (children) { 122 | for (let i = 0; i < children.length; i += 1) { 123 | initLeft(children[i], children[i].left) 124 | } 125 | } 126 | if (_children) { 127 | for (let i = 0; i < _children.length; i += 1) { 128 | initLeft(_children[i], _children[i].left) 129 | } 130 | } 131 | } 132 | 133 | getSource(id = '0') { 134 | const d = this.find(id) 135 | return d ? _getSource(d) : { name: '' } 136 | } 137 | 138 | resize(id = '0') { // 更新size 139 | const d = this.find(id) 140 | if (d) { 141 | initSize(d) 142 | } 143 | } 144 | 145 | find(id: string) { // 根据id找到数据 146 | const array = id.split('-').map(n => ~~n) 147 | let data = this.data 148 | for (let i = 1; i < array.length; i++) { 149 | if (data && data.children) { 150 | data = data.children[array[i]] 151 | } else { // No data matching id 152 | return null 153 | } 154 | } 155 | return data 156 | } 157 | 158 | rename(id: string, name: string) { // 修改名称 159 | if (id.length > 0) { 160 | const d = this.find(id) 161 | if (d) { 162 | d.name = name 163 | d.size = size(name, d.id === '0') 164 | } 165 | return d 166 | } 167 | } 168 | 169 | collapse(id: string | string[]) { // 折叠 170 | const arr = Array.isArray(id) ? id : [id] 171 | for (let i = 0; i < arr.length; i++) { 172 | const idChild = arr[i] 173 | const d = this.find(idChild) 174 | if (d && (!d._children || d._children.length === 0)) { 175 | d._children = d.children 176 | d.children = [] 177 | } 178 | } 179 | } 180 | 181 | expand(id: string | string[]) { // 展开 182 | const arr = Array.isArray(id) ? id : [id] 183 | for (let i = 0; i < arr.length; i++) { 184 | const idChild = arr[i] 185 | const d = this.find(idChild) 186 | if (d && (!d.children || d.children.length === 0)) { 187 | d.children = d._children 188 | d._children = [] 189 | } 190 | } 191 | } 192 | 193 | del(id: string | string[]) { // 删除指定id的数据 194 | const arr = Array.isArray(id) ? id : [id] 195 | let p 196 | for (let i = 0; i < arr.length; i++) { 197 | const idChild = arr[i] 198 | const idArr = idChild.split('-') 199 | if (idArr.length >= 2) { // 有parent 200 | const delIndex = idArr.pop() 201 | const parent = this.find(idArr.join('-')) 202 | if (delIndex && parent) { 203 | if (parent.children) { 204 | parent.children[~~delIndex].id = 'del' // 更新id时删除 205 | } 206 | if (p === undefined || (p.id.split('-').length > parent.id.split('-').length)) { // 找出最高的parent 207 | p = parent 208 | } 209 | } 210 | } 211 | } 212 | if (p) { 213 | initId(p, p.id) 214 | } 215 | } 216 | 217 | add(id: string, child: Data) { // 添加新的子节点 218 | if (id.length > 0) { 219 | const parent = this.find(id) 220 | if (parent) { 221 | if ((parent._children?.length || 0) > 0) { // 判断是否折叠,如果折叠,展开 222 | parent.children = parent._children 223 | parent._children = [] 224 | } 225 | const c: Mdata = JSON.parse(JSON.stringify(child)) 226 | parent.children ? parent.children.push(c) : parent.children = [c] 227 | initColor(c, parent.color || colorScale(`${colorNumber += 1}`)) 228 | initId(c, `${parent.id}-${parent.children.length - 1}`) 229 | c.left = parent.left 230 | initSize(c) 231 | return c 232 | } 233 | } 234 | } 235 | 236 | insert(id: string, d: Data, i = 0) { // 插入新的节点在前(或在后) 237 | if (id.length > 2) { 238 | const idArr = id.split('-') 239 | const bId = idArr.pop() 240 | const pId = idArr.join('-') 241 | const parent = this.find(pId) 242 | if (bId && parent) { 243 | const c: Mdata = JSON.parse(JSON.stringify(d)) 244 | const pChildren = parent.children 245 | if (pChildren) { 246 | pChildren.splice(~~bId + i, 0, c) 247 | c.left = pChildren[~~bId].left 248 | } 249 | initColor(c, parent.color || colorScale(`${colorNumber += 1}`)) 250 | initId(parent, parent.id) 251 | initSize(c) 252 | return c 253 | } 254 | } 255 | } 256 | 257 | move(delId: string, insertId?: string, i = 0) { // 节点在同层移动 258 | if (delId.length > 2) { 259 | if (!insertId) { // 左右转换 260 | const del = this.find(delId) 261 | if (del) { 262 | initLeft(del, !del.left) 263 | } 264 | } else if (insertId.length > 2) { 265 | const insert = this.find(insertId) 266 | const idArr = delId.split('-') 267 | const delIndexS = idArr.pop() 268 | const pId = idArr.join('-') 269 | const parent = this.find(pId) 270 | const insertIndexS = insertId.split('-').pop() 271 | 272 | if (delIndexS && insertIndexS && insert && parent && parent.children) { 273 | const delIndex = ~~delIndexS 274 | let insertIndex = ~~insertIndexS 275 | // 删除时可能会改变插入的序号 276 | if (delIndex < insertIndex) { 277 | insertIndex -= 1 278 | } 279 | const del = parent.children.splice(delIndex, 1)[0] 280 | if (del.left !== insert.left) { // 左右转换 281 | initLeft(del, insert.left) 282 | } 283 | parent.children.splice(insertIndex + i, 0, del) 284 | initId(parent, parent.id) 285 | } 286 | } 287 | } 288 | } 289 | 290 | reparent(parentId: string, delId: string) { // 节点移动到其他层 291 | if (delId.length > 2 && parentId.length > 0 && parentId !== delId) { 292 | const np = this.find(parentId) 293 | const idArr = delId.split('-') 294 | const delIndex = idArr.pop() 295 | const delParentId = idArr.join('-') 296 | const delParent = this.find(delParentId) 297 | if (delIndex && delParent && np) { 298 | const del = delParent.children?.splice(~~delIndex, 1)[0] // 删除 299 | if (del) { 300 | (np.children?.length || 0) > 0 ? np.children?.push(del) 301 | : ((np._children?.length || 0) > 0 ? np._children?.push(del) : np.children = [del]) 302 | 303 | initColor(del, parentId === '0' ? colorScale(`${colorNumber += 1}`) : np.color) 304 | initLeft(del, parentId === '0' ? del.left : np.left) 305 | initId(np, np.id) 306 | initId(delParent, delParent.id) 307 | } 308 | } 309 | } 310 | } 311 | } 312 | 313 | export default ImData 314 | -------------------------------------------------------------------------------- /src/ts/d3.ts: -------------------------------------------------------------------------------- 1 | export * from 'd3-transition' 2 | export * from 'd3-shape' 3 | export * from 'd3-ease' 4 | export * from 'd3-zoom' 5 | export * from 'd3-selection' 6 | export * from 'd3-drag' 7 | -------------------------------------------------------------------------------- /src/ts/toMarkdown.ts: -------------------------------------------------------------------------------- 1 | function deepTraverse(d: Array, m: string, md: string, flag: string) { 2 | for (let index = 0; index < d?.length; index += 1) { 3 | const dChild = d[index] 4 | if (m.length > 3 && m[0] === '#') { // #### 替换成 - 5 | md += `- ${dChild.name}\n` 6 | if (dChild.children) { 7 | md = deepTraverse(dChild.children, ' -', md, ' ') 8 | } 9 | } else { 10 | md += `${m} ${dChild.name}\n` 11 | if (dChild.children) { 12 | md = deepTraverse(dChild.children, `${flag}${m}`, md, flag) 13 | } 14 | } 15 | } 16 | return md 17 | } 18 | 19 | function toMarkdown(data: Data) { 20 | const d = Array.isArray(data) ? data : [data] 21 | return deepTraverse(d, '#', '', '#') 22 | } 23 | 24 | export default toMarkdown 25 | -------------------------------------------------------------------------------- /src/types/d3-zoom.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for d3JS d3-zoom module 1.7 2 | // Project: https://github.com/d3/d3-zoom/, https://d3js.org/d3-zoom 3 | // Definitions by: Tom Wanzek 4 | // Alex Ford 5 | // Boris Yankov 6 | // denisname 7 | // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped 8 | // TypeScript Version: 2.3 9 | /* eslint-disable */ 10 | // Last module patch version validated against: 1.7.0 11 | declare module 'd3-zoom' { 12 | import { ArrayLike, Selection, TransitionLike, ValueFn } from 'd3-selection'; 13 | import { ZoomView, ZoomInterpolator } from 'd3-interpolate'; 14 | 15 | // -------------------------------------------------------------------------- 16 | // Shared Type Definitions and Interfaces 17 | // -------------------------------------------------------------------------- 18 | 19 | /** 20 | * ZoomedElementBaseType serves as an alias for the 'minimal' data type which can be selected 21 | * without 'd3-zoom' (and related code in 'd3-selection') trying to use properties internally which would otherwise not 22 | * be supported. 23 | */ 24 | export type ZoomedElementBaseType = Element; 25 | 26 | /** 27 | * Minimal interface for a continuous scale. 28 | * This interface is used as a minimum contract for scale objects 29 | * that can be passed into zoomTransform methods rescaleX and rescaleY 30 | */ 31 | export interface ZoomScale { 32 | domain(): number[] | Date[]; 33 | domain(domain: Array): this; 34 | range(): number[]; 35 | range(range: number[]): this; 36 | copy(): ZoomScale; 37 | invert(value: number): number | Date; 38 | } 39 | 40 | // -------------------------------------------------------------------------- 41 | // Zoom Behavior 42 | // -------------------------------------------------------------------------- 43 | 44 | /** 45 | * A D3 Zoom Behavior 46 | * 47 | * The first generic refers to the type of reference element to which the zoom behavior is attached. 48 | * The second generic refers to the type of the datum of the reference element. 49 | */ 50 | export interface ZoomBehavior extends Function { 51 | /** 52 | * Applies this zoom behavior to the specified selection, binding the necessary event listeners to 53 | * allow panning and zooming, and initializing the zoom transform on each selected element to the identity transform if not already defined. This function is typically not invoked directly, 54 | * and is instead invoked via selection.call. 55 | * 56 | * For details see: {@link https://github.com/d3/d3-zoom#_zoom} 57 | * 58 | * @param selection A D3 selection of elements. 59 | * @param args Optional arguments to be passed in. 60 | */ 61 | (selection: Selection, ...args: any[]): void; 62 | /** 63 | * Sets the current zoom transform of the selected elements to the specified transform, 64 | * instantaneously emitting start, zoom and end events. 65 | * 66 | * This method requires that you specify the new zoom transform completely, 67 | * and does not enforce the defined scale extent and translate extent, if any. 68 | * To derive a new transform from the existing transform, and to enforce the scale and translate extents, 69 | * see the convenience methods zoom.translateBy, zoom.scaleBy and zoom.scaleTo. 70 | * 71 | * This function is typically not invoked directly, and is instead invoked via selection.call. 72 | * 73 | * @param selection A D3 selection of elements. 74 | * @param transform A zoom transform object. 75 | */ 76 | transform(selection: Selection, transform: ZoomTransform): void; 77 | /** 78 | * Sets the current zoom transform of the selected elements to the transform returned by the specified 79 | * zoom transform factory function evaluated for each element, instantaneously emitting start, zoom and end events. 80 | * 81 | * This method requires that you specify the new zoom transform completely, 82 | * and does not enforce the defined scale extent and translate extent, if any. 83 | * To derive a new transform from the existing transform, and to enforce the scale and translate extents, 84 | * see the convenience methods zoom.translateBy, zoom.scaleBy and zoom.scaleTo. 85 | * 86 | * This function is typically not invoked directly, and is instead invoked via selection.call. 87 | * 88 | * @param selection A D3 selection of elements. 89 | * @param transform A zoom transform factory function which is evaluated for each selected element, 90 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 91 | * with this as the current DOM element. The function returns a zoom transform object. 92 | */ 93 | transform(selection: Selection, transform: ValueFn): void; 94 | /** 95 | * Sets the current zoom transform of the transitioning elements to the specified transform. 96 | * It defines a “zoom” tween to the specified transform using d3.interpolateZoom, 97 | * emitting a start event when the transition starts, zoom events for each tick of the transition, 98 | * and then an end event when the transition ends (or is interrupted). 99 | * 100 | * This method requires that you specify the new zoom transform completely, 101 | * and does not enforce the defined scale extent and translate extent, if any. 102 | * To derive a new transform from the existing transform, and to enforce the scale and translate extents, 103 | * see the convenience methods zoom.translateBy, zoom.scaleBy and zoom.scaleTo. 104 | * 105 | * This function is typically not invoked directly, and is instead invoked via selection.call. 106 | * 107 | * @param transition A D3 transition on elements. 108 | * @param transform A zoom transform object. 109 | */ 110 | transform(transition: TransitionLike, transform: ZoomTransform): void; 111 | /** 112 | * Sets the current zoom transform of the transitioning elements to the transform returned by the specified 113 | * zoom transform factory function evaluated for each element. 114 | * It defines a “zoom” tween to the specified transform using d3.interpolateZoom, 115 | * emitting a start event when the transition starts, zoom events for each tick of the transition, 116 | * and then an end event when the transition ends (or is interrupted). 117 | * 118 | * This method requires that you specify the new zoom transform completely, 119 | * and does not enforce the defined scale extent and translate extent, if any. 120 | * To derive a new transform from the existing transform, and to enforce the scale and translate extents, 121 | * see the convenience methods zoom.translateBy, zoom.scaleBy and zoom.scaleTo. 122 | * 123 | * This function is typically not invoked directly, and is instead invoked via selection.call. 124 | * 125 | * @param transition A D3 transition on elements. 126 | * @param transform A zoom transform factory function which is evaluated for each selected element, 127 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 128 | * with this as the current DOM element. The function returns a zoom transform object. 129 | */ 130 | transform(transition: TransitionLike, transform: ValueFn): void; 131 | 132 | /** 133 | * Translates the current zoom transform of the selected elements by x and y, 134 | * such that the new t(x1) = t(x0) + kx and t(y1) = t(y0) + ky. 135 | * 136 | * x is provided as a constant for all elements. 137 | * y is provided as a constant for all elements. 138 | * 139 | * @param selection A D3 selection of elements. 140 | * @param x Amount of translation in x-direction. 141 | * @param y Amount of translation in y-direction. 142 | */ 143 | translateBy(selection: Selection, x: number, y: number): void; 144 | /** 145 | * Translates the current zoom transform of the selected elements by x and y, 146 | * such that the new t(x1) = t(x0) + kx and t(y1) = t(y0) + ky. 147 | * 148 | * x is provided by a value function evaluated for each element in the selection. 149 | * y is provided as a constant for all elements. 150 | * 151 | * This method is a convenience method for zoom.transform. 152 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 153 | * 154 | * @param selection A D3 selection of elements. 155 | * @param x A value function which is evaluated for each selected element, 156 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 157 | * with this as the current DOM element.The function returns the amount of translation in x-direction. 158 | * @param y Amount of translation in y-direction. 159 | */ 160 | translateBy(selection: Selection, x: ValueFn, y: number): void; 161 | /** 162 | * Translates the current zoom transform of the selected elements by x and y, 163 | * such that the new t(x1) = t(x0) + kx and t(y1) = t(y0) + ky. 164 | * 165 | * x is provided as a constant for all elements. 166 | * y is provided by a value function evaluated for each element in the selection. 167 | * 168 | * This method is a convenience method for zoom.transform. 169 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 170 | * 171 | * @param selection A D3 selection of elements. 172 | * @param x Amount of translation in x-direction. 173 | * @param y A value function which is evaluated for each selected element, 174 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 175 | * with this as the current DOM element.The function returns the amount of translation in y-direction. 176 | */ 177 | translateBy(selection: Selection, x: number, y: ValueFn): void; 178 | /** 179 | * Translates the current zoom transform of the selected elements by x and y, 180 | * such that the new t(x1) = t(x0) + kx and t(y1) = t(y0) + ky. 181 | * 182 | * x is provided by a value function evaluated for each element in the selection. 183 | * y is provided by a value function evaluated for each element in the selection. 184 | * 185 | * This method is a convenience method for zoom.transform. 186 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 187 | * 188 | * @param selection A D3 selection of elements. 189 | * @param x A value function which is evaluated for each selected element, 190 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 191 | * with this as the current DOM element.The function returns the amount of translation in x-direction. 192 | * @param y A value function which is evaluated for each selected element, 193 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 194 | * with this as the current DOM element.The function returns the amount of translation in y-direction. 195 | */ 196 | translateBy(selection: Selection, x: ValueFn, y: ValueFn): void; 197 | /** 198 | * Defines a “zoom” tween translating the current transform for the transitioning elements by x and y, 199 | * such that the new t(x1) = t(x0) + kx and t(y1) = t(y0) + ky. 200 | * 201 | * x is provided as a constant for all elements. 202 | * y is provided as a constant for all elements. 203 | * 204 | * This method is a convenience method for zoom.transform. 205 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 206 | * 207 | * @param transition A D3 transition on elements. 208 | * @param x Amount of translation in x-direction. 209 | * @param y Amount of translation in y-direction. 210 | */ 211 | translateBy(transition: TransitionLike, x: number, y: number): void; 212 | /** 213 | * Defines a “zoom” tween translating the current transform for the transitioning elements by x and y, 214 | * such that the new t(x1) = t(x0) + kx and t(y1) = t(y0) + ky. 215 | * 216 | * x is provided by a value function evaluated for each element in the selection. 217 | * y is provided as a constant for all elements. 218 | * 219 | * This method is a convenience method for zoom.transform. 220 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 221 | * 222 | * @param transition A D3 transition on elements. 223 | * @param x A value function which is evaluated for each selected element, 224 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 225 | * with this as the current DOM element.The function returns the amount of translation in x-direction. 226 | * @param y Amount of translation in y-direction. 227 | */ 228 | translateBy(transition: TransitionLike, x: ValueFn, y: number): void; 229 | /** 230 | * Defines a “zoom” tween translating the current transform for the transitioning elements by x and y, 231 | * such that the new t(x1) = t(x0) + kx and t(y1) = t(y0) + ky. 232 | * 233 | * x is provided as a constant for all elements. 234 | * y is provided by a value function evaluated for each element in the selection. 235 | * 236 | * This method is a convenience method for zoom.transform. 237 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 238 | * 239 | * @param transition A D3 transition on elements. 240 | * @param x Amount of translation in x-direction. 241 | * @param y A value function which is evaluated for each selected element, 242 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 243 | * with this as the current DOM element.The function returns the amount of translation in y-direction. 244 | */ 245 | translateBy(transition: TransitionLike, x: number, y: ValueFn): void; 246 | /** 247 | * Defines a “zoom” tween translating the current transform for the transitioning elements by x and y, 248 | * such that the new t(x1) = t(x0) + kx and t(y1) = t(y0) + ky. 249 | * 250 | * x is provided by a value function evaluated for each element in the selection. 251 | * y is provided by a value function evaluated for each element in the selection. 252 | * 253 | * This method is a convenience method for zoom.transform. 254 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 255 | * 256 | * @param transition A D3 transition on elements. 257 | * @param x A value function which is evaluated for each selected element, 258 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 259 | * with this as the current DOM element.The function returns the amount of translation in x-direction. 260 | * @param y A value function which is evaluated for each selected element, 261 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 262 | * with this as the current DOM element.The function returns the amount of translation in y-direction. 263 | */ 264 | translateBy(transition: TransitionLike, x: ValueFn, y: ValueFn): void; 265 | 266 | /** 267 | * Translates the current zoom transform of the selected elements such that the specified position ⟨x,y⟩ appears at the center of the viewport extent. 268 | * The new tx = cx - kx and ty = cy - ky, where ⟨cx,cy⟩ is the center. 269 | * 270 | * x is provided as a constant for all elements. 271 | * y is provided as a constant for all elements. 272 | * 273 | * @param selection A D3 selection of elements. 274 | * @param x Target x-position of translation. 275 | * @param y Target y-position of translation. 276 | */ 277 | translateTo(selection: Selection, x: number, y: number): void; 278 | /** 279 | * Translates the current zoom transform of the selected elements such that the specified position ⟨x,y⟩ appears at the center of the viewport extent. 280 | * The new tx = cx - kx and ty = cy - ky, where ⟨cx,cy⟩ is the center. 281 | * 282 | * x is provided by a value function evaluated for each element in the selection. 283 | * y is provided as a constant for all elements. 284 | * 285 | * This method is a convenience method for zoom.transform. 286 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 287 | * 288 | * @param selection A D3 selection of elements. 289 | * @param x A value function which is evaluated for each selected element, 290 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 291 | * with this as the current DOM element.The function returns the target x-position of translation. 292 | * @param y Target y-position of translation. 293 | */ 294 | translateTo(selection: Selection, x: ValueFn, y: number): void; 295 | /** 296 | * Translates the current zoom transform of the selected elements such that the specified position ⟨x,y⟩ appears at the center of the viewport extent. 297 | * The new tx = cx - kx and ty = cy - ky, where ⟨cx,cy⟩ is the center. 298 | * 299 | * x is provided as a constant for all elements. 300 | * y is provided by a value function evaluated for each element in the selection. 301 | * 302 | * This method is a convenience method for zoom.transform. 303 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 304 | * 305 | * @param selection A D3 selection of elements. 306 | * @param x Target x-position of translation. 307 | * @param y A value function which is evaluated for each selected element, 308 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 309 | * with this as the current DOM element.The function returns the target y-position of translation. 310 | */ 311 | translateTo(selection: Selection, x: number, y: ValueFn): void; 312 | /** 313 | * Translates the current zoom transform of the selected elements such that the specified position ⟨x,y⟩ appears at the center of the viewport extent. 314 | * The new tx = cx - kx and ty = cy - ky, where ⟨cx,cy⟩ is the center. 315 | * 316 | * x is provided by a value function evaluated for each element in the selection. 317 | * y is provided by a value function evaluated for each element in the selection. 318 | * 319 | * This method is a convenience method for zoom.transform. 320 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 321 | * 322 | * @param selection A D3 selection of elements. 323 | * @param x A value function which is evaluated for each selected element, 324 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 325 | * with this as the current DOM element.The function returns the target x-position of translation. 326 | * @param y A value function which is evaluated for each selected element, 327 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 328 | * with this as the current DOM element.The function returns the target y-position of translation. 329 | */ 330 | translateTo(selection: Selection, x: ValueFn, y: ValueFn): void; 331 | /** 332 | * Defines a “zoom” tween translating the current transform for the transitioning elements such that the specified position ⟨x,y⟩ appears at the center of the viewport extent. 333 | * The new tx = cx - kx and ty = cy - ky, where ⟨cx,cy⟩ is the center. 334 | * 335 | * x is provided as a constant for all elements. 336 | * y is provided as a constant for all elements. 337 | * 338 | * This method is a convenience method for zoom.transform. 339 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 340 | * 341 | * @param transition A D3 transition on elements. 342 | * @param x Target x-position of translation. 343 | * @param y Target y-position of translation. 344 | */ 345 | translateTo(transition: TransitionLike, x: number, y: number): void; 346 | /** 347 | * Defines a “zoom” tween translating the current transform for the transitioning elements such that the specified position ⟨x,y⟩ appears at the center of the viewport extent. 348 | * The new tx = cx - kx and ty = cy - ky, where ⟨cx,cy⟩ is the center. 349 | * 350 | * x is provided by a value function evaluated for each element in the selection. 351 | * y is provided as a constant for all elements. 352 | * 353 | * This method is a convenience method for zoom.transform. 354 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 355 | * 356 | * @param transition A D3 transition on elements. 357 | * @param x A value function which is evaluated for each selected element, 358 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 359 | * with this as the current DOM element.The function returns the target x-position of translation. 360 | * @param y Target y-position of translation. 361 | */ 362 | translateTo(transition: TransitionLike, x: ValueFn, y: number): void; 363 | /** 364 | * Defines a “zoom” tween translating the current transform for the transitioning elements such that the specified position ⟨x,y⟩ appears at the center of the viewport extent. 365 | * The new tx = cx - kx and ty = cy - ky, where ⟨cx,cy⟩ is the center. 366 | * 367 | * x is provided as a constant for all elements. 368 | * y is provided by a value function evaluated for each element in the selection. 369 | * 370 | * This method is a convenience method for zoom.transform. 371 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 372 | * 373 | * @param transition A D3 transition on elements. 374 | * @param x Target x-position of translation. 375 | * @param y A value function which is evaluated for each selected element, 376 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 377 | * with this as the current DOM element.The function returns the target y-position of translation. 378 | */ 379 | translateTo(transition: TransitionLike, x: number, y: ValueFn): void; 380 | /** 381 | * Defines a “zoom” tween translating the current transform for the transitioning elements such that the specified position ⟨x,y⟩ appears at the center of the viewport extent. 382 | * The new tx = cx - kx and ty = cy - ky, where ⟨cx,cy⟩ is the center. 383 | * 384 | * x is provided by a value function evaluated for each element in the selection. 385 | * y is provided by a value function evaluated for each element in the selection. 386 | * 387 | * This method is a convenience method for zoom.transform. 388 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 389 | * 390 | * @param transition A D3 transition on elements. 391 | * @param x A value function which is evaluated for each selected element, 392 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 393 | * with this as the current DOM element.The function returns the target x-position of translation. 394 | * @param y A value function which is evaluated for each selected element, 395 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 396 | * with this as the current DOM element.The function returns the target y-position of translation. 397 | */ 398 | translateTo(transition: TransitionLike, x: ValueFn, y: ValueFn): void; 399 | 400 | /** 401 | * Scales the current zoom transform of the selected elements by k, such that the new k(1) = k(0)k. 402 | * 403 | * k is provided as a constant for all elements. 404 | * 405 | * This method is a convenience method for zoom.transform. 406 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 407 | * 408 | * @param selection A D3 selection of elements. 409 | * @param k Scale factor. 410 | */ 411 | scaleBy(selection: Selection, k: number): void; 412 | /** 413 | * Scales the current zoom transform of the selected elements by k, such that the new k(1) = k(0)k. 414 | * 415 | * k is provided by a value function evaluated for each element in the selection. 416 | * 417 | * This method is a convenience method for zoom.transform. 418 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 419 | * 420 | * @param selection A D3 selection of elements. 421 | * @param k A value function which is evaluated for each selected element, 422 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 423 | * with this as the current DOM element.The function returns the scale factor. 424 | */ 425 | scaleBy(selection: Selection, k: ValueFn): void; 426 | /** 427 | * Defines a “zoom” tween translating scaling the current transform of the selected elements by k, such that the new k(1) = k(0)k. 428 | * 429 | * k is provided as a constant for all elements. 430 | * 431 | * This method is a convenience method for zoom.transform. 432 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 433 | * 434 | * @param transition A D3 transition on elements. 435 | * @param k Scale factor. 436 | */ 437 | scaleBy(transition: TransitionLike, k: number): void; 438 | /** 439 | * Defines a “zoom” tween translating scaling the current transform of the selected elements by k, such that the new k(1) = k(0)k. 440 | * 441 | * k is provided by a value function evaluated for each element in the selection. 442 | * 443 | * This method is a convenience method for zoom.transform. 444 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 445 | * 446 | * @param transition A D3 transition on elements. 447 | * @param k A value function which is evaluated for each selected element, 448 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 449 | * with this as the current DOM element.The function returns the scale factor. 450 | */ 451 | scaleBy(transition: TransitionLike, k: ValueFn): void; 452 | 453 | /** 454 | * Scales the current zoom transform of the selected elements to k, such that the new k(1) = k. 455 | * 456 | * k is provided as a constant for all elements. 457 | * 458 | * This method is a convenience method for zoom.transform. 459 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 460 | * 461 | * @param selection A D3 selection of elements. 462 | * @param k New scale. 463 | */ 464 | scaleTo(selection: Selection, k: number, p?: number[]): void; 465 | /** 466 | * Scales the current zoom transform of the selected elements to k, such that the new k(1) = k. 467 | * 468 | * k is provided by a value function evaluated for each element in the selection. 469 | * 470 | * This method is a convenience method for zoom.transform. 471 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 472 | * 473 | * @param selection A D3 selection of elements. 474 | * @param k A value function which is evaluated for each selected element, 475 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 476 | * with this as the current DOM element.The function returns the new scale. 477 | */ 478 | scaleTo(selection: Selection, k: ValueFn): void; 479 | /** 480 | * Defines a “zoom” tween translating scaling the current transform of the selected elements to k, such that the new k(1) = k. 481 | * 482 | * k is provided as a constant for all elements. 483 | * 484 | * This method is a convenience method for zoom.transform. 485 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 486 | * 487 | * @param transition A D3 transition on elements. 488 | * @param k New scale. 489 | */ 490 | scaleTo(transition: TransitionLike, k: number): void; 491 | /** 492 | * Defines a “zoom” tween translating scaling the current transform of the selected elements to k, such that the new k(1) = k. 493 | * 494 | * k is provided by a value function evaluated for each element in the selection. 495 | * 496 | * This method is a convenience method for zoom.transform. 497 | * In contrast to zoom.transform, however, it is subject to the constraints imposed by zoom.extent, zoom.scaleExtent, and zoom.translateExtent. 498 | * 499 | * @param transition A D3 transition on elements. 500 | * @param k A value function which is evaluated for each selected element, 501 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 502 | * with this as the current DOM element.The function returns the new scale. 503 | */ 504 | scaleTo(transition: TransitionLike, k: ValueFn): void; 505 | 506 | /** 507 | * Returns the current constraint function. 508 | * The default implementation attempts to ensure that the viewport extent does not go outside the translate extent. 509 | */ 510 | constrain(): (transform: ZoomTransform, extent: [[number, number], [number, number]], translateExtent: [[number, number], [number, number]]) => ZoomTransform; 511 | /** 512 | * Sets the transform constraint function to the specified function and returns the zoom behavior. 513 | * 514 | * @param constraint A constraint function which returns a transform given the current transform, viewport extent and translate extent. 515 | * The default implementation attempts to ensure that the viewport extent does not go outside the translate extent. 516 | */ 517 | constrain(constraint: ((transform: ZoomTransform, extent: [[number, number], [number, number]], translateExtent: [[number, number], [number, number]]) => ZoomTransform)): this; 518 | 519 | /** 520 | * Returns the current filter function. 521 | */ 522 | filter(): ValueFn; 523 | /** 524 | * Sets the filter to the specified filter function and returns the zoom behavior. 525 | * The filter function is invoked in the zoom initiating event handlers of each element to which the zoom behavior was applied. 526 | * 527 | * If the filter returns falsey, the initiating event is ignored and no zoom gesture is started. 528 | * Thus, the filter determines which input events are ignored. The default filter ignores mousedown events on secondary buttons, 529 | * since those buttons are typically intended for other purposes, such as the context menu. 530 | * 531 | * @param filterFn A filter function which is invoked in the zoom initiating event handlers of each element to which the zoom behavior was applied, 532 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 533 | * with this as the current DOM element. The function returns a boolean value. 534 | */ 535 | filter(filterFn: ValueFn): this; 536 | 537 | /** 538 | * Returns the current touch support detector, which defaults to a function returning true, 539 | * if the "ontouchstart" event is supported on the current element. 540 | */ 541 | touchable(): ValueFn; 542 | /** 543 | * Sets the touch support detector to the specified boolean value and returns the zoom behavior. 544 | * 545 | * Touch event listeners are only registered if the detector returns truthy for the corresponding element when the zoom behavior is applied. 546 | * The default detector works well for most browsers that are capable of touch input, but not all; Chrome’s mobile device emulator, for example, 547 | * fails detection. 548 | * 549 | * @param touchable A boolean value. true when touch event listeners should be applied to the corresponding element, otherwise false. 550 | */ 551 | touchable(touchable: boolean): this; 552 | /** 553 | * Sets the touch support detector to the specified function and returns the zoom behavior. 554 | * 555 | * Touch event listeners are only registered if the detector returns truthy for the corresponding element when the zoom behavior is applied. 556 | * The default detector works well for most browsers that are capable of touch input, but not all; Chrome’s mobile device emulator, for example, 557 | * fails detection. 558 | * 559 | * @param touchable A touch support detector function, which returns true when touch event listeners should be applied to the corresponding element. 560 | * The function is evaluated for each selected element to which the zoom behavior was applied, in order, being passed the current datum (d), 561 | * the current index (i), and the current group (nodes), with this as the current DOM element. The function returns a boolean value. 562 | */ 563 | touchable(touchable: ValueFn): this; 564 | 565 | /** 566 | * Returns the current wheelDelta function. 567 | */ 568 | wheelDelta(): ValueFn; 569 | /** 570 | * Sets the wheel delta function to the specified function and returns the zoom behavior. The wheel delta function which is invoked in the wheel event handler 571 | * of each element to which the zoom behavior was applied. 572 | * The value Δ returned by the wheel delta function determines the amount of scaling applied in response to a WheelEvent. 573 | * The scale factor transform.k is multiplied by 2Δ; for example, a Δ of +1 doubles the scale factor, Δ of -1 halves the scale factor. 574 | * 575 | * @param delta Wheel delta function which is invoked in the wheel event handler of each element to which the zoom behavior was applied, 576 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 577 | * with this as the current DOM element. The function returns a numeric value. 578 | */ 579 | wheelDelta(delta: ValueFn): this; 580 | 581 | /** 582 | * Return the current extent accessor, which defaults to [[0, 0], [width, height]] where width is the client width of the element and height is its client height; 583 | * for SVG elements, the nearest ancestor SVG element’s width and height is used. In this case, 584 | * the owner SVG element must have defined width and height attributes rather than (for example) relying on CSS properties or the viewBox attribute; 585 | * SVG provides no programmatic method for retrieving the initial viewport size. Alternatively, consider using element.getBoundingClientRect. 586 | * (In Firefox, element.clientWidth and element.clientHeight is zero for SVG elements!) 587 | */ 588 | extent(): ValueFn; 589 | /** 590 | * Set the viewport extent to the specified array of points [[x0, y0], [x1, y1]], 591 | * where [x0, y0] is the top-left corner of the viewport and [x1, y1] is the bottom-right corner of the viewport, 592 | * and return this zoom behavior. 593 | * 594 | * The viewport extent affects several functions: the center of the viewport remains fixed during changes by zoom.scaleBy and zoom.scaleTo; 595 | * the viewport center and dimensions affect the path chosen by d3.interpolateZoom; and the viewport extent is needed to enforce the optional translate extent. 596 | * 597 | * @param extent An extent specified as an array of two coordinates. 598 | */ 599 | extent(extent: [[number, number], [number, number]]): this; 600 | /** 601 | * Set the viewport extent to the array of points [[x0, y0], [x1, y1]] returned by the 602 | * extent accessor function, and return this zoom behavior. 603 | * The extent accessor function is evaluated for each element. 604 | * 605 | * [x0, y0] is the top-left corner of the viewport and [x1, y1] is the bottom-right corner of the viewport. 606 | * 607 | * The viewport extent affects several functions: the center of the viewport remains fixed during changes by zoom.scaleBy and zoom.scaleTo; 608 | * the viewport center and dimensions affect the path chosen by d3.interpolateZoom; and the viewport extent is needed to enforce the optional translate extent. 609 | * 610 | * The default is [[0, 0], [width, height]] where width is the client width of the element and height is its client height; 611 | * for SVG elements, the nearest ancestor SVG element’s width and height is used. 612 | * In this case, the owner SVG element must have defined width and height attributes rather than (for example) relying on CSS properties or the viewBox attribute; 613 | * SVG provides no programmatic method for retrieving the initial viewport size. Alternatively, consider using element.getBoundingClientRect. 614 | * (In Firefox, element.clientWidth and element.clientHeight is zero for SVG elements!) 615 | * 616 | * @extent An extent accessor function which is evaluated for each selected element, 617 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 618 | * with this as the current DOM element.The function returns the extent array. 619 | */ 620 | extent(extent: ValueFn): this; 621 | 622 | /** 623 | * Return the current scale extent. 624 | */ 625 | scaleExtent(): [number, number]; 626 | /** 627 | * Set the scale extent to the specified array of numbers [k0, k1] where k0 is the minimum allowed scale factor and k1 is the maximum allowed scale factor, 628 | * and return this zoom behavior. 629 | * 630 | * The scale extent restricts zooming in and out. It is enforced on interaction and when using zoom.scaleBy, zoom.scaleTo and zoom.translateBy; 631 | * however, it is not enforced when using zoom.transform to set the transform explicitly. 632 | * 633 | * The default scale extent is [0, infinity]. 634 | * 635 | * If the user tries to zoom by wheeling when already at the corresponding limit of the scale extent, the wheel events will be ignored and not initiate a zoom gesture. 636 | * This allows the user to scroll down past a zoomable area after zooming in, or to scroll up after zooming out. 637 | * If you would prefer to always prevent scrolling on wheel input regardless of the scale extent, register a wheel event listener to prevent the browser default behavior 638 | * 639 | * @param extent A scale extent array of two numbers representing the scale boundaries. 640 | */ 641 | scaleExtent(extent: [number, number]): this; 642 | 643 | /** 644 | * Return the current translate extent. 645 | */ 646 | translateExtent(): [[number, number], [number, number]]; 647 | /** 648 | * Set the translate extent to the specified array of points [[x0, y0], [x1, y1]], where [x0, y0] is the top-left corner of the world and [x1, y1] 649 | * is the bottom-right corner of the world, and return this zoom behavior. 650 | * 651 | * The translate extent restricts panning, and may cause translation on zoom out. It is enforced on interaction and when using zoom.scaleBy, zoom.scaleTo and zoom.translateBy; 652 | * however, it is not enforced when using zoom.transform to set the transform explicitly. 653 | * 654 | * The default scale extent is [[-infinity, infinity], [-infinity, infinity]]. 655 | * 656 | * @param extent A translate extent array, i.e. an array of two arrays, each representing a point. 657 | */ 658 | translateExtent(extent: [[number, number], [number, number]]): this; 659 | 660 | /** 661 | * Return the current click distance threshold, which defaults to zero. 662 | */ 663 | clickDistance(): number; 664 | /** 665 | * Set the maximum distance that the mouse can move between mousedown and mouseup that will trigger 666 | * a subsequent click event. If at any point between mousedown and mouseup the mouse is greater than or equal to 667 | * distance from its position on mousedown, the click event following mouseup will be suppressed. 668 | * 669 | * @param distance The distance threshold between mousedown and mouseup measured in client coordinates (event.clientX and event.clientY). 670 | * The default is zero. 671 | */ 672 | clickDistance(distance: number): this; 673 | 674 | /** 675 | * Get the duration for zoom transitions on double-click and double-tap in milliseconds. 676 | */ 677 | duration(): number; 678 | /** 679 | * Set the duration for zoom transitions on double-click and double-tap to the specified number of milliseconds and returns the zoom behavior. 680 | * 681 | * To disable double-click and double-tap transitions, you can remove the zoom behavior’s dblclick event listener after applying the zoom behavior to the selection. 682 | * 683 | * @param Duration in milliseconds. 684 | */ 685 | duration(duration: number): this; 686 | 687 | /** 688 | * Returns the current interpolation factory, which defaults to d3.interpolateZoom to implement smooth zooming. 689 | */ 690 | interpolate ((t: number) => ZoomView)>(): InterpolationFactory; 691 | 692 | /** 693 | * Sets the interpolation factory for zoom transitions to the specified function. 694 | * Use the default d3.interpolateZoom to implement smooth zooming. 695 | * To apply direct interpolation between two views, try d3.interpolate instead. 696 | * 697 | * Each view is defined as an array of three numbers: cx, cy and width. The first two coordinates cx, cy represent the center of the viewport; 698 | * the last coordinate width represents the size of the viewport. 699 | * 700 | * @param interpolatorFactory An interpolator factory to be used to generate interpolators between zooms for transitions. 701 | */ 702 | interpolate(interpolatorFactory: (a: ZoomView, b: ZoomView) => ((t: number) => ZoomView)): this; 703 | 704 | /** 705 | * Return the first currently-assigned listener matching the specified typenames, if any. 706 | * 707 | * @param typenames The typenames is a string containing one or more typename separated by whitespace. 708 | * Each typename is a type, optionally followed by a period (.) and a name, such as "drag.foo"" and "drag.bar"; 709 | * the name allows multiple listeners to be registered for the same type. The type must be one of the following: 710 | * start (after zooming begins [such as mousedown]), zoom (after a change to the zoom transform [such as mousemove], or 711 | * end (after an active pointer becomes inactive [such as on mouseup].) 712 | */ 713 | on(typenames: string): ValueFn | undefined; 714 | /** 715 | * Remove the current event listeners for the specified typenames, if any, return the drag behavior. 716 | * 717 | * @param typenames The typenames is a string containing one or more typename separated by whitespace. 718 | * Each typename is a type, optionally followed by a period (.) and a name, such as "drag.foo"" and "drag.bar"; 719 | * the name allows multiple listeners to be registered for the same type. The type must be one of the following: 720 | * start (after zooming begins [such as mousedown]), zoom (after a change to the zoom transform [such as mousemove], or 721 | * end (after an active pointer becomes inactive [such as on mouseup].) 722 | * @param listener Use null to remove the listener. 723 | */ 724 | on(typenames: string, listener: null): this; 725 | /** 726 | * Set the event listener for the specified typenames and return the zoom behavior. 727 | * If an event listener was already registered for the same type and name, 728 | * the existing listener is removed before the new listener is added. 729 | * When a specified event is dispatched, each listener will be invoked with the same context and arguments as selection.on listeners. 730 | * 731 | * 732 | * @param typenames The typenames is a string containing one or more typename separated by whitespace. 733 | * Each typename is a type, optionally followed by a period (.) and a name, such as "drag.foo"" and "drag.bar"; 734 | * the name allows multiple listeners to be registered for the same type. The type must be one of the following: 735 | * start (after zooming begins [such as mousedown]), zoom (after a change to the zoom transform [such as mousemove], or 736 | * end (after an active pointer becomes inactive [such as on mouseup].) 737 | * @param listener An event listener function which is evaluated for each selected element, 738 | * in order, being passed the current datum (d), the current index (i), and the current group (nodes), 739 | * with this as the current DOM element. 740 | */ 741 | on(typenames: string, listener: ValueFn): this; 742 | } 743 | 744 | /** 745 | * Creates a new zoom behavior. The returned behavior, zoom, is both an object and a function, 746 | * and is typically applied to selected elements via selection.call. 747 | * 748 | * The first generic refers to the type of reference element to which the zoom behavior is attached. 749 | * The second generic refers to the type of the datum of the reference element. 750 | */ 751 | export function zoom(): ZoomBehavior; 752 | 753 | // -------------------------------------------------------------------------- 754 | // Zoom Event 755 | // -------------------------------------------------------------------------- 756 | 757 | /** 758 | * A D3 Zoom Event 759 | * 760 | * The first generic refers to the type of reference element to which the zoom behavior is attached. 761 | * The second generic refers to the type of the datum of the reference element. 762 | */ 763 | export interface D3ZoomEvent { 764 | /** 765 | * The ZoomBehavior associated with the event 766 | */ 767 | target: ZoomBehavior; 768 | /** 769 | * The event type for the zoom event 770 | */ 771 | type: 'start' | 'zoom' | 'end' | string; // Leave failsafe string type for cases like 'zoom.foo' 772 | /** 773 | * The current zoom transform 774 | */ 775 | transform: ZoomTransform; 776 | /** 777 | * The underlying input event, such as mousemove or touchmove. 778 | */ 779 | sourceEvent: any; 780 | } 781 | 782 | // -------------------------------------------------------------------------- 783 | // Zoom Transforms 784 | // -------------------------------------------------------------------------- 785 | 786 | /** 787 | * A zoom transform 788 | * 789 | * The zoom behavior stores the zoom state on the element to which the zoom behavior was applied, not on the zoom behavior itself. 790 | * This is because the zoom behavior can be applied to many elements simultaneously, and each element can be zoomed independently. 791 | * The zoom state can change either on user interaction or programmatically via zoom.transform. 792 | * 793 | * To retrieve the zoom state, use event.transform on the current zoom event within a zoom event listener (see zoom.on), or use d3.zoomTransform for a given node. 794 | * The latter is particularly useful for modifying the zoom state programmatically, 795 | * say to implement buttons for zooming in and out. 796 | * 797 | * For details see {@link https://github.com/d3/d3-zoom#zoom-transforms} 798 | */ 799 | export interface ZoomTransform { 800 | /** 801 | * The translation amount tx along the x-axis. 802 | * This property should be considered read-only; instead of mutating a transform, 803 | * use transform.scale and transform.translate to derive a new transform. 804 | * Also see zoom.scaleBy, zoom.scaleTo and zoom.translateBy for convenience methods on the zoom behavior. 805 | */ 806 | readonly x: number; 807 | 808 | /** 809 | * The translation amount ty along the y-axis 810 | * This property should be considered read-only; instead of mutating a transform, 811 | * use transform.scale and transform.translate to derive a new transform. 812 | * Also see zoom.scaleBy, zoom.scaleTo and zoom.translateBy for convenience methods on the zoom behavior. 813 | */ 814 | readonly y: number; 815 | 816 | /** 817 | * The scale factor k. 818 | * This property should be considered read-only; instead of mutating a transform, 819 | * use transform.scale and transform.translate to derive a new transform. 820 | * Also see zoom.scaleBy, zoom.scaleTo and zoom.translateBy for convenience methods on the zoom behavior. 821 | */ 822 | readonly k: number; 823 | 824 | /** 825 | * Return the transformation of the specified point which is a two-element array of numbers [x, y]. 826 | * The returned point is equal to [xk + tx, yk + ty]. 827 | * 828 | * @param point Point coordinates [x, y] 829 | */ 830 | apply(point: [number, number]): [number, number]; 831 | 832 | /** 833 | * Return the transformation of the specified x-coordinate, xk + tx. 834 | * 835 | * @param x Value of x-coordinate. 836 | */ 837 | applyX(x: number): number; 838 | 839 | /** 840 | * Return the transformation of the specified y-coordinate, yk + ty. 841 | * 842 | * @param y Value of y-coordinate. 843 | */ 844 | applyY(y: number): number; 845 | 846 | /** 847 | * Return the inverse transformation of the specified point which is a two-element array of numbers [x, y]. 848 | * The returned point is equal to [(x - tx) / k, (y - ty) / k]. 849 | * 850 | * @param point Point coordinates [x, y] 851 | */ 852 | invert(point: [number, number]): [number, number]; 853 | 854 | /** 855 | * Return the inverse transformation of the specified x-coordinate, (x - tx) / k. 856 | * 857 | * @param x Value of x-coordinate. 858 | */ 859 | invertX(x: number): number; 860 | 861 | /** 862 | * Return the inverse transformation of the specified y-coordinate, (y - ty) / k. 863 | * 864 | * @param y Value of y-coordinate. 865 | */ 866 | invertY(y: number): number; 867 | 868 | /** 869 | * Returns a copy of the continuous scale x whose domain is transformed. 870 | * This is implemented by first applying the inverse x-transform on the scale’s range, 871 | * and then applying the inverse scale to compute the corresponding domain 872 | * 873 | * The scale x must use d3.interpolateNumber; do not use continuous.rangeRound as this 874 | * reduces the accuracy of continuous.invert and can lead to an inaccurate rescaled domain. 875 | * This method does not modify the input scale x; x thus represents the untransformed scale, 876 | * while the returned scale represents its transformed view. 877 | * 878 | * @param xScale A continuous scale for x-dimension. 879 | */ 880 | rescaleX(xScale: S): S; 881 | 882 | /** 883 | * Returns a copy of the continuous scale y whose domain is transformed. 884 | * This is implemented by first applying the inverse y-transform on the scale’s range, 885 | * and then applying the inverse scale to compute the corresponding domain 886 | * 887 | * The scale y must use d3.interpolateNumber; do not use continuous.rangeRound as this 888 | * reduces the accuracy of continuous.invert and can lead to an inaccurate rescaled domain. 889 | * This method does not modify the input scale x; x thus represents the untransformed scale, 890 | * while the returned scale represents its transformed view. 891 | * 892 | * @param yScale A continuous scale for y-dimension. 893 | */ 894 | rescaleY(yScale: S): S; 895 | 896 | /** 897 | * Return a transform whose scale k1 is equal to k0 × k, where k0 is this transform’s scale. 898 | * 899 | * @param k A scale factor. 900 | */ 901 | scale(k: number): ZoomTransform; 902 | 903 | /** 904 | * Return a string representing the SVG transform corresponding to this transform. 905 | */ 906 | toString(): string; 907 | 908 | /** 909 | * Return a transform whose translation tx1 and ty1 is equal to tx0 + x and ty0 + y, 910 | * where tx0 and ty0 is this transform’s translation. 911 | * 912 | * @param x Amount of translation in x-direction. 913 | * @param y Amount of translation in y-direction. 914 | */ 915 | translate(x: number, y: number): ZoomTransform; 916 | } 917 | 918 | /** 919 | * Returns the current transform for the specified node. Note that node should typically be a DOM element, and not a selection. 920 | * (A selection may consist of multiple nodes, in different states, and this function only returns a single transform.) If you have a selection, call selection.node first. 921 | * In the context of an event listener, the node is typically the element that received the input event (which should be equal to event.transform), "this". 922 | * Internally, an element’s transform is stored as element.__zoom; however, you should use this method rather than accessing it directly. 923 | * If the given node has no defined transform, returns the identity transformation. 924 | * The returned transform represents a two-dimensional transformation matrix 925 | * 926 | * For details see {@link https://github.com/d3/d3-zoom#zoom-transforms} 927 | * 928 | * @param node An element for which to retrieve its current zoom transform. 929 | */ 930 | export function zoomTransform(node: ZoomedElementBaseType): ZoomTransform; 931 | 932 | /** 933 | * The identity transform, where k = 1, tx = ty = 0. 934 | */ 935 | export const zoomIdentity: ZoomTransform; 936 | } -------------------------------------------------------------------------------- /src/types/flextree.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'd3-flextree' 2 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": true, 6 | "resolveJsonModule": true, 7 | "emitDecoratorMetadata": true, 8 | "jsx": "preserve", 9 | "importHelpers": true, 10 | "moduleResolution": "node", 11 | "experimentalDecorators": true, 12 | "esModuleInterop": true, 13 | "allowSyntheticDefaultImports": true, 14 | "sourceMap": true, 15 | "baseUrl": ".", 16 | "types": [ 17 | "webpack-env", 18 | "vuetify", 19 | "resize-observer-browser" 20 | ], 21 | "paths": { 22 | "@/*": [ 23 | "src/*" 24 | ] 25 | }, 26 | "lib": [ 27 | "esnext", 28 | "dom", 29 | "dom.iterable", 30 | "scripthost" 31 | ] 32 | }, 33 | "include": [ 34 | "src/**/*.ts", 35 | "src/**/*.tsx", 36 | "src/**/*.vue", 37 | "tests/**/*.ts", 38 | "tests/**/*.tsx" 39 | ], 40 | "exclude": [ 41 | "node_modules" 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "css": { 3 | "extract": false 4 | }, 5 | "transpileDependencies": [ 6 | "vuetify" 7 | ] 8 | } --------------------------------------------------------------------------------