fl-web-component 1.4.7 → 1.4.9-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +1 -28
  2. package/dist/fl-web-component.common.1.js +2 -2
  3. package/dist/fl-web-component.common.1.js.map +1 -1
  4. package/dist/fl-web-component.common.2.js.map +1 -1
  5. package/dist/fl-web-component.common.js +77420 -47296
  6. package/dist/fl-web-component.common.js.map +1 -1
  7. package/dist/fl-web-component.css +1 -1
  8. package/package.json +12 -4
  9. package/packages/components/com-flcanvas/components/entityFormatting.js +9 -1
  10. package/packages/components/com-graphics/box.json +77 -0
  11. package/packages/components/com-graphics/component/ann-tool.vue +465 -0
  12. package/packages/components/com-graphics/index copy.vue +1679 -0
  13. package/packages/components/com-graphics/index.vue +3890 -301
  14. package/packages/components/com-graphics/pid.vue +210 -44
  15. package/packages/components/com-graphics/test.html +127 -0
  16. package/packages/components/com-tiles/index.vue +187 -0
  17. package/packages/utils/StreamLoader.js +1498 -0
  18. package/packages/utils/StreamLoaderParser.worker.js +595 -0
  19. package/patches/camera-controls+2.9.0.patch +63 -63
  20. package/src/main.js +9 -1
  21. package/src/static/ann-img/mark_circle@2x.png +0 -0
  22. package/src/static/ann-img/mark_clear@2x.png +0 -0
  23. package/src/static/ann-img/mark_cloud@2x.png +0 -0
  24. package/src/static/ann-img/mark_color@2x.png +0 -0
  25. package/src/static/ann-img/mark_eraser@2x.png +0 -0
  26. package/src/static/ann-img/mark_exit@2x.png +0 -0
  27. package/src/static/ann-img/mark_finish@2x.png +0 -0
  28. package/src/static/ann-img/mark_font@2x.png +0 -0
  29. package/src/static/ann-img/mark_polyline@2x.png +0 -0
  30. package/src/static/ann-img/mark_rectangle@2x.png +0 -0
  31. package/src/static/ann-img/mark_zoomin@2x.png +0 -0
  32. package/src/static/ann-img/mark_zoomout@2x.png +0 -0
  33. package/src/utils/cloud.js +110 -0
  34. package/src/utils/cursor.js +10 -0
  35. package/src/utils/flgltf-parser.js +245 -193
  36. package/src/utils/instance-parser.js +718 -170
  37. package/dist/fl-web-component.common.3.js +0 -7740
  38. package/dist/fl-web-component.common.3.js.map +0 -1
