marquee-selection 0.0.11
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.
- package/README.html +442 -0
- package/README.md +204 -0
- package/dist/index.d.ts +215 -0
- package/dist/infinite-canvas.es.js +475 -0
- package/dist/infinite-canvas.es.js.map +1 -0
- package/dist/infinite-canvas.umd.js +2 -0
- package/dist/infinite-canvas.umd.js.map +1 -0
- package/dist/marquee-selection.es.js +672 -0
- package/dist/marquee-selection.es.js.map +1 -0
- package/dist/marquee-selection.umd.js +2 -0
- package/dist/marquee-selection.umd.js.map +1 -0
- package/index.html +740 -0
- package/package.json +49 -0
package/README.html
ADDED
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
<!DOCTYPE html><html><head>
|
|
2
|
+
<title>README</title>
|
|
3
|
+
<meta charset="utf-8">
|
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
5
|
+
|
|
6
|
+
<link rel="stylesheet" href="file:////Users/zhumingpeng/.vscode/extensions/shd101wyy.markdown-preview-enhanced-0.8.19/crossnote/dependencies/katex/katex.min.css">
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
<style>
|
|
13
|
+
code[class*=language-],pre[class*=language-]{color:#333;background:0 0;font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.4;-moz-tab-size:8;-o-tab-size:8;tab-size:8;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:.8em;overflow:auto;border-radius:3px;background:#f5f5f5}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal;background:#f5f5f5}.token.blockquote,.token.comment{color:#969896}.token.cdata{color:#183691}.token.doctype,.token.macro.property,.token.punctuation,.token.variable{color:#333}.token.builtin,.token.important,.token.keyword,.token.operator,.token.rule{color:#a71d5d}.token.attr-value,.token.regex,.token.string,.token.url{color:#183691}.token.atrule,.token.boolean,.token.code,.token.command,.token.constant,.token.entity,.token.number,.token.property,.token.symbol{color:#0086b3}.token.prolog,.token.selector,.token.tag{color:#63a35c}.token.attr-name,.token.class,.token.class-name,.token.function,.token.id,.token.namespace,.token.pseudo-class,.token.pseudo-element,.token.url-reference .token.variable{color:#795da3}.token.entity{cursor:help}.token.title,.token.title .token.punctuation{font-weight:700;color:#1d3e81}.token.list{color:#ed6a43}.token.inserted{background-color:#eaffea;color:#55a532}.token.deleted{background-color:#ffecec;color:#bd2c00}.token.bold{font-weight:700}.token.italic{font-style:italic}.language-json .token.property{color:#183691}.language-markup .token.tag .token.punctuation{color:#333}.language-css .token.function,code.language-css{color:#0086b3}.language-yaml .token.atrule{color:#63a35c}code.language-yaml{color:#183691}.language-ruby .token.function{color:#333}.language-markdown .token.url{color:#795da3}.language-makefile .token.symbol{color:#795da3}.language-makefile .token.variable{color:#183691}.language-makefile .token.builtin{color:#0086b3}.language-bash .token.keyword{color:#0086b3}pre[data-line]{position:relative;padding:1em 0 1em 3em}pre[data-line] .line-highlight-wrapper{position:absolute;top:0;left:0;background-color:transparent;display:block;width:100%}pre[data-line] .line-highlight{position:absolute;left:0;right:0;padding:inherit 0;margin-top:1em;background:hsla(24,20%,50%,.08);background:linear-gradient(to right,hsla(24,20%,50%,.1) 70%,hsla(24,20%,50%,0));pointer-events:none;line-height:inherit;white-space:pre}pre[data-line] .line-highlight:before,pre[data-line] .line-highlight[data-end]:after{content:attr(data-start);position:absolute;top:.4em;left:.6em;min-width:1em;padding:0 .5em;background-color:hsla(24,20%,50%,.4);color:#f4f1ef;font:bold 65%/1.5 sans-serif;text-align:center;vertical-align:.3em;border-radius:999px;text-shadow:none;box-shadow:0 1px #fff}pre[data-line] .line-highlight[data-end]:after{content:attr(data-end);top:auto;bottom:.4em}html body{font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif;font-size:16px;line-height:1.6;color:#333;background-color:#fff;overflow:initial;box-sizing:border-box;word-wrap:break-word}html body>:first-child{margin-top:0}html body h1,html body h2,html body h3,html body h4,html body h5,html body h6{line-height:1.2;margin-top:1em;margin-bottom:16px;color:#000}html body h1{font-size:2.25em;font-weight:300;padding-bottom:.3em}html body h2{font-size:1.75em;font-weight:400;padding-bottom:.3em}html body h3{font-size:1.5em;font-weight:500}html body h4{font-size:1.25em;font-weight:600}html body h5{font-size:1.1em;font-weight:600}html body h6{font-size:1em;font-weight:600}html body h1,html body h2,html body h3,html body h4,html body h5{font-weight:600}html body h5{font-size:1em}html body h6{color:#5c5c5c}html body strong{color:#000}html body del{color:#5c5c5c}html body a:not([href]){color:inherit;text-decoration:none}html body a{color:#08c;text-decoration:none}html body a:hover{color:#00a3f5;text-decoration:none}html body img{max-width:100%}html body>p{margin-top:0;margin-bottom:16px;word-wrap:break-word}html body>ol,html body>ul{margin-bottom:16px}html body ol,html body ul{padding-left:2em}html body ol.no-list,html body ul.no-list{padding:0;list-style-type:none}html body ol ol,html body ol ul,html body ul ol,html body ul ul{margin-top:0;margin-bottom:0}html body li{margin-bottom:0}html body li.task-list-item{list-style:none}html body li>p{margin-top:0;margin-bottom:0}html body .task-list-item-checkbox{margin:0 .2em .25em -1.8em;vertical-align:middle}html body .task-list-item-checkbox:hover{cursor:pointer}html body blockquote{margin:16px 0;font-size:inherit;padding:0 15px;color:#5c5c5c;background-color:#f0f0f0;border-left:4px solid #d6d6d6}html body blockquote>:first-child{margin-top:0}html body blockquote>:last-child{margin-bottom:0}html body hr{height:4px;margin:32px 0;background-color:#d6d6d6;border:0 none}html body table{margin:10px 0 15px 0;border-collapse:collapse;border-spacing:0;display:block;width:100%;overflow:auto;word-break:normal;word-break:keep-all}html body table th{font-weight:700;color:#000}html body table td,html body table th{border:1px solid #d6d6d6;padding:6px 13px}html body dl{padding:0}html body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:700}html body dl dd{padding:0 16px;margin-bottom:16px}html body code{font-family:Menlo,Monaco,Consolas,'Courier New',monospace;font-size:.85em;color:#000;background-color:#f0f0f0;border-radius:3px;padding:.2em 0}html body code::after,html body code::before{letter-spacing:-.2em;content:'\00a0'}html body pre>code{padding:0;margin:0;word-break:normal;white-space:pre;background:0 0;border:0}html body .highlight{margin-bottom:16px}html body .highlight pre,html body pre{padding:1em;overflow:auto;line-height:1.45;border:#d6d6d6;border-radius:3px}html body .highlight pre{margin-bottom:0;word-break:normal}html body pre code,html body pre tt{display:inline;max-width:initial;padding:0;margin:0;overflow:initial;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}html body pre code:after,html body pre code:before,html body pre tt:after,html body pre tt:before{content:normal}html body blockquote,html body dl,html body ol,html body p,html body pre,html body ul{margin-top:0;margin-bottom:16px}html body kbd{color:#000;border:1px solid #d6d6d6;border-bottom:2px solid #c7c7c7;padding:2px 4px;background-color:#f0f0f0;border-radius:3px}@media print{html body{background-color:#fff}html body h1,html body h2,html body h3,html body h4,html body h5,html body h6{color:#000;page-break-after:avoid}html body blockquote{color:#5c5c5c}html body pre{page-break-inside:avoid}html body table{display:table}html body img{display:block;max-width:100%;max-height:100%}html body code,html body pre{word-wrap:break-word;white-space:pre}}.markdown-preview{width:100%;height:100%;box-sizing:border-box}.markdown-preview ul{list-style:disc}.markdown-preview ul ul{list-style:circle}.markdown-preview ul ul ul{list-style:square}.markdown-preview ol{list-style:decimal}.markdown-preview ol ol,.markdown-preview ul ol{list-style-type:lower-roman}.markdown-preview ol ol ol,.markdown-preview ol ul ol,.markdown-preview ul ol ol,.markdown-preview ul ul ol{list-style-type:lower-alpha}.markdown-preview .newpage,.markdown-preview .pagebreak{page-break-before:always}.markdown-preview pre.line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}.markdown-preview pre.line-numbers>code{position:relative}.markdown-preview pre.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:1em;font-size:100%;left:0;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.markdown-preview pre.line-numbers .line-numbers-rows>span{pointer-events:none;display:block;counter-increment:linenumber}.markdown-preview pre.line-numbers .line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right}.markdown-preview .mathjax-exps .MathJax_Display{text-align:center!important}.markdown-preview:not([data-for=preview]) .code-chunk .code-chunk-btn-group{display:none}.markdown-preview:not([data-for=preview]) .code-chunk .status{display:none}.markdown-preview:not([data-for=preview]) .code-chunk .output-div{margin-bottom:16px}.markdown-preview .md-toc{padding:0}.markdown-preview .md-toc .md-toc-link-wrapper .md-toc-link{display:inline;padding:.25rem 0}.markdown-preview .md-toc .md-toc-link-wrapper .md-toc-link div,.markdown-preview .md-toc .md-toc-link-wrapper .md-toc-link p{display:inline}.markdown-preview .md-toc .md-toc-link-wrapper.highlighted .md-toc-link{font-weight:800}.scrollbar-style::-webkit-scrollbar{width:8px}.scrollbar-style::-webkit-scrollbar-track{border-radius:10px;background-color:transparent}.scrollbar-style::-webkit-scrollbar-thumb{border-radius:5px;background-color:rgba(150,150,150,.66);border:4px solid rgba(150,150,150,.66);background-clip:content-box}html body[for=html-export]:not([data-presentation-mode]){position:relative;width:100%;height:100%;top:0;left:0;margin:0;padding:0;overflow:auto}html body[for=html-export]:not([data-presentation-mode]) .markdown-preview{position:relative;top:0;min-height:100vh}@media screen and (min-width:914px){html body[for=html-export]:not([data-presentation-mode]) .markdown-preview{padding:2em calc(50% - 457px + 2em)}}@media screen and (max-width:914px){html body[for=html-export]:not([data-presentation-mode]) .markdown-preview{padding:2em}}@media screen and (max-width:450px){html body[for=html-export]:not([data-presentation-mode]) .markdown-preview{font-size:14px!important;padding:1em}}@media print{html body[for=html-export]:not([data-presentation-mode]) #sidebar-toc-btn{display:none}}html body[for=html-export]:not([data-presentation-mode]) #sidebar-toc-btn{position:fixed;bottom:8px;left:8px;font-size:28px;cursor:pointer;color:inherit;z-index:99;width:32px;text-align:center;opacity:.4}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] #sidebar-toc-btn{opacity:1}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc{position:fixed;top:0;left:0;width:300px;height:100%;padding:32px 0 48px 0;font-size:14px;box-shadow:0 0 4px rgba(150,150,150,.33);box-sizing:border-box;overflow:auto;background-color:inherit}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc::-webkit-scrollbar{width:8px}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc::-webkit-scrollbar-track{border-radius:10px;background-color:transparent}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc::-webkit-scrollbar-thumb{border-radius:5px;background-color:rgba(150,150,150,.66);border:4px solid rgba(150,150,150,.66);background-clip:content-box}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc a{text-decoration:none}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc{padding:0 16px}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc .md-toc-link-wrapper .md-toc-link{display:inline;padding:.25rem 0}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc .md-toc-link-wrapper .md-toc-link div,html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc .md-toc-link-wrapper .md-toc-link p{display:inline}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc .md-toc-link-wrapper.highlighted .md-toc-link{font-weight:800}html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .markdown-preview{left:300px;width:calc(100% - 300px);padding:2em calc(50% - 457px - 300px / 2);margin:0;box-sizing:border-box}@media screen and (max-width:1274px){html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .markdown-preview{padding:2em}}@media screen and (max-width:450px){html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .markdown-preview{width:100%}}html body[for=html-export]:not([data-presentation-mode]):not([html-show-sidebar-toc]) .markdown-preview{left:50%;transform:translateX(-50%)}html body[for=html-export]:not([data-presentation-mode]):not([html-show-sidebar-toc]) .md-sidebar-toc{display:none}
|
|
14
|
+
/* Please visit the URL below for more information: */
|
|
15
|
+
/* https://shd101wyy.github.io/markdown-preview-enhanced/#/customize-css */
|
|
16
|
+
.markdown-preview.markdown-preview {
|
|
17
|
+
font-size: 15px;
|
|
18
|
+
color: #3e3e3e;
|
|
19
|
+
line-height: 1.5;
|
|
20
|
+
word-spacing: 1px;
|
|
21
|
+
letter-spacing: 1.1px;
|
|
22
|
+
font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;
|
|
23
|
+
background-image: linear-gradient(90deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%), linear-gradient(360deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%);
|
|
24
|
+
background-size: 20px 20px;
|
|
25
|
+
background-position: center center;
|
|
26
|
+
}
|
|
27
|
+
.markdown-preview.markdown-preview * {
|
|
28
|
+
font-size: inherit;
|
|
29
|
+
color: inherit;
|
|
30
|
+
line-height: inherit;
|
|
31
|
+
margin: 0px;
|
|
32
|
+
padding: 0px;
|
|
33
|
+
}
|
|
34
|
+
.markdown-preview.markdown-preview p {
|
|
35
|
+
margin: 1.7em 0px;
|
|
36
|
+
}
|
|
37
|
+
.markdown-preview.markdown-preview h1,
|
|
38
|
+
.markdown-preview.markdown-preview h2,
|
|
39
|
+
.markdown-preview.markdown-preview h3,
|
|
40
|
+
.markdown-preview.markdown-preview h4,
|
|
41
|
+
.markdown-preview.markdown-preview h5,
|
|
42
|
+
.markdown-preview.markdown-preview h6 {
|
|
43
|
+
margin: 1.6em 0px;
|
|
44
|
+
font-weight: bold;
|
|
45
|
+
}
|
|
46
|
+
.markdown-preview.markdown-preview h1 {
|
|
47
|
+
font-size: 1.6em;
|
|
48
|
+
}
|
|
49
|
+
.markdown-preview.markdown-preview h2 {
|
|
50
|
+
font-size: 1.4em;
|
|
51
|
+
}
|
|
52
|
+
.markdown-preview.markdown-preview h3 {
|
|
53
|
+
font-size: 1.3em;
|
|
54
|
+
}
|
|
55
|
+
.markdown-preview.markdown-preview h4 {
|
|
56
|
+
font-size: 1.2em;
|
|
57
|
+
}
|
|
58
|
+
.markdown-preview.markdown-preview h5 {
|
|
59
|
+
font-size: 1em;
|
|
60
|
+
}
|
|
61
|
+
.markdown-preview.markdown-preview h6 {
|
|
62
|
+
font-size: 1em;
|
|
63
|
+
}
|
|
64
|
+
.markdown-preview.markdown-preview h3 {
|
|
65
|
+
border-bottom: 2px solid #ef7060;
|
|
66
|
+
font-size: 1.3em;
|
|
67
|
+
}
|
|
68
|
+
.markdown-preview.markdown-preview h3 strong {
|
|
69
|
+
display: inline-block;
|
|
70
|
+
font-weight: normal;
|
|
71
|
+
background: #ef7060;
|
|
72
|
+
color: #ffffff;
|
|
73
|
+
padding: 3px 10px 1px;
|
|
74
|
+
border-top-right-radius: 3px;
|
|
75
|
+
border-top-left-radius: 3px;
|
|
76
|
+
max-width: 80%;
|
|
77
|
+
vertical-align: bottom;
|
|
78
|
+
overflow: hidden;
|
|
79
|
+
text-overflow: ellipsis;
|
|
80
|
+
white-space: nowrap;
|
|
81
|
+
}
|
|
82
|
+
.markdown-preview.markdown-preview h3::after {
|
|
83
|
+
margin-left: -7px;
|
|
84
|
+
display: inline-block;
|
|
85
|
+
content: " ";
|
|
86
|
+
vertical-align: bottom;
|
|
87
|
+
border-bottom: 30px solid #efebe9;
|
|
88
|
+
border-right: 20px solid transparent;
|
|
89
|
+
}
|
|
90
|
+
.markdown-preview.markdown-preview ul,
|
|
91
|
+
.markdown-preview.markdown-preview ol {
|
|
92
|
+
padding-left: 32px;
|
|
93
|
+
}
|
|
94
|
+
.markdown-preview.markdown-preview ul {
|
|
95
|
+
list-style-type: disc;
|
|
96
|
+
}
|
|
97
|
+
.markdown-preview.markdown-preview ol {
|
|
98
|
+
list-style-type: decimal;
|
|
99
|
+
}
|
|
100
|
+
.markdown-preview.markdown-preview li {
|
|
101
|
+
margin-bottom: 0.5em;
|
|
102
|
+
}
|
|
103
|
+
.markdown-preview.markdown-preview .code_size_default {
|
|
104
|
+
line-height: 18px;
|
|
105
|
+
font-size: 14px;
|
|
106
|
+
font-weight: normal;
|
|
107
|
+
word-spacing: 0px;
|
|
108
|
+
letter-spacing: 0px;
|
|
109
|
+
}
|
|
110
|
+
.markdown-preview.markdown-preview .code_size_tight {
|
|
111
|
+
line-height: 15px;
|
|
112
|
+
font-size: 11px;
|
|
113
|
+
font-weight: normal;
|
|
114
|
+
word-spacing: -3px;
|
|
115
|
+
letter-spacing: 0px;
|
|
116
|
+
}
|
|
117
|
+
.markdown-preview.markdown-preview pre code {
|
|
118
|
+
font-family: Consolas, Inconsolata, Courier, monospace;
|
|
119
|
+
border-radius: 0px;
|
|
120
|
+
}
|
|
121
|
+
.markdown-preview.markdown-preview blockquote {
|
|
122
|
+
display: block;
|
|
123
|
+
padding: 15px 15px 15px 1rem;
|
|
124
|
+
font-size: 0.9em;
|
|
125
|
+
margin: 1em 0px;
|
|
126
|
+
color: #000000;
|
|
127
|
+
border-left: 5px solid #ef7060;
|
|
128
|
+
background: #efebe9;
|
|
129
|
+
overflow: auto;
|
|
130
|
+
overflow-wrap: normal;
|
|
131
|
+
word-break: normal;
|
|
132
|
+
}
|
|
133
|
+
.markdown-preview.markdown-preview blockquote p {
|
|
134
|
+
margin: 0px;
|
|
135
|
+
}
|
|
136
|
+
.markdown-preview.markdown-preview a {
|
|
137
|
+
text-decoration: none;
|
|
138
|
+
color: #1e6bb8;
|
|
139
|
+
overflow-wrap: break-word;
|
|
140
|
+
}
|
|
141
|
+
.markdown-preview.markdown-preview strong {
|
|
142
|
+
font-weight: bold;
|
|
143
|
+
color: #e96900;
|
|
144
|
+
}
|
|
145
|
+
.markdown-preview.markdown-preview em {
|
|
146
|
+
color: #6200ea;
|
|
147
|
+
}
|
|
148
|
+
.markdown-preview.markdown-preview del {
|
|
149
|
+
font-style: italic;
|
|
150
|
+
text-decoration: none;
|
|
151
|
+
color: #2962ff;
|
|
152
|
+
}
|
|
153
|
+
.markdown-preview.markdown-preview strong em {
|
|
154
|
+
font-weight: bold;
|
|
155
|
+
color: #c51162;
|
|
156
|
+
}
|
|
157
|
+
.markdown-preview.markdown-preview hr {
|
|
158
|
+
height: 1px;
|
|
159
|
+
margin: 1.5rem 0px;
|
|
160
|
+
border-right: none;
|
|
161
|
+
border-bottom: none;
|
|
162
|
+
border-left: none;
|
|
163
|
+
border-image: initial;
|
|
164
|
+
border-top: 1px dashed #a5a5a5;
|
|
165
|
+
}
|
|
166
|
+
.markdown-preview.markdown-preview code {
|
|
167
|
+
overflow-wrap: break-word;
|
|
168
|
+
padding: 2px 0px;
|
|
169
|
+
border-radius: 4px;
|
|
170
|
+
margin: 0px 2px;
|
|
171
|
+
color: #f82375;
|
|
172
|
+
background: rgba(239, 236, 236, 0.976);
|
|
173
|
+
}
|
|
174
|
+
.markdown-preview.markdown-preview img {
|
|
175
|
+
display: block;
|
|
176
|
+
margin: 0px auto;
|
|
177
|
+
max-width: 100%;
|
|
178
|
+
}
|
|
179
|
+
.markdown-preview.markdown-preview figcaption {
|
|
180
|
+
margin-top: 10px;
|
|
181
|
+
text-align: center;
|
|
182
|
+
color: #999999;
|
|
183
|
+
font-size: 0.7em;
|
|
184
|
+
}
|
|
185
|
+
.markdown-preview.markdown-preview table {
|
|
186
|
+
display: table;
|
|
187
|
+
width: 100%;
|
|
188
|
+
text-align: left;
|
|
189
|
+
}
|
|
190
|
+
.markdown-preview.markdown-preview tbody {
|
|
191
|
+
border: 0px;
|
|
192
|
+
}
|
|
193
|
+
.markdown-preview.markdown-preview table tr {
|
|
194
|
+
border-width: 1px 0px 0px;
|
|
195
|
+
border-right-style: initial;
|
|
196
|
+
border-bottom-style: initial;
|
|
197
|
+
border-left-style: initial;
|
|
198
|
+
border-right-color: initial;
|
|
199
|
+
border-bottom-color: initial;
|
|
200
|
+
border-left-color: initial;
|
|
201
|
+
border-image: initial;
|
|
202
|
+
border-top-style: solid;
|
|
203
|
+
border-top-color: #cccccc;
|
|
204
|
+
background-color: white;
|
|
205
|
+
}
|
|
206
|
+
.markdown-preview.markdown-preview table tr:nth-child(2n) {
|
|
207
|
+
background-color: #f8f8f8;
|
|
208
|
+
}
|
|
209
|
+
.markdown-preview.markdown-preview table tr th,
|
|
210
|
+
.markdown-preview.markdown-preview table tr td {
|
|
211
|
+
font-size: 1em;
|
|
212
|
+
border: 1px solid #cccccc;
|
|
213
|
+
padding: 0.5em 1em;
|
|
214
|
+
text-align: left;
|
|
215
|
+
}
|
|
216
|
+
.markdown-preview.markdown-preview table tr th {
|
|
217
|
+
font-weight: bold;
|
|
218
|
+
background-color: #f0f0f0;
|
|
219
|
+
}
|
|
220
|
+
.markdown-preview.markdown-preview .katex-display {
|
|
221
|
+
font-size: 1.22em;
|
|
222
|
+
}
|
|
223
|
+
.markdown-preview.markdown-preview .katex {
|
|
224
|
+
padding: 8px 3px;
|
|
225
|
+
}
|
|
226
|
+
.markdown-preview.markdown-preview .katex-display > .katex {
|
|
227
|
+
display: inline-block;
|
|
228
|
+
text-align: center;
|
|
229
|
+
padding: 3px;
|
|
230
|
+
}
|
|
231
|
+
.markdown-preview.markdown-preview .katex img {
|
|
232
|
+
display: inline-block;
|
|
233
|
+
vertical-align: middle;
|
|
234
|
+
}
|
|
235
|
+
.markdown-preview.markdown-preview a[href^="#"] sup {
|
|
236
|
+
vertical-align: super;
|
|
237
|
+
margin: 0px 2px;
|
|
238
|
+
padding: 1px 3px;
|
|
239
|
+
color: #ffffff;
|
|
240
|
+
background: #666666;
|
|
241
|
+
font-size: 0.7em;
|
|
242
|
+
}
|
|
243
|
+
.markdown-preview.markdown-preview .task-list-list {
|
|
244
|
+
list-style-type: none;
|
|
245
|
+
}
|
|
246
|
+
.markdown-preview.markdown-preview .task-list-list.checked {
|
|
247
|
+
color: #3e3e3e;
|
|
248
|
+
}
|
|
249
|
+
.markdown-preview.markdown-preview .task-list-list.uncheck {
|
|
250
|
+
color: #bfc1bf;
|
|
251
|
+
}
|
|
252
|
+
.markdown-preview.markdown-preview .task-list-list .icon_uncheck,
|
|
253
|
+
.markdown-preview.markdown-preview .task-list-list .icon_check {
|
|
254
|
+
display: inline-block;
|
|
255
|
+
vertical-align: middle;
|
|
256
|
+
margin-right: 10px;
|
|
257
|
+
}
|
|
258
|
+
.markdown-preview.markdown-preview .task-list-list .icon_check::before {
|
|
259
|
+
content: "√";
|
|
260
|
+
border: 2px solid #3e3e3e;
|
|
261
|
+
color: red;
|
|
262
|
+
}
|
|
263
|
+
.markdown-preview.markdown-preview .task-list-list .icon_uncheck::before {
|
|
264
|
+
content: "x";
|
|
265
|
+
border: 2px solid #bfc1bf;
|
|
266
|
+
color: #bfc1bf;
|
|
267
|
+
}
|
|
268
|
+
.markdown-preview.markdown-preview .task-list-list .icon_check::before,
|
|
269
|
+
.markdown-preview.markdown-preview .task-list-list .icon_uncheck::before {
|
|
270
|
+
padding: 2px 8px 2px 5px;
|
|
271
|
+
border-radius: 5px;
|
|
272
|
+
}
|
|
273
|
+
.markdown-preview.markdown-preview .toc {
|
|
274
|
+
margin-left: 25px;
|
|
275
|
+
}
|
|
276
|
+
.markdown-preview.markdown-preview .toc_item {
|
|
277
|
+
display: block;
|
|
278
|
+
}
|
|
279
|
+
.markdown-preview.markdown-preview .toc_left {
|
|
280
|
+
margin-left: 25px;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
</style>
|
|
284
|
+
<!-- The content below will be included at the end of the <head> element. --><script type="text/javascript">
|
|
285
|
+
document.addEventListener("DOMContentLoaded", function () {
|
|
286
|
+
// your code here
|
|
287
|
+
});
|
|
288
|
+
</script></head><body for="html-export">
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
<div class="crossnote markdown-preview ">
|
|
292
|
+
|
|
293
|
+
<h1 id="groupjs--dom-矩形圈选与编组">groupjs · DOM 矩形圈选与编组 </h1>
|
|
294
|
+
<p>一个轻量的浏览器侧 DOM 圈选库:支持鼠标拖拽矩形圈选、精度模式(相交/包含/中心点 + 面积阈值/IoU)、多次圈选合并、编组与覆盖层、组框四边/四角拖动实时重算、双击快速成组、组间合并、悬浮高亮,以及结果快照与事件回调。内置组级嵌套关系快照,便于构建“组嵌套查看”之类的 UI。</p>
|
|
295
|
+
<h2 id="特性">特性 </h2>
|
|
296
|
+
<ul>
|
|
297
|
+
<li>容器内拖拽矩形圈选(fixed 覆盖层,不受容器 overflow 影响)</li>
|
|
298
|
+
<li>精度策略:intersects/contains/center + minOverlapRatio + overlapMetric(element/IoU)</li>
|
|
299
|
+
<li>冲突处理:none/leaf/best(避免误选大容器)</li>
|
|
300
|
+
<li>多次圈选:replace/add/subtract/toggle/auto(Shift/Alt/Ctrl/⌘)</li>
|
|
301
|
+
<li>编组模式:每次拖拽生成一组;组覆盖层可见/隐藏、删除</li>
|
|
302
|
+
<li>组覆盖层:四边+四角拖动,拖动过程中实时重算命中</li>
|
|
303
|
+
<li>组合并:新建组与其它组相交时,工具条“合并”并选择目标组合并</li>
|
|
304
|
+
<li>双击快速成组:以双击元素外框作为选择框直接生成一组</li>
|
|
305
|
+
<li>悬浮高亮:hoverHighlight+hoverClass</li>
|
|
306
|
+
<li>完整快照:单选/编组含 flat 并集、hidden、groupRects、groupNesting(组级嵌套)</li>
|
|
307
|
+
<li>事件:onChange、onSelectionEnd;控制器:onSelectionEnd(订阅)与 waitForSelectionEnd(一次性)</li>
|
|
308
|
+
</ul>
|
|
309
|
+
<h2 id="安装">安装 </h2>
|
|
310
|
+
<p>可直接拷贝 <code>src/index.ts</code> 使用,或自行打包。</p>
|
|
311
|
+
<p>开发/打包:</p>
|
|
312
|
+
<pre data-role="codeBlock" data-info="bash" class="language-bash bash"><code><span class="token function">npm</span> i
|
|
313
|
+
<span class="token function">npm</span> run dev <span class="token comment"># 本地预览 demo(Vite)</span>
|
|
314
|
+
<span class="token function">npm</span> run build <span class="token comment"># 产出 dist(es/umd/types)</span>
|
|
315
|
+
</code></pre><h2 id="快速上手浏览器">快速上手(浏览器) </h2>
|
|
316
|
+
<pre data-role="codeBlock" data-info="ts" class="language-ts ts"><code><span class="token keyword keyword-import">import</span> enableMarqueeSelection <span class="token keyword keyword-from">from</span> <span class="token string">'/src/index.ts'</span>
|
|
317
|
+
|
|
318
|
+
<span class="token keyword keyword-const">const</span> ctrl <span class="token operator">=</span> <span class="token function">enableMarqueeSelection</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
|
|
319
|
+
container<span class="token operator">:</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'container'</span><span class="token punctuation">)</span><span class="token operator">!</span><span class="token punctuation">,</span>
|
|
320
|
+
selectable<span class="token operator">:</span> <span class="token string">'*'</span><span class="token punctuation">,</span>
|
|
321
|
+
selectionMode<span class="token operator">:</span> <span class="token string">'intersects'</span><span class="token punctuation">,</span>
|
|
322
|
+
minOverlapRatio<span class="token operator">:</span> <span class="token number">0.2</span><span class="token punctuation">,</span>
|
|
323
|
+
overlapMetric<span class="token operator">:</span> <span class="token string">'element'</span><span class="token punctuation">,</span>
|
|
324
|
+
conflictStrategy<span class="token operator">:</span> <span class="token string">'best'</span><span class="token punctuation">,</span>
|
|
325
|
+
multi<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
|
|
326
|
+
combineMode<span class="token operator">:</span> <span class="token string">'auto'</span><span class="token punctuation">,</span>
|
|
327
|
+
groupMode<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
|
|
328
|
+
groupOverlayClass<span class="token operator">:</span> <span class="token keyword keyword-undefined">undefined</span><span class="token punctuation">,</span>
|
|
329
|
+
hoverHighlight<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
|
|
330
|
+
hoverClass<span class="token operator">:</span> <span class="token string">'hovered'</span><span class="token punctuation">,</span>
|
|
331
|
+
quickGroupOnDblClick<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
|
|
332
|
+
<span class="token comment">// 结果回调(一次完整拖拽/操作结束)</span>
|
|
333
|
+
<span class="token function-variable function">onSelectionEnd</span><span class="token operator">:</span> <span class="token punctuation">(</span>snapshot<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
|
|
334
|
+
<span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'snapshot'</span><span class="token punctuation">,</span> snapshot<span class="token punctuation">)</span>
|
|
335
|
+
<span class="token punctuation">}</span><span class="token punctuation">,</span>
|
|
336
|
+
<span class="token punctuation">}</span><span class="token punctuation">)</span>
|
|
337
|
+
</code></pre><h2 id="api">API </h2>
|
|
338
|
+
<h3 id="enablemarqueeselectionoptions--controller">enableMarqueeSelection(options) => controller </h3>
|
|
339
|
+
<p>options(主要项):</p>
|
|
340
|
+
<ul>
|
|
341
|
+
<li>container: HTMLElement 必填,圈选容器</li>
|
|
342
|
+
<li>selectable?: string 默认 'img',可被圈选的选择器</li>
|
|
343
|
+
<li>selectionMode?: 'intersects' | 'contains' | 'center' 默认 'intersects'</li>
|
|
344
|
+
<li>minOverlapRatio?: number 相交模式下的最小重叠阈值(0~1)</li>
|
|
345
|
+
<li>overlapMetric?: 'element' | 'iou' 重叠指标</li>
|
|
346
|
+
<li>selectedClass?: string 默认 'selected'</li>
|
|
347
|
+
<li>onChange?: (payload) => void 实时变更(单选/编组)</li>
|
|
348
|
+
<li>preventAncestorSelection?: boolean 默认 true,避免误选父容器</li>
|
|
349
|
+
<li>conflictStrategy?: 'none' | 'leaf' | 'best' 父子冲突处理</li>
|
|
350
|
+
<li>multi?: boolean 多次圈选</li>
|
|
351
|
+
<li>combineMode?: 'replace' | 'add' | 'subtract' | 'toggle' | 'auto'</li>
|
|
352
|
+
<li>groupMode?: boolean 开启编组</li>
|
|
353
|
+
<li>groupOverlayClass?: string 组覆盖层类名(可自定义样式)</li>
|
|
354
|
+
<li>hoverHighlight?: boolean 悬浮高亮</li>
|
|
355
|
+
<li>hoverClass?: string 悬浮高亮类</li>
|
|
356
|
+
<li>onSelectionEnd?: (snapshot) => void 一次交互结束</li>
|
|
357
|
+
<li>quickGroupOnDblClick?: boolean 双击快速成组</li>
|
|
358
|
+
<li>quickGroupSelector?: string 双击匹配祖先选择器后再成组</li>
|
|
359
|
+
</ul>
|
|
360
|
+
<p>controller:</p>
|
|
361
|
+
<ul>
|
|
362
|
+
<li>destroy(): void 卸载</li>
|
|
363
|
+
<li>getGroups(): Element[][] 获取所有组</li>
|
|
364
|
+
<li>clearGroups(): void 清空所有组</li>
|
|
365
|
+
<li>removeGroup(index: number): boolean 删除指定组</li>
|
|
366
|
+
<li>setGroupVisibility(index: number, hidden: boolean): boolean 设置组可见</li>
|
|
367
|
+
<li>toggleGroupVisibility(index: number): boolean 切换可见</li>
|
|
368
|
+
<li>getSelectionResult(): MarqueeSelectionSnapshot 获取当前快照</li>
|
|
369
|
+
<li>onSelectionEnd(handler): () => void 订阅下一次结束</li>
|
|
370
|
+
<li>waitForSelectionEnd(): Promise<marqueeselectionsnapshot> 等待下一次结束</marqueeselectionsnapshot></li>
|
|
371
|
+
<li>getGroupNesting(): { parents: (number|null)[]; children: number[][]; roots: number[] } | null 获取组级嵌套(groupMode 下有效)</li>
|
|
372
|
+
</ul>
|
|
373
|
+
<h3 id="快照结构-marqueeselectionsnapshot">快照结构 MarqueeSelectionSnapshot </h3>
|
|
374
|
+
<ul>
|
|
375
|
+
<li>单选:<code>{ type: 'single'; selected: Element[] }</code></li>
|
|
376
|
+
<li>编组:<pre data-role="codeBlock" data-info="ts" class="language-ts ts"><code><span class="token punctuation">{</span>
|
|
377
|
+
type<span class="token operator">:</span> <span class="token string">'groups'</span>
|
|
378
|
+
groups<span class="token operator">:</span> Element<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">// 每组元素集</span>
|
|
379
|
+
flat<span class="token operator">:</span> Element<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">// 全部并集</span>
|
|
380
|
+
hidden<span class="token operator">:</span> <span class="token builtin">boolean</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">// 各组隐藏状态</span>
|
|
381
|
+
groupRects<span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">{</span> left<span class="token operator">:</span><span class="token builtin">number</span><span class="token punctuation">;</span> top<span class="token operator">:</span><span class="token builtin">number</span><span class="token punctuation">;</span> width<span class="token operator">:</span><span class="token builtin">number</span><span class="token punctuation">;</span> height<span class="token operator">:</span><span class="token builtin">number</span> <span class="token punctuation">}</span> <span class="token operator">|</span> <span class="token keyword keyword-null">null</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">// 各组外接框</span>
|
|
382
|
+
groupNesting<span class="token operator">:</span> <span class="token punctuation">{</span>
|
|
383
|
+
parents<span class="token operator">:</span> <span class="token punctuation">(</span><span class="token builtin">number</span><span class="token operator">|</span><span class="token keyword keyword-null">null</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token punctuation">]</span>
|
|
384
|
+
children<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token punctuation">]</span>
|
|
385
|
+
roots<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">[</span><span class="token punctuation">]</span>
|
|
386
|
+
<span class="token punctuation">}</span>
|
|
387
|
+
<span class="token punctuation">}</span>
|
|
388
|
+
</code></pre></li>
|
|
389
|
+
</ul>
|
|
390
|
+
<p>groupNesting 说明:依据组外接矩形完全包含关系,给每个组选取“面积最小的包含者”作为其最近父组,从而形成多层嵌套树(roots 为无父组)。这使得你能在 UI 中构建“组嵌套查看”。</p>
|
|
391
|
+
<h2 id="高级能力">高级能力 </h2>
|
|
392
|
+
<ul>
|
|
393
|
+
<li>
|
|
394
|
+
<p>组覆盖层拖动:</p>
|
|
395
|
+
<ul>
|
|
396
|
+
<li>覆盖层四边/四角(nw/ne/sw/se)句柄拖动,实时更新圈选命中与 DOM 选中态;</li>
|
|
397
|
+
<li>鼠标松开后固定结果,并触发 onSelectionEnd。</li>
|
|
398
|
+
</ul>
|
|
399
|
+
</li>
|
|
400
|
+
<li>
|
|
401
|
+
<p>组合并:</p>
|
|
402
|
+
<ul>
|
|
403
|
+
<li>当新建组与其他组外接框相交时,工具条显示“合并”;</li>
|
|
404
|
+
<li>点击弹出合并面板,勾选要合并的组后确认;</li>
|
|
405
|
+
<li>被合并组删除,当前组元素替换为并集,自动刷新覆盖层与快照。</li>
|
|
406
|
+
</ul>
|
|
407
|
+
</li>
|
|
408
|
+
<li>
|
|
409
|
+
<p>双击快速成组:</p>
|
|
410
|
+
<ul>
|
|
411
|
+
<li>开启 quickGroupOnDblClick 后,双击元素(或其 closest(quickGroupSelector) 祖先)会以该元素外框作为选择框迅速生成一组。</li>
|
|
412
|
+
</ul>
|
|
413
|
+
</li>
|
|
414
|
+
<li>
|
|
415
|
+
<p>悬浮高亮:</p>
|
|
416
|
+
<ul>
|
|
417
|
+
<li>hoverHighlight + hoverClass,非拖拽时鼠标悬浮可提示可圈选元素。</li>
|
|
418
|
+
</ul>
|
|
419
|
+
</li>
|
|
420
|
+
</ul>
|
|
421
|
+
<h2 id="demo">Demo </h2>
|
|
422
|
+
<ul>
|
|
423
|
+
<li>项目内置 <code>index.html</code> 演示:右上角浮层面板展示结果;</li>
|
|
424
|
+
<li>面板支持“平铺查看 / 组嵌套查看”切换;嵌套查看直接使用库返回的 <code>snapshot.groupNesting</code>。</li>
|
|
425
|
+
</ul>
|
|
426
|
+
<h2 id="开发">开发 </h2>
|
|
427
|
+
<pre data-role="codeBlock" data-info="bash" class="language-bash bash"><code><span class="token function">npm</span> run dev <span class="token comment"># 起 Vite 开发服务</span>
|
|
428
|
+
<span class="token function">npm</span> run build <span class="token comment"># 产出 dist(es/umd/types)</span>
|
|
429
|
+
</code></pre><h2 id="license">License </h2>
|
|
430
|
+
<p>MIT</p>
|
|
431
|
+
|
|
432
|
+
</div>
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
</body></html>
|
package/README.md
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# groupjs · DOM 矩形圈选与编组
|
|
2
|
+
|
|
3
|
+
一个轻量的浏览器侧 DOM 圈选库:支持鼠标拖拽矩形圈选、精度模式(相交/包含/中心点 + 面积阈值/IoU)、多次圈选合并、编组与覆盖层、组框四边/四角拖动实时重算、双击快速成组、组间合并、悬浮高亮,以及结果快照与事件回调。内置组级嵌套关系快照,便于构建“组嵌套查看”之类的 UI。
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
|
|
7
|
+
- 容器内拖拽矩形圈选(fixed 覆盖层,不受容器 overflow 影响)
|
|
8
|
+
- 精度策略:intersects/contains/center + minOverlapRatio + overlapMetric(element/IoU)
|
|
9
|
+
- 冲突处理:none/leaf/best(避免误选大容器)
|
|
10
|
+
- 多次圈选:replace/add/subtract/toggle/auto(Shift/Alt/Ctrl/⌘)
|
|
11
|
+
- 编组模式:每次拖拽生成一组;组覆盖层可见/隐藏、删除
|
|
12
|
+
- 组覆盖层:四边+四角拖动,拖动过程中实时重算命中
|
|
13
|
+
- 组合并:新建组与其它组相交时,工具条“合并”并选择目标组合并
|
|
14
|
+
- 双击快速成组:以双击元素外框作为选择框直接生成一组
|
|
15
|
+
- 悬浮高亮:hoverHighlight+hoverClass
|
|
16
|
+
- 选择约束:allowIntersectionSelection / allowContainmentSelection / allowUnionSelection 控制是否允许“与已有选择部分交叉”“包含/被包含(父子)”与“新增并集”;当不允许时,拖拽/双击/覆盖层尺寸调整都会以红框提示并取消本次操作
|
|
17
|
+
- 完整快照:单选/编组含 flat 并集、hidden、groupRects、groupNesting(组级嵌套)
|
|
18
|
+
- 事件:onChange、onSelectionEnd;控制器:onSelectionEnd(订阅)与 waitForSelectionEnd(一次性)
|
|
19
|
+
|
|
20
|
+
## 安装
|
|
21
|
+
|
|
22
|
+
可直接拷贝 `src/index.ts` 使用,或自行打包。
|
|
23
|
+
|
|
24
|
+
## 位置注入与 position.js 用法
|
|
25
|
+
|
|
26
|
+
本项目支持为 HTML 元素自动注入源码位置信息(如行号、列号、起止 offset),便于调试、可视化、AST 映射等高级用例。
|
|
27
|
+
|
|
28
|
+
### 1. 生成位置信息注入脚本
|
|
29
|
+
|
|
30
|
+
运行以下命令,会自动解析 `index.html`,为每个 DOM 元素生成唯一选择器及其源码位置信息,并输出注入脚本 `src/position-injector.js`:
|
|
31
|
+
|
|
32
|
+
`npm run position`
|
|
33
|
+
|
|
34
|
+
开发/打包:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm i
|
|
38
|
+
npm run dev # 本地预览 demo(Vite)
|
|
39
|
+
npm run build # 产出 dist(es/umd/types)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 快速上手(浏览器)
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import enableMarqueeSelection from "/src/index.ts";
|
|
46
|
+
|
|
47
|
+
const ctrl = enableMarqueeSelection({
|
|
48
|
+
container: document.getElementById("container")!,
|
|
49
|
+
selectable: "*",
|
|
50
|
+
selectionMode: "intersects",
|
|
51
|
+
minOverlapRatio: 0.2,
|
|
52
|
+
overlapMetric: "element",
|
|
53
|
+
conflictStrategy: "best",
|
|
54
|
+
multi: true,
|
|
55
|
+
combineMode: "auto",
|
|
56
|
+
groupMode: true,
|
|
57
|
+
groupOverlayClass: undefined,
|
|
58
|
+
hoverHighlight: true,
|
|
59
|
+
hoverClass: "hovered",
|
|
60
|
+
quickGroupOnDblClick: true,
|
|
61
|
+
// 结果回调(一次完整拖拽/操作结束)
|
|
62
|
+
onSelectionEnd: (snapshot) => {
|
|
63
|
+
console.log("snapshot", snapshot);
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## API
|
|
69
|
+
|
|
70
|
+
### enableMarqueeSelection(options) => controller
|
|
71
|
+
|
|
72
|
+
options(主要项):
|
|
73
|
+
|
|
74
|
+
- container: HTMLElement 必填,圈选容器
|
|
75
|
+
- selectable?: string 默认 'img',可被圈选的选择器
|
|
76
|
+
- selectionMode?: 'intersects' | 'contains' | 'center' 默认 'intersects'
|
|
77
|
+
- minOverlapRatio?: number 相交模式下的最小重叠阈值(0~1)
|
|
78
|
+
- overlapMetric?: 'element' | 'iou' 重叠指标
|
|
79
|
+
- selectedClass?: string 默认 'selected'
|
|
80
|
+
- onChange?: (payload) => void 实时变更(单选/编组)
|
|
81
|
+
- preventAncestorSelection?: boolean 默认 true,避免误选父容器
|
|
82
|
+
- conflictStrategy?: 'none' | 'leaf' | 'best' 父子冲突处理
|
|
83
|
+
- multi?: boolean 多次圈选
|
|
84
|
+
- combineMode?: 'replace' | 'add' | 'subtract' | 'toggle' | 'auto'
|
|
85
|
+
- groupMode?: boolean 开启编组
|
|
86
|
+
- groupOverlayClass?: string 组覆盖层类名(可自定义样式)
|
|
87
|
+
- hoverHighlight?: boolean 悬浮高亮
|
|
88
|
+
- hoverClass?: string 悬浮高亮类
|
|
89
|
+
- onSelectionEnd?: (snapshot) => void 一次交互结束
|
|
90
|
+
- quickGroupOnDblClick?: boolean 双击快速成组
|
|
91
|
+
- quickGroupSelector?: string 双击匹配祖先选择器后再成组
|
|
92
|
+
- allowIntersectionSelection?: boolean 默认 true。若为 false,则只禁止“部分交叉”关系:即新集合与已有集合间存在交集且双方都还有各自独有的元素。
|
|
93
|
+
- allowContainmentSelection?: boolean 默认 true。仅当 allowIntersectionSelection=false 时生效;true 表示仍允许“包含/被包含”关系(A 是 B 的子集或父集),false 表示包含也禁止,仅保留完全不相交或完全相等两种情况。
|
|
94
|
+
- allowUnionSelection?: boolean 默认 true。若为 false,则当已存在选择/组时,禁止新增元素(并集)。
|
|
95
|
+
- toolbarButtons?: { label; title?; className?; onClick?(ctx) }[] 追加自定义工具栏按钮
|
|
96
|
+
|
|
97
|
+
controller:
|
|
98
|
+
|
|
99
|
+
- destroy(): void 卸载
|
|
100
|
+
- getGroups(): Element[][] 获取所有组
|
|
101
|
+
- clearGroups(): void 清空所有组
|
|
102
|
+
- removeGroup(index: number): boolean 删除指定组
|
|
103
|
+
- setGroupVisibility(index: number, hidden: boolean): boolean 设置组可见
|
|
104
|
+
- toggleGroupVisibility(index: number): boolean 切换可见
|
|
105
|
+
- getSelectionResult(): MarqueeSelectionSnapshot 获取当前快照
|
|
106
|
+
- onSelectionEnd(handler): () => void 订阅下一次结束
|
|
107
|
+
- waitForSelectionEnd(): Promise<MarqueeSelectionSnapshot> 等待下一次结束
|
|
108
|
+
- getGroupNesting(): { parents: (number|null)[]; children: number[][]; roots: number[] } | null 获取组级嵌套(groupMode 下有效)
|
|
109
|
+
|
|
110
|
+
### 快照结构 MarqueeSelectionSnapshot
|
|
111
|
+
|
|
112
|
+
- 单选:`{ type: 'single'; selected: Element[] }`
|
|
113
|
+
- 编组:
|
|
114
|
+
```ts
|
|
115
|
+
{
|
|
116
|
+
type: 'groups'
|
|
117
|
+
groups: Element[][] // 每组元素集
|
|
118
|
+
flat: Element[] // 全部并集
|
|
119
|
+
hidden: boolean[] // 各组隐藏状态
|
|
120
|
+
groupRects: ({ left:number; top:number; width:number; height:number } | null)[] // 各组外接框
|
|
121
|
+
groupNesting: {
|
|
122
|
+
parents: (number|null)[]
|
|
123
|
+
children: number[][]
|
|
124
|
+
roots: number[]
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
groupNesting 说明:依据组外接矩形完全包含关系,给每个组选取“面积最小的包含者”作为其最近父组,从而形成多层嵌套树(roots 为无父组)。这使得你能在 UI 中构建“组嵌套查看”。
|
|
130
|
+
|
|
131
|
+
## 高级能力
|
|
132
|
+
|
|
133
|
+
- 组覆盖层拖动:
|
|
134
|
+
|
|
135
|
+
- 覆盖层四边/四角(nw/ne/sw/se)句柄拖动,实时更新圈选命中与 DOM 选中态;
|
|
136
|
+
- 鼠标松开后固定结果,并触发 onSelectionEnd。
|
|
137
|
+
- 当禁用交叉/包含/并集时(allowIntersectionSelection / allowContainmentSelection / allowUnionSelection),若本次调整会产生被禁止的部分交叉、包含或新增元素,将以红色边框与浅红底提示,并在松开时取消本次调整。
|
|
138
|
+
|
|
139
|
+
- 组合并:
|
|
140
|
+
|
|
141
|
+
- 当新建组与其他组外接框相交时,工具条显示“合并”;
|
|
142
|
+
- 点击弹出合并面板,勾选要合并的组后确认;
|
|
143
|
+
- 被合并组删除,当前组元素替换为并集,自动刷新覆盖层与快照。
|
|
144
|
+
|
|
145
|
+
- 双击快速成组:
|
|
146
|
+
|
|
147
|
+
- 开启 quickGroupOnDblClick 后,双击元素(或其 closest(quickGroupSelector) 祖先)会以该元素外框作为选择框迅速生成一组。
|
|
148
|
+
- 亦会遵守 allowIntersectionSelection / allowContainmentSelection / allowUnionSelection;违规则提示并取消。
|
|
149
|
+
|
|
150
|
+
- 自定义工具栏按钮:
|
|
151
|
+
|
|
152
|
+
- 通过 options.toolbarButtons 追加按钮到每个组的工具栏;
|
|
153
|
+
- onClick(ctx) 回调提供:
|
|
154
|
+
- ctx.index 当前组索引
|
|
155
|
+
- ctx.group 当前组元素数组
|
|
156
|
+
- ctx.controller 控制器实例
|
|
157
|
+
- ctx.getSnapshot() 获取最新快照
|
|
158
|
+
- ctx.refresh() 触发重绘覆盖层并广播 onSelectionEnd
|
|
159
|
+
- 示例:
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
enableMarqueeSelection({
|
|
163
|
+
// ...existing options...
|
|
164
|
+
toolbarButtons: [
|
|
165
|
+
{
|
|
166
|
+
label: "导出",
|
|
167
|
+
title: "导出该组元素信息",
|
|
168
|
+
onClick: ({ index, group, getSnapshot }) => {
|
|
169
|
+
const ids = group.map((el) => (el as HTMLElement).id).join(",");
|
|
170
|
+
console.log("组", index + 1, "元素ID:", ids);
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
label: "反选本组",
|
|
175
|
+
onClick: ({ index, controller, getSnapshot, refresh }) => {
|
|
176
|
+
const snap = getSnapshot();
|
|
177
|
+
if (snap.type !== "groups") return;
|
|
178
|
+
// 简单示例:把该组设置为隐藏/显示切换
|
|
179
|
+
controller.toggleGroupVisibility(index);
|
|
180
|
+
refresh();
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
],
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
- 悬浮高亮:
|
|
188
|
+
- hoverHighlight + hoverClass,非拖拽时鼠标悬浮可提示可圈选元素。
|
|
189
|
+
|
|
190
|
+
## Demo
|
|
191
|
+
|
|
192
|
+
- 项目内置 `index.html` 演示:右上角浮层面板展示结果;
|
|
193
|
+
- 面板支持“平铺查看 / 组嵌套查看”切换;嵌套查看直接使用库返回的 `snapshot.groupNesting`。
|
|
194
|
+
|
|
195
|
+
## 开发
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
npm run dev # 起 Vite 开发服务
|
|
199
|
+
npm run build # 产出 dist(es/umd/types)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## License
|
|
203
|
+
|
|
204
|
+
MIT
|