@@ -1 +1 @@
1
- @charset "UTF-8";#fl-model[data-v-2e0d2de9]{width:100%;height:100%;cursor:pointer}[data-v-2e0d2de9] .tips-label{width:60px;color:#000;font:12px Helvetica;margin-top:-3em;padding:5px;text-align:center;vertical-align:middle;background-color:khaki}[data-v-2e0d2de9] .measure-label{max-width:100px;margin-top:-1em;border:10px;border-radius:5px;padding:3px 10px;cursor:pointer;color:#009bea;background-color:#f4f4f4;-webkit-box-shadow:0 1px 3px 1px rgba(0,0,0,.25);box-shadow:0 1px 3px 1px rgba(0,0,0,.25)}[data-v-2e0d2de9] .circle-tag{width:10px;height:10px;margin-top:5px;border-radius:50%;background-color:#ff5000}[data-v-2e0d2de9] .measure-label-font{word-break:break-all}[data-v-2e0d2de9] .mark-label-img{padding-top:5px;width:20px;height:20px}.lil-gui{background:hsla(0,0%,100%,.95)!important;border:1px solid #e0e0e0!important;border-radius:8px!important;-webkit-box-shadow:0 4px 12px rgba(0,0,0,.15)!important;box-shadow:0 4px 12px rgba(0,0,0,.15)!important;backdrop-filter:blur(10px)!important;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif!important}.lil-gui .title{background:linear-gradient(135deg,#f8f9fa,#e9ecef)!important;color:#495057!important;border-bottom:1px solid #dee2e6!important;font-weight:600!important;padding:0 12px!important;border-radius:8px 8px 0 0!important}.lil-gui .controller{border-bottom:1px solid #f1f3f4!important;background:transparent!important}.lil-gui .controller:last-child{border-bottom:none!important}.lil-gui .controller .name{color:#495057!important;font-weight:500!important;font-size:12px!important}.lil-gui .controller .widget{background:#f8f9fa!important;border:1px solid #ced4da!important;border-radius:4px!important;color:#495057!important}.lil-gui .controller .widget:focus,.lil-gui .controller .widget:hover{border-color:#80bdff!important;-webkit-box-shadow:0 0 0 2px rgba(0,123,255,.25)!important;box-shadow:0 0 0 2px rgba(0,123,255,.25)!important}.lil-gui .controller .widget:focus{outline:none!important}.lil-gui .controller input[type=range]{background:#e9ecef!important;height:4px!important;-webkit-appearance:none!important;-moz-appearance:none!important;appearance:none!important;border-radius:2px!important}.lil-gui .controller.number .fill{border-right:solid #008de9}.lil-gui .controller input[type=range]::-webkit-slider-thumb{background:#007bff!important;border:2px solid #fff!important;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.2)!important;box-shadow:0 2px 4px rgba(0,0,0,.2)!important;width:16px!important;height:16px!important;border-radius:50%!important;-webkit-appearance:none!important;appearance:none!important;cursor:pointer!important}.lil-gui .controller input[type=range]::-moz-range-thumb{background:#007bff!important;border:2px solid #fff!important;box-shadow:0 2px 4px rgba(0,0,0,.2)!important;width:16px!important;height:16px!important;border-radius:50%!important;cursor:pointer!important}.lil-gui .controller .option{background:#fff!important;color:#495057!important;border-bottom:1px solid #f1f3f4!important}.lil-gui .controller .option:hover{background:#f8f9fa!important}.lil-gui .controller .option:last-child{border-bottom:none!important}.lil-gui input:active{background:#e6eff4}.lil-gui .controller button{background:linear-gradient(135deg,#007bff,#0056b3)!important;color:#fff!important;border:none!important;border-radius:4px!important;font-weight:500!important;-webkit-transition:all .2s ease!important;transition:all .2s ease!important}.lil-gui .controller button:hover{background:linear-gradient(135deg,#0056b3,#004085)!important;-webkit-transform:translateY(-1px)!important;transform:translateY(-1px)!important;-webkit-box-shadow:0 4px 8px rgba(0,123,255,.3)!important;box-shadow:0 4px 8px rgba(0,123,255,.3)!important}.lil-gui .controller .color{border:2px solid #fff!important;border-radius:4px!important;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.1)!important;box-shadow:0 2px 4px rgba(0,0,0,.1)!important}.lil-gui .controller.number .slider,.lil-gui .controller.number .slider:hover{background-color:#e6eff4}.lil-gui input,.lil-gui input:hover,.lil-gui input[type=number]:focus,.lil-gui input[type=text]:focus{background:#e6eff4}.lil-gui .controller>.name{min-width:25px}.lil-gui .controller.number input{color:#2e3136}.lil-gui .controller.number .slider:active{background-color:#e6eff4}.lil-gui .folder>.title{background:linear-gradient(135deg,#f1f3f4,#e9ecef)!important;color:#495057!important;border-bottom:1px solid #dee2e6!important}.lil-gui .folder>.title:before{color:#6c757d!important}.lil-gui .folder.closed>.children{display:none!important}#konva-container[data-v-459d4d3b]{z-index:3;width:100%;height:100%;cursor:pointer;overflow:hidden}span[data-v-f547d5c6]{font-weight:bolder}.text[data-v-f547d5c6]{margin-top:20px}.line[data-v-f547d5c6]{border-bottom:1px solid #dcdfe6;margin:20px 0}.center[data-v-f547d5c6]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.center .cen span[data-v-f547d5c6],.center .top span[data-v-f547d5c6]{color:"#53a8ff";display:inline-block;width:30px;height:30px;text-align:center;line-height:30px;border:1px solid;padding:5px;margin-bottom:10px;background-color:#e9f3ff}.center .cen span[data-v-f547d5c6]{margin:10px}.button[data-v-f547d5c6]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:end;margin-top:20px}@font-face{font-family:iconfont;src:url(//at.alicdn.com/t/font_3226805_qqvo3ag3r8.woff2?t=1646635700216) format("woff2"),url(//at.alicdn.com/t/font_3226805_qqvo3ag3r8.woff?t=1646635700216) format("woff"),url(//at.alicdn.com/t/font_3226805_qqvo3ag3r8.ttf?t=1646635700216) format("truetype")}.iconfont[data-v-f547d5c6]{font-family:iconfont!important;font-size:50px;font-style:normal;color:"#53a8ff";-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-shubiao[data-v-f547d5c6]:before{content:""}#svg-tigger[data-v-0ec35ee4]{cursor:pointer;height:100%;width:100%}
1
+ @charset "UTF-8";#fl-model[data-v-62715e67]{width:100%;height:100%;cursor:pointer}[data-v-62715e67] .tips-label{width:60px;color:#000;font:12px Helvetica;margin-top:-3em;padding:5px;text-align:center;vertical-align:middle;background-color:khaki}[data-v-62715e67] .measure-label{max-width:100px;margin-top:-1em;border:10px;border-radius:5px;padding:3px 10px;cursor:pointer;color:#009bea;background-color:#f4f4f4;-webkit-box-shadow:0 1px 3px 1px rgba(0,0,0,.25);box-shadow:0 1px 3px 1px rgba(0,0,0,.25)}[data-v-62715e67] .circle-tag{width:10px;height:10px;margin-top:5px;border-radius:50%;background-color:#ff5000}[data-v-62715e67] .measure-label-font{word-break:break-all}[data-v-62715e67] .mark-label-img{padding-top:5px;width:20px;height:20px}.loading-overlay[data-v-62715e67]{position:absolute;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,.7);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;z-index:1000;opacity:0;visibility:hidden;-webkit-transition:opacity .3s ease,visibility .3s ease;transition:opacity .3s ease,visibility .3s ease}.loading-overlay--visible[data-v-62715e67]{opacity:1;visibility:visible}.loading-content[data-v-62715e67]{background:#fff;border-radius:12px;padding:30px;text-align:center;-webkit-box-shadow:0 8px 32px rgba(0,0,0,.3);box-shadow:0 8px 32px rgba(0,0,0,.3);min-width:300px;max-width:400px}.loading-spinner[data-v-62715e67]{width:40px;height:40px;border:4px solid #f3f3f3;border-top:4px solid #409eff;border-radius:50%;-webkit-animation:spin-62715e67 1s linear infinite;animation:spin-62715e67 1s linear infinite;margin:0 auto 20px}@-webkit-keyframes spin-62715e67{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes spin-62715e67{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.loading-text[data-v-62715e67]{font-size:16px;font-weight:500;color:#333;margin-bottom:20px}.loading-progress-bar[data-v-62715e67]{width:100%;height:8px;background-color:#f0f0f0;border-radius:4px;overflow:hidden;margin-bottom:15px}.loading-progress-fill[data-v-62715e67]{height:100%;background:-webkit-gradient(linear,left top,right top,from(#409eff),to(#67c23a));background:linear-gradient(90deg,#409eff,#67c23a);border-radius:4px;-webkit-transition:width .3s ease;transition:width .3s ease}.loading-details[data-v-62715e67]{font-size:12px;color:#666;line-height:1.5}.lil-gui{background:hsla(0,0%,100%,.95)!important;border:1px solid #e0e0e0!important;border-radius:8px!important;-webkit-box-shadow:0 4px 12px rgba(0,0,0,.15)!important;box-shadow:0 4px 12px rgba(0,0,0,.15)!important;backdrop-filter:blur(10px)!important;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif!important}.lil-gui .title{background:linear-gradient(135deg,#f8f9fa,#e9ecef)!important;color:#495057!important;border-bottom:1px solid #dee2e6!important;font-weight:600!important;padding:0 12px!important;border-radius:8px 8px 0 0!important}.lil-gui .controller{border-bottom:1px solid #f1f3f4!important;background:transparent!important}.lil-gui .controller:last-child{border-bottom:none!important}.lil-gui .controller .name{color:#495057!important;font-weight:500!important;font-size:12px!important}.lil-gui .controller .widget{background:#f8f9fa!important;border:1px solid #ced4da!important;border-radius:4px!important;color:#495057!important}.lil-gui .controller .widget:focus,.lil-gui .controller .widget:hover{border-color:#80bdff!important;-webkit-box-shadow:0 0 0 2px rgba(0,123,255,.25)!important;box-shadow:0 0 0 2px rgba(0,123,255,.25)!important}.lil-gui .controller .widget:focus{outline:none!important}.lil-gui .controller input[type=range]{background:#e9ecef!important;height:4px!important;-webkit-appearance:none!important;-moz-appearance:none!important;appearance:none!important;border-radius:2px!important}.lil-gui .controller.number .fill{border-right:solid #008de9}.lil-gui .controller input[type=range]::-webkit-slider-thumb{background:#007bff!important;border:2px solid #fff!important;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.2)!important;box-shadow:0 2px 4px rgba(0,0,0,.2)!important;width:16px!important;height:16px!important;border-radius:50%!important;-webkit-appearance:none!important;appearance:none!important;cursor:pointer!important}.lil-gui .controller input[type=range]::-moz-range-thumb{background:#007bff!important;border:2px solid #fff!important;box-shadow:0 2px 4px rgba(0,0,0,.2)!important;width:16px!important;height:16px!important;border-radius:50%!important;cursor:pointer!important}.lil-gui .controller .option{background:#fff!important;color:#495057!important;border-bottom:1px solid #f1f3f4!important}.lil-gui .controller .option:hover{background:#f8f9fa!important}.lil-gui .controller .option:last-child{border-bottom:none!important}.lil-gui input:active{background:#e6eff4}.lil-gui .controller button{background:linear-gradient(135deg,#007bff,#0056b3)!important;color:#fff!important;border:none!important;border-radius:4px!important;font-weight:500!important;-webkit-transition:all .2s ease!important;transition:all .2s ease!important}.lil-gui .controller button:hover{background:linear-gradient(135deg,#0056b3,#004085)!important;-webkit-transform:translateY(-1px)!important;transform:translateY(-1px)!important;-webkit-box-shadow:0 4px 8px rgba(0,123,255,.3)!important;box-shadow:0 4px 8px rgba(0,123,255,.3)!important}.lil-gui .controller .color{border:2px solid #fff!important;border-radius:4px!important;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.1)!important;box-shadow:0 2px 4px rgba(0,0,0,.1)!important}.lil-gui .controller.number .slider,.lil-gui .controller.number .slider:hover{background-color:#e6eff4}.lil-gui input,.lil-gui input:hover,.lil-gui input[type=number]:focus,.lil-gui input[type=text]:focus{background:#e6eff4}.lil-gui .controller>.name{min-width:25px}.lil-gui .controller.number input{color:#2e3136}.lil-gui .controller.number .slider:active{background-color:#e6eff4}.lil-gui .folder>.title{background:linear-gradient(135deg,#f1f3f4,#e9ecef)!important;color:#495057!important;border-bottom:1px solid #dee2e6!important}.lil-gui .folder>.title:before{color:#6c757d!important}.lil-gui .folder.closed>.children{display:none!important}#konva-container[data-v-459d4d3b]{z-index:3;width:100%;height:100%;cursor:pointer;overflow:hidden}span[data-v-f547d5c6]{font-weight:bolder}.text[data-v-f547d5c6]{margin-top:20px}.line[data-v-f547d5c6]{border-bottom:1px solid #dcdfe6;margin:20px 0}.center[data-v-f547d5c6]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.center .cen span[data-v-f547d5c6],.center .top span[data-v-f547d5c6]{color:"#53a8ff";display:inline-block;width:30px;height:30px;text-align:center;line-height:30px;border:1px solid;padding:5px;margin-bottom:10px;background-color:#e9f3ff}.center .cen span[data-v-f547d5c6]{margin:10px}.button[data-v-f547d5c6]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:end;margin-top:20px}@font-face{font-family:iconfont;src:url(//at.alicdn.com/t/font_3226805_qqvo3ag3r8.woff2?t=1646635700216) format("woff2"),url(//at.alicdn.com/t/font_3226805_qqvo3ag3r8.woff?t=1646635700216) format("woff"),url(//at.alicdn.com/t/font_3226805_qqvo3ag3r8.ttf?t=1646635700216) format("truetype")}.iconfont[data-v-f547d5c6]{font-family:iconfont!important;font-size:50px;font-style:normal;color:"#53a8ff";-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-shubiao[data-v-f547d5c6]:before{content:""}.main_body[data-v-5f081c10]{position:relative;width:100%;height:100%;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden}.classification_title[data-v-5f081c10]{margin:0 0 10px 0;color:#fff;font-size:14px;cursor:default}.toolbar[data-v-5f081c10]{z-index:10;position:absolute;width:520px;padding:8px 16px;border-radius:6px;-webkit-box-shadow:0 2px 10px 0 rgba(6,29,44,.25);box-shadow:0 2px 10px 0 rgba(6,29,44,.25);background-color:#fff;top:10px;left:50%;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transform:translateX(-50%);transform:translateX(-50%);display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-pack:distribute;justify-content:space-around}.icon_toolbar[data-v-5f081c10],.text_toolbar[data-v-5f081c10]{float:left;width:32px;height:32px;padding:0!important;background-repeat:no-repeat;background-size:24px;background-position:50%}.icon_active[data-v-5f081c10],.icon_toolbar[data-v-5f081c10]:hover,.text_toolbar[data-v-5f081c10]:hover{background-color:#eee}[data-v-5f081c10].icon_color .el-color-picker__trigger{height:24px;margin-top:4px;width:24px!important}[data-v-5f081c10].el-color-picker--medium,[data-v-5f081c10].el-color-picker--medium .el-color-picker__trigger{width:24px!important;height:24px!important}.canvas_container[data-v-5f081c10]{position:relative;width:100%;height:100%;overflow:auto;-webkit-box-sizing:border-box;box-sizing:border-box}.canvas_container canvas[data-v-5f081c10]{position:absolute;left:0}.canvas_container #ctx_front[data-v-5f081c10]{z-index:5;background-color:transparent}.canvas_container #ctx_back[data-v-5f081c10]{z-index:3}.canvas_container #ctx_base[data-v-5f081c10]{z-index:1}#text[data-v-5f081c10]{position:absolute;z-index:-1;resize:none;outline:none;border:1px dashed #9c9c9c;overflow:hidden;background:transparent;line-height:30px;display:none}#text[data-v-5f081c10]:hover{border:1px dashed #53a8ff}#svg-component[data-v-6e1600cc],#svg-tigger[data-v-6e1600cc]{cursor:pointer;height:100%;width:100%;position:relative}#toolbar-show[data-v-6e1600cc]{z-index:20;position:absolute;top:0;left:0;background:#fff}#three-box[data-v-5504c19e],#toolbar-show[data-v-6e1600cc]{width:100%;height:100%;overflow:hidden}
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "fl-web-component",
3
- "version": "1.4.7",
3
+ "version": "1.4.9-beta.0",
4
4
  "scripts": {
5
+ "postinstall": "patch-package",
5
6
  "tip1": "仅调试本组件不涉及业务组件,请执行dev",
6
7
  "dev": "vue-cli-service serve",
7
8
  "lint": "eslint \"{src,packages}/**/*.{vue,js}\" --fix",
@@ -12,8 +13,10 @@
12
13
  "build": "npm run lint && vue-cli-service build --target lib --name fl-web-component --formats commonjs ./src/main.js",
13
14
  "build:test": "vue-cli-service build --target lib --name fl-web-component --formats commonjs ./src/main.js",
14
15
  "publish:base": "npm run build && npm publish --registry https://registry.npmjs.org/",
16
+ "publish:beta:base": "npm run build && npm publish --tag beta --registry https://registry.npmjs.org/",
15
17
  "==": "=============================================================",
16
- "tip3": "发版注意: 【修改bug执行publish:fix】【新增功能执行publish:feat】【新特性执行publish:perf】",
18
+ "tip3": "发版注意: 【测试版执行publish:beta】【修改bug执行publish:fix】【新增功能执行publish:feat】【新特性执行publish:perf】",
19
+ "publish:beta": "npm version prerelease --preid=beta && npm run publish:beta:base",
17
20
  "publish:fix": "npm version patch && npm run publish:base",
18
21
  "publish:feat": "npm version minor && npm run publish:base",
19
22
  "publish:perf": "npm version major && npm run publish:base"
@@ -26,13 +29,15 @@
26
29
  ],
27
30
  "main": "dist/fl-web-component.common.js",
28
31
  "dependencies": {
32
+ "3d-tiles-renderer": "^0.4.14",
29
33
  "camera-controls": "2.9.0",
30
34
  "core-js": "^3.42.0",
31
35
  "dxf-parser": "^1.1.2",
32
36
  "element-ui": "2.15.14",
37
+ "fflate": "^0.8.2",
33
38
  "html2canvas": "^1.4.1",
34
39
  "jspdf": "^3.0.1",
35
- "konva": "^9.3.14",
40
+ "konva": "^9.3.12",
36
41
  "lodash": "^4.17.21",
37
42
  "meshline": "^3.3.1",
38
43
  "regenerator-runtime": "^0.14.1",
@@ -43,6 +48,8 @@
43
48
  },
44
49
  "devDependencies": {
45
50
  "@babel/core": "^7.12.16",
51
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
52
+ "@babel/plugin-proposal-optional-chaining": "^7.21.0",
46
53
  "@babel/preset-env": "^7.0.0",
47
54
  "@babel/runtime-corejs3": "^7.27.1",
48
55
  "@vue/cli-plugin-babel": "~4.4.0",
@@ -56,7 +63,8 @@
56
63
  "patch-package": "^6.4.7",
57
64
  "sass": "1.32.13",
58
65
  "sass-loader": "10.1.1",
59
- "vue-template-compiler": "^2.6.11"
66
+ "vue-template-compiler": "^2.6.11",
67
+ "worker-loader": "^3.0.8"
60
68
  },
61
69
  "eslintConfig": {
62
70
  "root": true,
@@ -416,7 +416,14 @@ function drawText(recordDxf, entity, group, key, configParams) {
416
416
  }
417
417
  dim.attrs.rotation = 360-entity.rotation ;
418
418
  }else{
419
- dim.attrs.y= -parseFloat(y) - fontSize;
419
+ // 支持 DXF 垂直对齐(valign),仅在未旋转时按插入点对齐
420
+ if (entity.valign === 2) { // Middle
421
+ dim.attrs.y = -parseFloat(y) - fontSize / 2;
422
+ } else if (entity.valign === 3) { // Top
423
+ dim.attrs.y = -parseFloat(y);
424
+ } else { // Baseline / Bottom 或未设置,保持原逻辑
425
+ dim.attrs.y = -parseFloat(y) - fontSize;
426
+ }
420
427
  }
421
428
  if (entity.xScale) {
422
429
  dim.attrs.fontSize =(fontSize+0.35)* entity.xScale;
@@ -432,6 +439,7 @@ function drawText(recordDxf, entity, group, key, configParams) {
432
439
 
433
440
  }
434
441
  }
442
+
435
443
  //dim.attrs.x= dim.attrs.x-parseFloat(2);
436
444
  group.push({
437
445
  "type":'text',
@@ -0,0 +1,77 @@
1
+ {
2
+ "code": 200,
3
+ "msg": "操作成功",
4
+ "data": [
5
+ {
6
+ "id": 5,
7
+ "min": [268.0, 578.0, 5.0],
8
+ "max": [280.0, 588.0, 5.02],
9
+ "flag": 1,
10
+ "obb": [
11
+ 268.0, 588.0, 5.0, 268.0, 578.0, 5.0, 268.0, 588.0, 5.02, 268.0, 588.0, 5.02, 268.0, 578.0,
12
+ 5.0, 268.0, 578.0, 5.02, 268.0, 578.0, 5.0, 271.0, 578.0, 5.0, 268.0, 578.0, 5.02, 268.0,
13
+ 578.0, 5.02, 271.0, 578.0, 5.0, 271.0, 578.0, 5.02, 271.0, 578.0, 5.0, 271.0, 585.0, 5.0,
14
+ 271.0, 578.0, 5.02, 271.0, 578.0, 5.02, 271.0, 585.0, 5.0, 271.0, 585.0, 5.02, 271.0, 585.0,
15
+ 5.0, 280.0, 585.0, 5.0, 271.0, 585.0, 5.02, 271.0, 585.0, 5.02, 280.0, 585.0, 5.0, 280.0,
16
+ 585.0, 5.02, 271.0, 578.0, 5.0, 268.0, 578.0, 5.0, 271.0, 585.0, 5.0, 271.0, 585.0, 5.0,
17
+ 268.0, 578.0, 5.0, 268.0, 588.0, 5.0, 271.0, 585.0, 5.0, 268.0, 588.0, 5.0, 280.0, 588.0,
18
+ 5.0, 280.0, 588.0, 5.0, 280.0, 585.0, 5.0, 271.0, 585.0, 5.0, 268.0, 578.0, 5.02, 271.0,
19
+ 578.0, 5.02, 268.0, 588.0, 5.02, 268.0, 588.0, 5.02, 271.0, 578.0, 5.02, 271.0, 585.0, 5.02,
20
+ 268.0, 588.0, 5.02, 271.0, 585.0, 5.02, 280.0, 585.0, 5.02, 280.0, 585.0, 5.02, 280.0,
21
+ 588.0, 5.02, 268.0, 588.0, 5.02, 280.0, 585.0, 5.0, 280.0, 588.0, 5.0, 280.0, 585.0, 5.02,
22
+ 280.0, 585.0, 5.02, 280.0, 588.0, 5.0, 280.0, 588.0, 5.02, 280.0, 588.0, 5.0, 268.0, 588.0,
23
+ 5.0, 280.0, 588.0, 5.02, 280.0, 588.0, 5.02, 268.0, 588.0, 5.0, 268.0, 588.0, 5.02
24
+ ],
25
+ "transp": 1.0
26
+ },
27
+ {
28
+ "id": 288,
29
+ "min": [2881.839, 3967.814, -0.01065],
30
+ "max": [2882.217, 3967.836, 0.01065],
31
+ "flag": 2,
32
+ "obb": [
33
+ 2882.02807617188, 3967.82495117188, -2.55106394476346e-20, 0.188999995589256,
34
+ 0.0109999999403954, 0.0106499996036291, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0
35
+ ],
36
+ "transp": 1.0
37
+ },
38
+ {
39
+ "id": 291,
40
+ "min": [2882.104, 3967.956, -0.01065],
41
+ "max": [2882.374, 3968.124, 0.01065],
42
+ "flag": 2,
43
+ "obb": [
44
+ 2882.23901367188, 3968.0400390625, -2.55106394476346e-20, 0.188999995589256,
45
+ 0.0109999999403954, 0.0106499996036291, 0.500014126300812, 0.86601722240448, 0.0,
46
+ -0.86601722240448, 0.500014126300812, 0.0, 0.0, 0.0, 1.0
47
+ ],
48
+ "transp": 1.0
49
+ },
50
+ {
51
+ "id": 292,
52
+ "min": [2882.217, 3968.04, -0.01065],
53
+ "max": [2882.374, 3968.124, 0.01065],
54
+ "flag": 3,
55
+ "obb": [
56
+ 276.758514404297, 586.730529785156, 5.27499485015869,
57
+ 276.844261169434, 586.816268920898, 5.47500514984131,
58
+ 276.758514404297, 586.816268920898, 5.27499485015869,
59
+ 276.844261169434, 586.902008056641, 5.47500514984131,
60
+ 276.758514404297, 586.987747192383, 5.27499485015869,
61
+ 276.844261169434, 587.073486328125, 5.47500514984131
62
+ ]
63
+ },
64
+ {
65
+ "id": 293,
66
+ "min": [2882.217, 3968.04, -0.01065],
67
+ "max": [2882.374, 3968.124, 0.01065],
68
+ "flag": 3,
69
+ "obb": [
70
+ 276.758514404297, 586.730529785156, 5.27499485015869,
71
+ 276.844261169434, 586.816268920898, 5.47500514984131,
72
+ 276.758514404297, 586.816268920898, 5.27499485015869,
73
+ 276.844261169434, 586.902008056641, 5.47500514984131
74
+ ]
75
+ }
76
+ ]
77
+ }
@@ -0,0 +1,465 @@
1
+
2
+ <template>
3
+ <div class="main_body">
4
+ <!-- 绘制工具栏 -->
5
+ <div class="toolbar" v-if="toolbarShow">
6
+ <el-button type="text" :style="`background-image: url(${btnBg.text})`" class="icon_toolbar icon_title" :class="[type === 'text' ? 'icon_active' : '']" title="文本" @click="handleDrawCanvas('text', '文本', 'text')" />
7
+ <!-- <el-button type="text" class="icon_toolbar icon_line" :class="[type === 'line' ? 'icon_active' : '']" title="折线" @click="handleDrawCanvas('crosshair', '折线', 'line')" />-->
8
+ <!-- <el-button type="text" class="icon_toolbar icon_rectangle" :class="[type === 'rectangle' ? 'icon_active' : '']" title="矩形" @click="handleDrawCanvas('crosshair', '矩形', 'rectangle')" /> -->
9
+ <!-- <el-button type="text" class="icon_toolbar icon_circle" :class="[type === 'circle' ? 'icon_active' : '']" title="圆形" @click="handleDrawCanvas('crosshair', '圆形', 'circle')" /> -->
10
+ <el-button
11
+ type="text"
12
+ class="icon_toolbar icon_rectangle"
13
+ :class="[type === 'cloud' ? 'icon_active' : '']"
14
+ title="云线"
15
+ :style="`background-image: url(${btnBg.cloud})`"
16
+ @click="handleDrawCanvas('crosshair', '云线', 'cloud')"
17
+ />
18
+ <!-- <el-button type="text" class="icon_toolbar icon_rubber" :class="[type === 'rubber' ? 'icon_active' : '']" title="橡皮擦" @click="handleDrawCanvas('eraser', '橡皮', 'rubber')" />-->
19
+ <el-button type="text" class="icon_toolbar icon_color" title="颜色" >
20
+ <el-color-picker v-model="defaultColor" popper-class="popperClass" @change="colorChange"></el-color-picker>
21
+ </el-button>
22
+ <el-button type="text" :style="`background-image: url(${btnBg.clear})`" class="text_toolbar icon_clear" @click="clearAnn" title="清除"></el-button>
23
+ <el-button type="text" :style="`background-image: url(${btnBg.cancel})`" class="text_toolbar icon_cancel" @click="cancel" title="取消"></el-button>
24
+ <el-button type="text" :style="`background-image: url(${btnBg.save})`" class="text_toolbar icon_save" @click="saveDrawing" title="保存"></el-button>
25
+ </div>
26
+ <div class="canvas_container" id="canvas_container">
27
+ <canvas id="ctx_base" ref="ctx_base" :style="'cursor:' + cursorStyle"></canvas>
28
+ <input name="text" id="text" @keyup.enter="handleTextBlur" @blur="handleTextBlur" v-model="text" autofocus autocomplete="off" :style="'font-size:' + (this.slide * 10 + 14) + 'pxcolor:' + defaultColor" placeholder="输入完成请按回车键" />
29
+ </div>
30
+ </div>
31
+ </template>
32
+
33
+ <script>
34
+ var canvas_base = null, ctx_base = null, recordImg = null
35
+ var canvas_container = null, startPoint = null, currentPoint = null
36
+ let originalImageWidth = 0, originalImageHeight = 0, displayImageWidth = 0, displayImageHeight = 0, translateX = 0, translateY = 0
37
+ var annList = []
38
+ let scale = 1.0; // 当前缩放比例
39
+ const MIN_SCALE = 0.1; // 最小缩放比例
40
+ const MAX_SCALE = 8.0; // 最大缩放比例
41
+ const SCALE_STEP = 0.1; // 缩放步长
42
+ let offsetX = 0; // X轴平移
43
+ let offsetY = 0; // Y轴平移
44
+ let isPanning = false; // 是否正在平移
45
+ let panStartX = 0; // 平移起始X坐标
46
+ let panStartY = 0; // 平移起始Y坐标
47
+ let isSpacePressed = false; // 空格键是否按下
48
+ import cursors from "@/utils/cursor"
49
+ import { drawCloudLines } from '@/utils/cloud'
50
+ export default {
51
+ name: 'DrawToolbar',
52
+ props: {
53
+ src: {
54
+ type: String,
55
+ default: ''
56
+ }
57
+ },
58
+ data() {
59
+ return {
60
+ currentImg: {
61
+ url: null,
62
+ width: "",
63
+ height: "",
64
+ scale: 1,
65
+ index: 0,
66
+ },
67
+ tl: 0,
68
+ tt: 0,
69
+ slide: 1,// 2,
70
+ text: '',
71
+ toolbarShow: true,
72
+ ctx_base: null,
73
+ ctx_front: null,
74
+ ctx_back: null,
75
+ canDraw: false,
76
+ baseMap: null,
77
+ canvasStore: [],
78
+ type: '',
79
+ cloudDensity: 3,
80
+ defaultColor: '#A90A0A', // 颜色选取
81
+ cursorStyle: 'default', // 鼠标样式
82
+ btnBg: {
83
+ 'text': require('@static/ann-img/mark_font@2x.png'),
84
+ 'cloud': require('@static/ann-img/mark_cloud@2x.png'),
85
+ 'clear': require('@static/ann-img/mark_clear@2x.png'),
86
+ 'cancel': require('@static/ann-img/mark_exit@2x.png'),
87
+ 'save': require('@static/ann-img/mark_finish@2x.png'),
88
+ }
89
+ }
90
+ },
91
+ mounted() {
92
+ this.$nextTick(() => {
93
+ this.handleInitCanvas()
94
+ })
95
+ },
96
+ created() {
97
+ console.log('created')
98
+ },
99
+ methods: {
100
+ clearAnn() {
101
+ annList.splice(0)
102
+ this.redraw()
103
+ },
104
+ // 初始化图纸
105
+ handleInitCanvas() {
106
+ console.log('handleInitCanvas')
107
+ this.currentImg = {
108
+ url: this.src,
109
+ width: "",
110
+ height: "",
111
+ scale: 1,
112
+ index: 0,
113
+ }
114
+ canvas_container = document.getElementById("canvas_container")
115
+ canvas_base = document.getElementById("ctx_base")
116
+ ctx_base = canvas_base.getContext("2d")
117
+ ctx_base.strokeStyle = this.defaultColor
118
+
119
+ let img = new Image()
120
+ img.src = this.currentImg.url
121
+ let _this = this
122
+ img.onload = function () {
123
+
124
+ recordImg = this
125
+ originalImageWidth = img.naturalWidth || img.width;
126
+ originalImageHeight = img.naturalHeight || img.height;
127
+ _this.resetView()
128
+ }
129
+ canvas_base.width = canvas_container.clientWidth
130
+ canvas_base.height = canvas_container.clientHeight
131
+ canvas_base.addEventListener('wheel', (e) => {
132
+ e.preventDefault()
133
+ const rect = canvas_base.getBoundingClientRect();
134
+ const mouseX = e.clientX - rect.left;
135
+ const mouseY = e.clientY - rect.top;
136
+ let imagePointBeforeZoom = this.screenToImage(mouseX, mouseY)
137
+ const zoomFactor = e.deltaY > 0 ? 0.8 : 1.2
138
+ const newScale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, scale * zoomFactor))
139
+ scale = newScale
140
+ const imagePointAfterZoom = this.screenToImage(mouseX, mouseY)
141
+ translateX += (imagePointAfterZoom.x - imagePointBeforeZoom.x) * scale
142
+ translateY += (imagePointAfterZoom.y - imagePointBeforeZoom.y) * scale
143
+ this.redraw()
144
+ })
145
+ canvas_base.addEventListener('mousedown', (e) => {
146
+ if (e.button === 0) {
147
+ // ctx_base.strokeStyle = this.defaultColor
148
+ // ctx_base.lineWidth = this.slide * 2
149
+ e = e || window.event
150
+ let rect = canvas_base.getBoundingClientRect()
151
+ let screenX = e.clientX - rect.left
152
+ let screenY = e.clientY - rect.top
153
+ let imagePoint = this.screenToImage(screenX, screenY)
154
+ startPoint = imagePoint;
155
+ currentPoint = imagePoint;
156
+ switch (this.type) {
157
+ case 'rubber':
158
+ ctx_front.putImageData( cbx, e.offsetX - 12, e.offsetY - 12)
159
+ // this.ctx_back.putImageData(cbx, e.offsetX - 12, e.offsetY - 12)
160
+ break
161
+ case 'text':
162
+ let text = document.getElementById("text")
163
+ // this.handleTextBlur()
164
+ this.text = ""
165
+ text.style.fontSize = 14 + this.slide * 10 + "px"
166
+ text.style.color = this.defaultColor
167
+ text.style.left = screenX - 5 + "px"
168
+ text.style.top = screenY - 20 + "px"
169
+ text.style.zIndex = 10
170
+ text.style.display = "block"
171
+ let textPos = this.screenToImage(screenX - 5, screenY + 10)
172
+ this.tl = textPos.x // currentPoint.x
173
+ this.tt = textPos.y // currentPoint.y
174
+ break;
175
+ case 'cloud':
176
+ this.canDraw = true
177
+ break;
178
+ }
179
+ this.redraw()
180
+ }
181
+ })
182
+ canvas_base.addEventListener('contextmenu', (e) => {
183
+ e.preventDefault()
184
+ })
185
+ canvas_base.addEventListener('mousemove', (e) => {
186
+ if (e.button === 0) {
187
+ e = e || window.event
188
+ let rect = canvas_base.getBoundingClientRect()
189
+ let screenX = e.clientX - rect.left;
190
+ let screenY = e.clientY - rect.top;
191
+ if (this.canDraw) {
192
+ let imagePoint = this.screenToImage(screenX, screenY)
193
+ currentPoint = imagePoint
194
+ this.redraw()
195
+ }
196
+ }
197
+ })
198
+ canvas_base.addEventListener('mouseup', (e) => {
199
+ if (e.button === 0 && this.canDraw) {
200
+ this.canDraw = false
201
+ if (this.type === 'cloud') {
202
+ let width = Math.abs(currentPoint.x - startPoint.x)
203
+ let height = Math.abs(currentPoint.y - startPoint.y)
204
+ let minSize = 5 / scale
205
+ if (width > minSize && height > minSize) {
206
+ annList.push({
207
+ x: Math.min(startPoint.x, currentPoint.x),
208
+ y: Math.min(startPoint.y, currentPoint.y),
209
+ ex: Math.max(startPoint.x, currentPoint.x),
210
+ ey: Math.max(startPoint.y, currentPoint.y),
211
+ type: 'cloud',
212
+ color: this.defaultColor,
213
+ lineWidth: ctx_base.lineWidth
214
+ })
215
+ }
216
+ startPoint = null
217
+ currentPoint = null
218
+ }
219
+ this.redraw()
220
+ }
221
+ })
222
+
223
+ },
224
+ resetView() {
225
+ if (!recordImg) return
226
+ const containerWidth = canvas_base.width;
227
+ const containerHeight = canvas_base.height;
228
+
229
+ // 计算保持比例的最大尺寸
230
+ const widthRatio = containerWidth / originalImageWidth;
231
+ const heightRatio = containerHeight / originalImageHeight;
232
+ const scaleRatio = Math.min(widthRatio, heightRatio);
233
+
234
+ displayImageWidth = originalImageWidth * scaleRatio;
235
+ displayImageHeight = originalImageHeight * scaleRatio;
236
+
237
+ // 居中显示
238
+ translateX = (containerWidth - displayImageWidth) / 2;
239
+ translateY = (containerHeight - displayImageHeight) / 2;
240
+ scale = scaleRatio;
241
+ this.redraw()
242
+ },
243
+ redraw() {
244
+ if (!recordImg) return
245
+ ctx_base.clearRect(0, 0, canvas_base.width, canvas_base.height)
246
+ ctx_base.save()
247
+ ctx_base.translate(translateX, translateY)
248
+ ctx_base.scale(scale, scale)
249
+ ctx_base.drawImage(recordImg, 0, 0, originalImageWidth, originalImageHeight)
250
+ annList.forEach(item => {
251
+ switch (item.type) {
252
+ case 'cloud':
253
+ this.drawCloudAnn(item)
254
+ break;
255
+ case 'text':
256
+ this.drawTextAnn(item)
257
+ break;
258
+ }
259
+ })
260
+ if (this.canDraw && startPoint && currentPoint) {
261
+ if (this.type === 'cloud') {
262
+ let tempAnn = {
263
+ x: Math.min(startPoint.x, currentPoint.x),
264
+ y: Math.min(startPoint.y, currentPoint.y),
265
+ ex: Math.max(startPoint.x, currentPoint.x),
266
+ ey: Math.max(startPoint.y, currentPoint.y),
267
+ type: 'cloud',
268
+ color: this.defaultColor,
269
+ lineWidth: ctx_base.lineWidth
270
+ }
271
+ this.drawCloudAnn(tempAnn)
272
+ }
273
+ }
274
+ ctx_base.restore()
275
+ },
276
+ // 绘制云线
277
+ drawCloudAnn(annotation) {
278
+ ctx_base.save()
279
+ ctx_base.strokeStyle = annotation.color
280
+ ctx_base.lineWidth = annotation.lineWidth || ctx_base.lineWidth;
281
+ ctx_base.setLineDash([])
282
+ ctx_base.beginPath()
283
+ drawCloudLines(ctx_base, [{x: annotation.ex, y: annotation.y}, {x: annotation.ex, y: annotation.ey}, {x: annotation.x, y: annotation.ey}, {x: annotation.x, y: annotation.y}], true);
284
+ ctx_base.restore()
285
+ },
286
+ drawTextAnn(annotation) {
287
+ ctx_base.save()
288
+ ctx_base.strokeStyle = annotation.color
289
+ ctx_base.fillStyle = annotation.color
290
+ ctx_base.fillText(annotation.text, annotation.x, annotation.y)
291
+ ctx_base.restore()
292
+ },
293
+ // 屏幕坐标转换为图像坐标
294
+ screenToImage(screenX, screenY) {
295
+ const imageX = (screenX - translateX) / scale
296
+ const imageY = (screenY - translateY) / scale
297
+ return { x: imageX, y: imageY }
298
+ },
299
+ // 当前显示的颜色发生改变时
300
+ colorChange (val) {
301
+ if (this.defaultColor === null) this.defaultColor = '#A90A0A'
302
+ this.redraw()
303
+ },
304
+ saveDrawing() {
305
+ const link = document.createElement('a');
306
+ link.download = `图纸批注_${new Date().toISOString().slice(0, 19).replace(/[:T]/g, '-')}.png`;
307
+ link.href = canvas_base.toDataURL('image/png', 1.0);
308
+ link.click();
309
+ },
310
+ handleDrawCanvas(style, type, actived) {
311
+ if (actived !== this.type) { this.type = actived }
312
+ if (style !== 'eraser') this.cursorStyle = style
313
+ else if (style === 'eraser') this.cursorStyle = `url('${cursors.eraser}') 15 15, auto`
314
+ this.canDraw = false
315
+ },
316
+ /** 失焦或者回车绘制文本,框隐藏*/
317
+ handleTextBlur() {
318
+ let realTxt = this.text.replace(/^\s+|\s+$/g, '')
319
+ if (realTxt === '') return
320
+ let text = document.getElementById("text")
321
+ let fontSize = 1.2 // text.style.fontSize / 10
322
+ annList.push({
323
+ type: 'text',
324
+ x: this.tl,
325
+ y: this.tt,
326
+ text: realTxt,
327
+ color: this.defaultColor,
328
+ font: `100 ${fontSize} sans-serif`
329
+ });
330
+ text.style.display = "none"
331
+ this.text = ""
332
+ text.value = ""
333
+ this.redraw()
334
+
335
+ },
336
+ cancel() {
337
+ canvas_base = null
338
+ ctx_base = null
339
+ recordImg = null
340
+ canvas_container = null
341
+ startPoint = null
342
+ currentPoint = null
343
+ originalImageWidth = 0
344
+ originalImageHeight = 0
345
+ displayImageWidth = 0
346
+ displayImageHeight = 0
347
+ translateX = 0
348
+ translateY = 0
349
+ annList.splice(0 )
350
+ scale = 1.0 // 当前缩放比例
351
+ offsetX = 0 // X轴平移
352
+ offsetY = 0 // Y轴平移
353
+ isPanning = false; // 是否正在平移
354
+ panStartX = // 平移起始X坐标
355
+ panStartY = 0 // 平移起始Y坐标
356
+ isSpacePressed = false // 空格键是否按下
357
+ this.$emit('closeAnn')
358
+ }
359
+ }
360
+
361
+ }
362
+ </script>
363
+ <style scoped lang="scss">
364
+ .main_body {
365
+ position: relative;
366
+ width: 100%;
367
+ height: 100%;
368
+ box-sizing: border-box;
369
+ overflow: hidden;
370
+ }
371
+ // P标签样式
372
+ .classification_title {
373
+ margin: 0 0 10px 0;
374
+ color: #fff;
375
+ font-size: 14px;
376
+ cursor: default;
377
+ }
378
+
379
+ // 工具栏样式
380
+ .toolbar {
381
+ z-index: 10;
382
+ position: absolute;
383
+ width: 520px;
384
+ padding: 8px 16px;
385
+ border-radius: 6px;
386
+ box-shadow: 0px 2px 10px 0px rgba(6,29,44,0.25);
387
+ background-color: #fff;
388
+ top: 10px;
389
+ left: 50%;
390
+ box-sizing: border-box;
391
+ transform: translateX(-50%);
392
+ display: flex;
393
+ justify-content: space-around
394
+ }
395
+ // 工具栏图标
396
+ .icon_toolbar,
397
+ .text_toolbar {
398
+ float: left;
399
+ width: 32px;
400
+ height: 32px;
401
+ padding: 0px !important;
402
+ background-repeat: no-repeat;
403
+ background-size: 24px;
404
+ background-position: center;
405
+ }
406
+ .icon_toolbar:hover, .text_toolbar:hover, .icon_active{
407
+ background-color: rgba(238, 238, 238, 1);
408
+ }
409
+
410
+ // 调色盘设置
411
+ ::v-deep.icon_color .el-color-picker__trigger {
412
+ height: 24px;
413
+ margin-top: 4px;
414
+ width: 24px !important
415
+ // opacity: 0;
416
+ // filter: alpha(opacity=0);
417
+ }
418
+ ::v-deep.el-color-picker--medium,
419
+ ::v-deep.el-color-picker--medium .el-color-picker__trigger {
420
+ width: 24px !important;
421
+ height: 24px !important;
422
+ }
423
+
424
+ // 画布
425
+ .canvas_container {
426
+ position: relative;
427
+ width: 100%;
428
+ height: 100%;
429
+ overflow: auto;
430
+ box-sizing: border-box;
431
+ // padding: 20px;
432
+
433
+ canvas {
434
+ position: absolute;
435
+ left: 0;
436
+ // top: 20px;
437
+ // left: 20px;
438
+ }
439
+ #ctx_front {
440
+ z-index: 5;
441
+ background-color: transparent
442
+ }
443
+ #ctx_back {
444
+
445
+ z-index: 3;
446
+ }
447
+ #ctx_base {
448
+ z-index: 1;
449
+ }
450
+ }
451
+ #text {
452
+ position: absolute;
453
+ z-index: -1;
454
+ resize: none;
455
+ outline: none;
456
+ border: 1px dashed #9c9c9c;
457
+ overflow: hidden;
458
+ background: transparent;
459
+ line-height: 30px;
460
+ display: none;
461
+ }
462
+ #text:hover{
463
+ border: 1px dashed #53a8ff
464
+ }
465
+ </style>