@363045841yyt/klinechart 0.4.7 → 0.5.0-alpha.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.
- package/README.md +7 -1
- package/dist/index.cjs +9 -9
- package/dist/index.js +2588 -1395
- package/dist/klinechart.css +1 -1
- package/dist/src/App.vue.d.ts +3 -1
- package/dist/src/api/data/unified.d.ts +6 -2
- package/dist/src/components/KLineChart.vue.d.ts +6 -1
- package/dist/src/components/LeftToolbar.vue.d.ts +17 -0
- package/dist/src/core/chart.d.ts +5 -0
- package/dist/src/core/drawing/index.d.ts +37 -0
- package/dist/src/core/drawing/interaction.d.ts +40 -0
- package/dist/src/core/drawing/plugin.d.ts +8 -0
- package/dist/src/plugin/types.d.ts +106 -8
- package/package.json +4 -1
package/dist/klinechart.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
.kline-tooltip[data-v-d0fe85e6]{z-index:10;color:#000000c7;pointer-events:none;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);background:#ffffffeb;border:1px solid #0000001f;border-radius:8px;min-width:200px;max-width:260px;padding:10px 12px;font-size:12px;line-height:1.4;position:absolute;box-shadow:0 6px 18px #0000001f}.kline-tooltip__title[data-v-d0fe85e6]{justify-content:space-between;gap:10px;margin-bottom:6px;font-weight:600;display:flex}.kline-tooltip__grid[data-v-d0fe85e6]{grid-template-columns:1fr;gap:2px;display:grid}.kline-tooltip__grid .row[data-v-d0fe85e6]{justify-content:space-between;gap:10px;display:flex}.kline-tooltip__grid .row span[data-v-d0fe85e6]:first-child{color:#0000008f}@supports (anchor-name:--kmap-anchor) and (position-anchor:--kmap-anchor){.kline-tooltip.use-anchor[data-v-d0fe85e6]{position-anchor:--kline-tooltip-anchor;left:anchor(left);top:anchor(top);position:absolute}.kline-tooltip.use-anchor.anchor-right-bottom[data-v-d0fe85e6]{transform:translate(14px,14px)}.kline-tooltip.use-anchor.anchor-left-bottom[data-v-d0fe85e6]{transform:translate(calc(-100% - 14px),14px)}}.marker-tooltip[data-v-5574cc25]{z-index:10;color:#000000c7;pointer-events:none;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);background:#ffffffeb;border:1px solid #0000001f;border-radius:8px;min-width:180px;max-width:260px;padding:10px 12px;font-size:12px;line-height:1.4;position:absolute;box-shadow:0 6px 18px #0000001f}.marker-tooltip__title[data-v-5574cc25]{justify-content:space-between;gap:10px;margin-bottom:6px;font-weight:600;display:flex}.marker-tooltip__content[data-v-5574cc25]{grid-template-columns:1fr;gap:2px;display:grid}.marker-tooltip__content .row[data-v-5574cc25]{justify-content:space-between;gap:10px;display:flex}.marker-tooltip__content .row span[data-v-5574cc25]:first-child{color:#0000008f}@supports (anchor-name:--kmap-anchor) and (position-anchor:--kmap-anchor){.marker-tooltip.use-anchor[data-v-5574cc25]{position-anchor:--marker-tooltip-anchor;left:anchor(left);top:anchor(top);position:absolute}.marker-tooltip.use-anchor.anchor-right-bottom[data-v-5574cc25]{transform:translate(12px,12px)}.marker-tooltip.use-anchor.anchor-left-bottom[data-v-5574cc25]{transform:translate(calc(-100% - 12px),12px)}}.params-overlay[data-v-c14eedcc]{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;background:#0000004d;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.indicator-params[data-v-c14eedcc]{background:#fff;border:1px solid #e0e0e0;border-radius:12px;width:90vw;min-width:340px;max-width:420px;overflow:hidden;box-shadow:0 8px 40px #00000026}.params-header[data-v-c14eedcc]{background:#f8f8f8;border-bottom:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:16px 20px;display:flex}.header-left[data-v-c14eedcc]{align-items:baseline;gap:8px;display:flex}.header-right[data-v-c14eedcc]{align-items:center;gap:8px;display:flex}.params-title[data-v-c14eedcc]{color:#1a1a1a;letter-spacing:.2px;font-size:14px;font-weight:600}.params-subtitle[data-v-c14eedcc]{color:#999;font-size:11px}.toggle-desc-btn[data-v-c14eedcc]{cursor:pointer;color:#888;background:#fff;border:1px solid #e0e0e0;border-radius:6px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:all .2s;display:flex}.toggle-desc-btn[data-v-c14eedcc]:hover{color:#555;background:#f0f0f0;border-color:#ccc}.toggle-desc-btn.active[data-v-c14eedcc]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.toggle-desc-btn svg[data-v-c14eedcc]{width:14px;height:14px}.params-close[data-v-c14eedcc]{cursor:pointer;color:#888;background:#fff;border:1px solid #e0e0e0;border-radius:6px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:background .15s,color .15s,border-color .15s;display:flex}.params-close[data-v-c14eedcc]:hover{color:#333;background:#f0f0f0;border-color:#ccc}.params-close svg[data-v-c14eedcc]{width:14px;height:14px}.indicator-description[data-v-c14eedcc]{background:#f0f7ff;border-bottom:1px solid #d6e8f5;padding:12px 20px}.indicator-description p[data-v-c14eedcc]{color:#2c5282;margin:0;font-size:12px;line-height:1.6}.params-body[data-v-c14eedcc]{flex-direction:column;gap:10px;padding:16px 20px;display:flex}.param-item[data-v-c14eedcc]{background:#f8f8f8;border:1px solid #e8e8e8;border-radius:8px;padding:10px 14px;transition:border-color .2s}.param-item[data-v-c14eedcc]:has(.param-input:focus){border-color:#bbb}.param-item.has-desc[data-v-c14eedcc]{padding:10px 14px 8px}.param-header[data-v-c14eedcc]{justify-content:space-between;align-items:center;gap:16px;display:flex}.param-label[data-v-c14eedcc]{flex-direction:column;gap:3px;display:flex}.param-label-text[data-v-c14eedcc]{color:#333;font-size:13px;font-weight:500}.param-range[data-v-c14eedcc]{color:#999;font-size:11px}.param-description[data-v-c14eedcc]{color:#666;border-top:1px dashed #e0e0e0;margin-top:8px;padding-top:8px;font-size:11px;line-height:1.5}.input-wrapper[data-v-c14eedcc]{background:#fff;border:1px solid #d0d0d0;border-radius:7px;align-items:stretch;height:32px;transition:border-color .2s;display:flex;overflow:hidden}.input-wrapper[data-v-c14eedcc]:focus-within{border-color:#999}.stepper-btn[data-v-c14eedcc]{cursor:pointer;color:#666;background:#f0f0f0;border:none;flex-shrink:0;justify-content:center;align-items:center;width:28px;font-size:15px;font-weight:400;line-height:1;transition:background .15s,color .15s;display:flex}.stepper-btn[data-v-c14eedcc]:hover:not(:disabled){color:#333;background:#e0e0e0}.stepper-btn[data-v-c14eedcc]:disabled{color:#ccc;cursor:not-allowed}.param-input[data-v-c14eedcc]{text-align:center;color:#1a1a1a;appearance:textfield;background:0 0;border:none;border-left:1px solid #e8e8e8;border-right:1px solid #e8e8e8;width:60px;font-size:13px;font-weight:600}.param-input[data-v-c14eedcc]::-webkit-inner-spin-button{-webkit-appearance:none}.param-input[data-v-c14eedcc]::-webkit-outer-spin-button{-webkit-appearance:none}.param-input[data-v-c14eedcc]:focus{outline:none}.params-footer[data-v-c14eedcc]{background:#f8f8f8;border-top:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:12px 20px;display:flex}.footer-right[data-v-c14eedcc]{gap:8px;display:flex}.params-btn[data-v-c14eedcc]{cursor:pointer;border:1px solid #0000;border-radius:7px;align-items:center;gap:5px;padding:6px 14px;font-size:13px;font-weight:500;line-height:1.4;transition:all .15s;display:flex}.params-btn svg[data-v-c14eedcc]{flex-shrink:0;width:12px;height:12px}.params-btn.reset[data-v-c14eedcc]{color:#666;background:0 0;border-color:#d0d0d0}.params-btn.reset[data-v-c14eedcc]:hover{color:#e74c3c;background:#e74c3c14;border-color:#c0392b}.params-btn.cancel[data-v-c14eedcc]{color:#666;background:0 0;border-color:#d0d0d0}.params-btn.cancel[data-v-c14eedcc]:hover{color:#333;background:#f0f0f0;border-color:#bbb}.params-btn.confirm[data-v-c14eedcc]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.params-btn.confirm[data-v-c14eedcc]:hover{background:#333;border-color:#333;transform:translateY(-1px);box-shadow:0 2px 10px #00000026}.params-btn.confirm[data-v-c14eedcc]:active{box-shadow:none;transform:translateY(0)}.overlay-enter-active[data-v-c14eedcc],.overlay-leave-active[data-v-c14eedcc]{transition:opacity .2s}.overlay-enter-from[data-v-c14eedcc],.overlay-leave-to[data-v-c14eedcc]{opacity:0}.modal-enter-active[data-v-c14eedcc]{transition:all .22s cubic-bezier(.34,1.56,.64,1)}.modal-leave-active[data-v-c14eedcc]{transition:all .16s ease-in}.modal-enter-from[data-v-c14eedcc]{opacity:0;transform:scale(.88)translateY(-16px)}.modal-leave-to[data-v-c14eedcc]{opacity:0;transform:scale(.94)translateY(8px)}.slide-enter-active[data-v-c14eedcc],.slide-leave-active[data-v-c14eedcc]{transition:all .2s;overflow:hidden}.slide-enter-from[data-v-c14eedcc],.slide-leave-to[data-v-c14eedcc]{opacity:0;max-height:0;margin-top:0;padding-top:0;padding-bottom:0}.indicator-selector[data-v-4b90c954]{width:80%;margin:20px;position:relative}.indicator-scroll-container[data-v-4b90c954]{scrollbar-width:none;-webkit-overflow-scrolling:touch;text-align:center;width:100%;overflow:auto hidden}.indicator-scroll-container[data-v-4b90c954]::-webkit-scrollbar{display:none}.indicator-list[data-v-4b90c954]{gap:8px;margin:0 auto;padding:2px;display:inline-flex}.indicator-divider[data-v-4b90c954]{background:#d9d9d9;align-self:center;width:1px;height:20px}.indicator-item[data-v-4b90c954]{align-items:center;gap:4px;display:flex}.indicator-item.draggable[data-v-4b90c954],.indicator-item.draggable .indicator-btn[data-v-4b90c954],.indicator-item.draggable[data-v-4b90c954]:hover,.indicator-item.draggable:hover .indicator-btn[data-v-4b90c954]{cursor:move}.indicator-item.is-dragging[data-v-4b90c954]{opacity:.6}.indicator-item.drag-over .indicator-btn[data-v-4b90c954]{border-color:#1a1a1a;box-shadow:0 0 0 2px #1a1a1a1f}.indicator-btn-wrapper[data-v-4b90c954]{position:relative}.indicator-btn[data-v-4b90c954]{color:#666;cursor:pointer;white-space:nowrap;background:#fff;border:1px solid #e0e0e0;border-radius:16px;flex-shrink:0;justify-content:center;align-items:center;gap:4px;padding:6px 16px;font-size:13px;font-weight:500;transition:all .3s;display:flex;position:relative;overflow:hidden}.indicator-btn[data-v-4b90c954]:hover:not(.hovering){color:#333;background:#f8f8f8;border-color:#ccc}.indicator-btn.active[data-v-4b90c954]{color:#1a1a1a;background:#f8f8f8;border-color:#1a1a1a}.indicator-btn.active[data-v-4b90c954]:hover:not(.hovering){background:#f0f0f0;border-color:#333}.btn-content[data-v-4b90c954]{z-index:1;position:relative}.param-hint[data-v-4b90c954]{opacity:.85;font-size:11px}.hover-overlay[data-v-4b90c954]{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:2;background:#ffffffd9;border-radius:16px;justify-content:center;align-items:center;gap:4px;display:flex;position:absolute;inset:0}.action-btn[data-v-4b90c954]{color:#666;cursor:pointer;background:0 0;border:none;border-radius:50%;justify-content:center;align-items:center;width:24px;height:24px;padding:0;transition:all .2s;display:flex}.action-btn[data-v-4b90c954]:hover{color:#333;background:#0000000f}.settings-btn[data-v-4b90c954]:hover{color:#1a1a1a}.remove-btn[data-v-4b90c954]:hover{color:#ff4d4f}.divider[data-v-4b90c954]{background:#e0e0e0;width:1px;height:14px}.add-btn[data-v-4b90c954]{anchor-name:--indicator-add-btn;color:#999;cursor:pointer;background:0 0;border:1px dashed #d9d9d9;border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;width:32px;height:32px;padding:0;transition:all .3s;display:flex}.add-btn[data-v-4b90c954]:hover{color:#1a1a1a;background:#1a1a1a0a;border-color:#1a1a1a}.add-menu[data-v-4b90c954]{white-space:nowrap;z-index:9999;background:#fff;border-radius:8px;padding:8px 0;position:fixed;transform:translate(-50%);box-shadow:0 6px 16px #00000014,0 3px 6px -4px #0000001f,0 9px 28px 8px #0000000d}@supports (anchor-name:--kmap-anchor) and (position-anchor:--kmap-anchor){.add-menu.use-anchor[data-v-4b90c954]{position-anchor:--indicator-add-btn;left:anchor(center);top:anchor(top);max-width:calc(100vw - 16px);position:fixed;transform:translate(-50%,calc(-100% - 8px))}}.menu-section[data-v-4b90c954]{padding:4px 0}.menu-section[data-v-4b90c954]:not(:last-child){border-bottom:1px solid #f0f0f0}.menu-title[data-v-4b90c954]{color:#999;padding:4px 16px;font-size:12px;font-weight:500}.menu-items[data-v-4b90c954]{flex-direction:column;gap:2px;display:flex}.menu-item[data-v-4b90c954]{text-align:left;color:#333;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;width:100%;padding:8px 16px;font-size:13px;transition:background .2s;display:flex}.menu-item[data-v-4b90c954]:hover:not(.disabled){background:#f5f5f5}.menu-item.disabled[data-v-4b90c954]{color:#999;cursor:not-allowed}.menu-item .param-hint[data-v-4b90c954]{color:#999;font-size:11px}.active-tag[data-v-4b90c954]{color:#1a1a1a;align-items:center;margin-left:auto;display:flex}.fade-enter-active[data-v-4b90c954],.fade-leave-active[data-v-4b90c954]{transition:opacity .2s}.fade-enter-from[data-v-4b90c954],.fade-leave-to[data-v-4b90c954]{opacity:0}.slide-enter-active[data-v-4b90c954],.slide-leave-active[data-v-4b90c954]{transition:all .2s}.slide-enter-from[data-v-4b90c954],.slide-leave-to[data-v-4b90c954]{opacity:0;transform:translate(-50%)translateY(8px)}.chart-wrapper[data-v-289d47a8]{--kmap-height:var(--kmap-chart-height,100%);--kmap-width:var(--kmap-chart-width,100%);width:var(--kmap-width);height:var(--kmap-height);flex-direction:column;justify-content:center;align-items:center;min-height:300px;display:flex}.chart-container[data-v-289d47a8]{scrollbar-width:none;-ms-overflow-style:none;box-sizing:border-box;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;touch-action:none;border:1px solid #e0e0e0;width:95%;height:85%;min-height:255px;position:relative;overflow:auto hidden}.chart-container[data-v-289d47a8]::-webkit-scrollbar{display:none}.chart-container[data-v-289d47a8]:hover{cursor:crosshair}.chart-container.is-resizing-pane[data-v-289d47a8],.chart-container.is-hovering-pane-separator[data-v-289d47a8]{cursor:row-resize}.chart-container.is-hovering-kline[data-v-289d47a8]{cursor:pointer}.chart-container:hover.is-hovering-right-axis[data-v-289d47a8]{cursor:ns-resize}.chart-container.is-dragging[data-v-289d47a8]{cursor:grabbing}.scroll-content[data-v-289d47a8]{height:100%;min-height:inherit;position:relative}.canvas-layer[data-v-289d47a8]{pointer-events:none;position:sticky;top:0;left:0}.tooltip-anchor[data-v-289d47a8]{pointer-events:none;width:1px;height:1px;position:absolute}.tooltip-anchor.kline-tooltip-anchor.use-anchor[data-v-289d47a8]{anchor-name:--kline-tooltip-anchor}.tooltip-anchor.marker-tooltip-anchor.use-anchor[data-v-289d47a8]{anchor-name:--marker-tooltip-anchor}.plot-canvas{display:block;position:absolute;top:0;left:0}.right-axis{display:block;position:absolute}.x-axis-canvas{z-index:10;display:block;position:absolute;bottom:0;left:0}.main,.sub{border-bottom:1px solid #e0e0e0;border-right:1px solid #e0e0e0}.x-axis-canvas{border-right:1px solid #e0e0e0}.right-axis{border-bottom:1px solid #e0e0e0;border-right:1px solid #e0e0e0}
|
|
1
|
+
.kline-tooltip[data-v-d0fe85e6]{z-index:10;color:#000000c7;pointer-events:none;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);background:#ffffffeb;border:1px solid #0000001f;border-radius:8px;min-width:200px;max-width:260px;padding:10px 12px;font-size:12px;line-height:1.4;position:absolute;box-shadow:0 6px 18px #0000001f}.kline-tooltip__title[data-v-d0fe85e6]{justify-content:space-between;gap:10px;margin-bottom:6px;font-weight:600;display:flex}.kline-tooltip__grid[data-v-d0fe85e6]{grid-template-columns:1fr;gap:2px;display:grid}.kline-tooltip__grid .row[data-v-d0fe85e6]{justify-content:space-between;gap:10px;display:flex}.kline-tooltip__grid .row span[data-v-d0fe85e6]:first-child{color:#0000008f}@supports (anchor-name:--kmap-anchor) and (position-anchor:--kmap-anchor){.kline-tooltip.use-anchor[data-v-d0fe85e6]{position-anchor:--kline-tooltip-anchor;left:anchor(left);top:anchor(top);position:absolute}.kline-tooltip.use-anchor.anchor-right-bottom[data-v-d0fe85e6]{transform:translate(14px,14px)}.kline-tooltip.use-anchor.anchor-left-bottom[data-v-d0fe85e6]{transform:translate(calc(-100% - 14px),14px)}}.marker-tooltip[data-v-5574cc25]{z-index:10;color:#000000c7;pointer-events:none;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);background:#ffffffeb;border:1px solid #0000001f;border-radius:8px;min-width:180px;max-width:260px;padding:10px 12px;font-size:12px;line-height:1.4;position:absolute;box-shadow:0 6px 18px #0000001f}.marker-tooltip__title[data-v-5574cc25]{justify-content:space-between;gap:10px;margin-bottom:6px;font-weight:600;display:flex}.marker-tooltip__content[data-v-5574cc25]{grid-template-columns:1fr;gap:2px;display:grid}.marker-tooltip__content .row[data-v-5574cc25]{justify-content:space-between;gap:10px;display:flex}.marker-tooltip__content .row span[data-v-5574cc25]:first-child{color:#0000008f}@supports (anchor-name:--kmap-anchor) and (position-anchor:--kmap-anchor){.marker-tooltip.use-anchor[data-v-5574cc25]{position-anchor:--marker-tooltip-anchor;left:anchor(left);top:anchor(top);position:absolute}.marker-tooltip.use-anchor.anchor-right-bottom[data-v-5574cc25]{transform:translate(12px,12px)}.marker-tooltip.use-anchor.anchor-left-bottom[data-v-5574cc25]{transform:translate(calc(-100% - 12px),12px)}}.params-overlay[data-v-c14eedcc]{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;background:#0000004d;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.indicator-params[data-v-c14eedcc]{background:#fff;border:1px solid #e0e0e0;border-radius:12px;width:90vw;min-width:340px;max-width:420px;overflow:hidden;box-shadow:0 8px 40px #00000026}.params-header[data-v-c14eedcc]{background:#f8f8f8;border-bottom:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:16px 20px;display:flex}.header-left[data-v-c14eedcc]{align-items:baseline;gap:8px;display:flex}.header-right[data-v-c14eedcc]{align-items:center;gap:8px;display:flex}.params-title[data-v-c14eedcc]{color:#1a1a1a;letter-spacing:.2px;font-size:14px;font-weight:600}.params-subtitle[data-v-c14eedcc]{color:#999;font-size:11px}.toggle-desc-btn[data-v-c14eedcc]{cursor:pointer;color:#888;background:#fff;border:1px solid #e0e0e0;border-radius:6px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:all .2s;display:flex}.toggle-desc-btn[data-v-c14eedcc]:hover{color:#555;background:#f0f0f0;border-color:#ccc}.toggle-desc-btn.active[data-v-c14eedcc]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.toggle-desc-btn svg[data-v-c14eedcc]{width:14px;height:14px}.params-close[data-v-c14eedcc]{cursor:pointer;color:#888;background:#fff;border:1px solid #e0e0e0;border-radius:6px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:background .15s,color .15s,border-color .15s;display:flex}.params-close[data-v-c14eedcc]:hover{color:#333;background:#f0f0f0;border-color:#ccc}.params-close svg[data-v-c14eedcc]{width:14px;height:14px}.indicator-description[data-v-c14eedcc]{background:#f0f7ff;border-bottom:1px solid #d6e8f5;padding:12px 20px}.indicator-description p[data-v-c14eedcc]{color:#2c5282;margin:0;font-size:12px;line-height:1.6}.params-body[data-v-c14eedcc]{flex-direction:column;gap:10px;padding:16px 20px;display:flex}.param-item[data-v-c14eedcc]{background:#f8f8f8;border:1px solid #e8e8e8;border-radius:8px;padding:10px 14px;transition:border-color .2s}.param-item[data-v-c14eedcc]:has(.param-input:focus){border-color:#bbb}.param-item.has-desc[data-v-c14eedcc]{padding:10px 14px 8px}.param-header[data-v-c14eedcc]{justify-content:space-between;align-items:center;gap:16px;display:flex}.param-label[data-v-c14eedcc]{flex-direction:column;gap:3px;display:flex}.param-label-text[data-v-c14eedcc]{color:#333;font-size:13px;font-weight:500}.param-range[data-v-c14eedcc]{color:#999;font-size:11px}.param-description[data-v-c14eedcc]{color:#666;border-top:1px dashed #e0e0e0;margin-top:8px;padding-top:8px;font-size:11px;line-height:1.5}.input-wrapper[data-v-c14eedcc]{background:#fff;border:1px solid #d0d0d0;border-radius:7px;align-items:stretch;height:32px;transition:border-color .2s;display:flex;overflow:hidden}.input-wrapper[data-v-c14eedcc]:focus-within{border-color:#999}.stepper-btn[data-v-c14eedcc]{cursor:pointer;color:#666;background:#f0f0f0;border:none;flex-shrink:0;justify-content:center;align-items:center;width:28px;font-size:15px;font-weight:400;line-height:1;transition:background .15s,color .15s;display:flex}.stepper-btn[data-v-c14eedcc]:hover:not(:disabled){color:#333;background:#e0e0e0}.stepper-btn[data-v-c14eedcc]:disabled{color:#ccc;cursor:not-allowed}.param-input[data-v-c14eedcc]{text-align:center;color:#1a1a1a;appearance:textfield;background:0 0;border:none;border-left:1px solid #e8e8e8;border-right:1px solid #e8e8e8;width:60px;font-size:13px;font-weight:600}.param-input[data-v-c14eedcc]::-webkit-inner-spin-button{-webkit-appearance:none}.param-input[data-v-c14eedcc]::-webkit-outer-spin-button{-webkit-appearance:none}.param-input[data-v-c14eedcc]:focus{outline:none}.params-footer[data-v-c14eedcc]{background:#f8f8f8;border-top:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:12px 20px;display:flex}.footer-right[data-v-c14eedcc]{gap:8px;display:flex}.params-btn[data-v-c14eedcc]{cursor:pointer;border:1px solid #0000;border-radius:7px;align-items:center;gap:5px;padding:6px 14px;font-size:13px;font-weight:500;line-height:1.4;transition:all .15s;display:flex}.params-btn svg[data-v-c14eedcc]{flex-shrink:0;width:12px;height:12px}.params-btn.reset[data-v-c14eedcc]{color:#666;background:0 0;border-color:#d0d0d0}.params-btn.reset[data-v-c14eedcc]:hover{color:#e74c3c;background:#e74c3c14;border-color:#c0392b}.params-btn.cancel[data-v-c14eedcc]{color:#666;background:0 0;border-color:#d0d0d0}.params-btn.cancel[data-v-c14eedcc]:hover{color:#333;background:#f0f0f0;border-color:#bbb}.params-btn.confirm[data-v-c14eedcc]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.params-btn.confirm[data-v-c14eedcc]:hover{background:#333;border-color:#333;transform:translateY(-1px);box-shadow:0 2px 10px #00000026}.params-btn.confirm[data-v-c14eedcc]:active{box-shadow:none;transform:translateY(0)}.overlay-enter-active[data-v-c14eedcc],.overlay-leave-active[data-v-c14eedcc]{transition:opacity .2s}.overlay-enter-from[data-v-c14eedcc],.overlay-leave-to[data-v-c14eedcc]{opacity:0}.modal-enter-active[data-v-c14eedcc]{transition:all .22s cubic-bezier(.34,1.56,.64,1)}.modal-leave-active[data-v-c14eedcc]{transition:all .16s ease-in}.modal-enter-from[data-v-c14eedcc]{opacity:0;transform:scale(.88)translateY(-16px)}.modal-leave-to[data-v-c14eedcc]{opacity:0;transform:scale(.94)translateY(8px)}.slide-enter-active[data-v-c14eedcc],.slide-leave-active[data-v-c14eedcc]{transition:all .2s;overflow:hidden}.slide-enter-from[data-v-c14eedcc],.slide-leave-to[data-v-c14eedcc]{opacity:0;max-height:0;margin-top:0;padding-top:0;padding-bottom:0}.indicator-selector[data-v-4b90c954]{width:80%;margin:20px;position:relative}.indicator-scroll-container[data-v-4b90c954]{scrollbar-width:none;-webkit-overflow-scrolling:touch;text-align:center;width:100%;overflow:auto hidden}.indicator-scroll-container[data-v-4b90c954]::-webkit-scrollbar{display:none}.indicator-list[data-v-4b90c954]{gap:8px;margin:0 auto;padding:2px;display:inline-flex}.indicator-divider[data-v-4b90c954]{background:#d9d9d9;align-self:center;width:1px;height:20px}.indicator-item[data-v-4b90c954]{align-items:center;gap:4px;display:flex}.indicator-item.draggable[data-v-4b90c954],.indicator-item.draggable .indicator-btn[data-v-4b90c954],.indicator-item.draggable[data-v-4b90c954]:hover,.indicator-item.draggable:hover .indicator-btn[data-v-4b90c954]{cursor:move}.indicator-item.is-dragging[data-v-4b90c954]{opacity:.6}.indicator-item.drag-over .indicator-btn[data-v-4b90c954]{border-color:#1a1a1a;box-shadow:0 0 0 2px #1a1a1a1f}.indicator-btn-wrapper[data-v-4b90c954]{position:relative}.indicator-btn[data-v-4b90c954]{color:#666;cursor:pointer;white-space:nowrap;background:#fff;border:1px solid #e0e0e0;border-radius:16px;flex-shrink:0;justify-content:center;align-items:center;gap:4px;padding:6px 16px;font-size:13px;font-weight:500;transition:all .3s;display:flex;position:relative;overflow:hidden}.indicator-btn[data-v-4b90c954]:hover:not(.hovering){color:#333;background:#f8f8f8;border-color:#ccc}.indicator-btn.active[data-v-4b90c954]{color:#1a1a1a;background:#f8f8f8;border-color:#1a1a1a}.indicator-btn.active[data-v-4b90c954]:hover:not(.hovering){background:#f0f0f0;border-color:#333}.btn-content[data-v-4b90c954]{z-index:1;position:relative}.param-hint[data-v-4b90c954]{opacity:.85;font-size:11px}.hover-overlay[data-v-4b90c954]{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:2;background:#ffffffd9;border-radius:16px;justify-content:center;align-items:center;gap:4px;display:flex;position:absolute;inset:0}.action-btn[data-v-4b90c954]{color:#666;cursor:pointer;background:0 0;border:none;border-radius:50%;justify-content:center;align-items:center;width:24px;height:24px;padding:0;transition:all .2s;display:flex}.action-btn[data-v-4b90c954]:hover{color:#333;background:#0000000f}.settings-btn[data-v-4b90c954]:hover{color:#1a1a1a}.remove-btn[data-v-4b90c954]:hover{color:#ff4d4f}.divider[data-v-4b90c954]{background:#e0e0e0;width:1px;height:14px}.add-btn[data-v-4b90c954]{anchor-name:--indicator-add-btn;color:#999;cursor:pointer;background:0 0;border:1px dashed #d9d9d9;border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;width:32px;height:32px;padding:0;transition:all .3s;display:flex}.add-btn[data-v-4b90c954]:hover{color:#1a1a1a;background:#1a1a1a0a;border-color:#1a1a1a}.add-menu[data-v-4b90c954]{white-space:nowrap;z-index:9999;background:#fff;border-radius:8px;padding:8px 0;position:fixed;transform:translate(-50%);box-shadow:0 6px 16px #00000014,0 3px 6px -4px #0000001f,0 9px 28px 8px #0000000d}@supports (anchor-name:--kmap-anchor) and (position-anchor:--kmap-anchor){.add-menu.use-anchor[data-v-4b90c954]{position-anchor:--indicator-add-btn;left:anchor(center);top:anchor(top);max-width:calc(100vw - 16px);position:fixed;transform:translate(-50%,calc(-100% - 8px))}}.menu-section[data-v-4b90c954]{padding:4px 0}.menu-section[data-v-4b90c954]:not(:last-child){border-bottom:1px solid #f0f0f0}.menu-title[data-v-4b90c954]{color:#999;padding:4px 16px;font-size:12px;font-weight:500}.menu-items[data-v-4b90c954]{flex-direction:column;gap:2px;display:flex}.menu-item[data-v-4b90c954]{text-align:left;color:#333;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;width:100%;padding:8px 16px;font-size:13px;transition:background .2s;display:flex}.menu-item[data-v-4b90c954]:hover:not(.disabled){background:#f5f5f5}.menu-item.disabled[data-v-4b90c954]{color:#999;cursor:not-allowed}.menu-item .param-hint[data-v-4b90c954]{color:#999;font-size:11px}.active-tag[data-v-4b90c954]{color:#1a1a1a;align-items:center;margin-left:auto;display:flex}.fade-enter-active[data-v-4b90c954],.fade-leave-active[data-v-4b90c954]{transition:opacity .2s}.fade-enter-from[data-v-4b90c954],.fade-leave-to[data-v-4b90c954]{opacity:0}.slide-enter-active[data-v-4b90c954],.slide-leave-active[data-v-4b90c954]{transition:all .2s}.slide-enter-from[data-v-4b90c954],.slide-leave-to[data-v-4b90c954]{opacity:0;transform:translate(-50%)translateY(8px)}.left-toolbar[data-v-39e1168e]{box-sizing:border-box;-webkit-user-select:none;user-select:none;background:#fafbfc;border:1px solid #e5e7eb;border-radius:6px;flex-direction:column;flex:0 0 40px;align-items:center;gap:6px;padding:8px 5px;display:flex;box-shadow:0 1px 3px #0000000f}.left-toolbar__group[data-v-39e1168e]{flex-direction:column;gap:4px;display:flex}.left-toolbar__divider[data-v-39e1168e]{background:#e5e7eb;width:18px;height:1px}.left-toolbar__button[data-v-39e1168e]{color:#6b7280;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:4px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:border-color .15s,background .15s,color .15s;display:inline-flex;position:relative}.left-toolbar__button[data-v-39e1168e]:hover{color:#374151;background:#f3f4f6;border-color:#d1d5db}.left-toolbar__button.active[data-v-39e1168e]{color:#1f2937;background:#e5e7eb;border-color:#9ca3af}.left-toolbar__button[data-v-39e1168e]:focus-visible{border-color:#6b7280;outline:none}.tool-icon[data-v-39e1168e]{width:16px;height:16px}.corner-indicator[data-v-39e1168e]{cursor:pointer;width:8px;height:8px;position:absolute;bottom:0;right:0;overflow:hidden}.corner-indicator[data-v-39e1168e]:after{content:"";opacity:.45;border-bottom:5px solid;border-left:5px solid #0000;width:0;height:0;transition:opacity .15s;position:absolute;bottom:0;right:0}.left-toolbar__button:hover .corner-indicator[data-v-39e1168e]:after,.left-toolbar__button.active .corner-indicator[data-v-39e1168e]:after{opacity:.7}.corner-indicator.open[data-v-39e1168e]:after{opacity:.8}.tool-dropdown[data-v-39e1168e]{-webkit-backdrop-filter:blur(8px);box-sizing:border-box;z-index:100;background:#fafbfcd1;border:1px solid #e5e7eb;border-radius:6px;flex-direction:row;align-items:center;gap:4px;height:40px;padding:0 5px;display:flex;position:absolute;top:50%;left:calc(100% + 13px);transform:translateY(-50%);box-shadow:0 1px 3px #0000000f}.tool-item[data-v-39e1168e]{position:relative}.dropdown-enter-active[data-v-39e1168e],.dropdown-leave-active[data-v-39e1168e]{transition:opacity .15s,transform .15s}.dropdown-enter-from[data-v-39e1168e],.dropdown-leave-to[data-v-39e1168e]{opacity:0;transform:translateY(-50%)translate(-6px)}@media (width<=768px),(height<=640px){.left-toolbar[data-v-39e1168e]{border-radius:5px;flex-basis:36px;gap:5px;padding:6px 4px}.left-toolbar__group[data-v-39e1168e]{gap:3px}.left-toolbar__button[data-v-39e1168e]{border-radius:3px;width:26px;height:26px}.left-toolbar__divider[data-v-39e1168e]{width:16px}.corner-indicator[data-v-39e1168e]{width:7px;height:7px}.corner-indicator[data-v-39e1168e]:after{border-bottom-width:4px;border-left-width:4px}.tool-dropdown[data-v-39e1168e]{height:36px}}.chart-wrapper[data-v-a3b8c041]{--kmap-height:var(--kmap-chart-height,100%);--kmap-width:var(--kmap-chart-width,100%);width:var(--kmap-width);height:var(--kmap-height);flex-direction:column;justify-content:center;align-items:center;min-height:300px;display:flex}.chart-stage[data-v-a3b8c041]{align-items:stretch;gap:8px;width:95%;height:85%;min-height:255px;display:flex}.chart-container[data-v-a3b8c041]{height:100%;min-height:inherit;scrollbar-width:none;-ms-overflow-style:none;box-sizing:border-box;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;touch-action:none;background:#fff;border:1px solid #e5e7eb;border-radius:6px;flex:auto;position:relative;overflow:auto hidden}.chart-container[data-v-a3b8c041]::-webkit-scrollbar{display:none}.chart-container[data-v-a3b8c041]:hover{cursor:crosshair}.chart-container.is-resizing-pane[data-v-a3b8c041],.chart-container.is-hovering-pane-separator[data-v-a3b8c041]{cursor:row-resize}.chart-container.is-hovering-kline[data-v-a3b8c041]{cursor:pointer}.chart-container:hover.is-hovering-right-axis[data-v-a3b8c041]{cursor:ns-resize}.chart-container.is-dragging[data-v-a3b8c041]{cursor:grabbing}.scroll-content[data-v-a3b8c041]{height:100%;min-height:inherit;position:relative}.canvas-layer[data-v-a3b8c041]{pointer-events:none;position:sticky;top:0;left:0}.tooltip-anchor[data-v-a3b8c041]{pointer-events:none;width:1px;height:1px;position:absolute}.tooltip-anchor.kline-tooltip-anchor.use-anchor[data-v-a3b8c041]{anchor-name:--kline-tooltip-anchor}.tooltip-anchor.marker-tooltip-anchor.use-anchor[data-v-a3b8c041]{anchor-name:--marker-tooltip-anchor}@media (width<=768px),(height<=640px){.chart-stage[data-v-a3b8c041]{gap:6px}}.plot-canvas{display:block;position:absolute;top:0;left:0}.right-axis{display:block;position:absolute}.x-axis-canvas{z-index:10;display:block;position:absolute;bottom:0;left:0}.main,.sub{border-bottom:1px solid #e0e0e0;border-right:1px solid #e0e0e0}.x-axis-canvas{border-right:1px solid #e0e0e0}.right-axis{border-bottom:1px solid #e0e0e0;border-right:1px solid #e0e0e0}
|
|
2
2
|
/*$vite$:1*/
|
package/dist/src/App.vue.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
declare const _default: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {
|
|
1
|
+
declare const _default: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {
|
|
2
|
+
embedContainerRef: HTMLDivElement;
|
|
3
|
+
}, HTMLDivElement>;
|
|
2
4
|
export default _default;
|
|
@@ -8,9 +8,10 @@ declare class DataSourceFactory {
|
|
|
8
8
|
static create(type: DataSourceType): IKLineDataSource;
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
|
-
* 获取 K
|
|
11
|
+
* 获取 K 线数据(统一入口,带缓存)
|
|
12
12
|
* @param type 数据源类型
|
|
13
13
|
* @param config 统一配置
|
|
14
|
+
* @param useCache 是否使用缓存,默认 true
|
|
14
15
|
* @returns Promise<KLineData[]>
|
|
15
16
|
*
|
|
16
17
|
* 使用示例:
|
|
@@ -26,8 +27,11 @@ declare class DataSourceFactory {
|
|
|
26
27
|
*
|
|
27
28
|
* // 切换东财只需改第一个参数
|
|
28
29
|
* const data = await fetchKLineData('dongcai', { ... })
|
|
30
|
+
*
|
|
31
|
+
* // 跳过缓存强制刷新
|
|
32
|
+
* const data = await fetchKLineData('baostock', config, false)
|
|
29
33
|
* ```
|
|
30
34
|
*/
|
|
31
|
-
export declare function fetchKLineData(type: DataSourceType, config: KLineDataSourceConfig): Promise<KLineData[]>;
|
|
35
|
+
export declare function fetchKLineData(type: DataSourceType, config: KLineDataSourceConfig, useCache?: boolean): Promise<KLineData[]>;
|
|
32
36
|
export { DataSourceFactory };
|
|
33
37
|
export type { KLineDataSourceConfig, DataSourceType, IKLineDataSource };
|
|
@@ -16,6 +16,8 @@ type __VLS_Props = {
|
|
|
16
16
|
zoomLevels?: number;
|
|
17
17
|
/** 初始缩放级别(1 ~ zoomLevels,默认居中) */
|
|
18
18
|
initialZoomLevel?: number;
|
|
19
|
+
/** 是否全屏 */
|
|
20
|
+
isFullscreen?: boolean;
|
|
19
21
|
};
|
|
20
22
|
declare function scheduleRender(): void;
|
|
21
23
|
declare function addSubPane(indicatorId?: SubIndicatorType, params?: Record<string, number>): boolean;
|
|
@@ -30,15 +32,17 @@ declare const _default: import('vue').DefineComponent<__VLS_Props, {
|
|
|
30
32
|
removeSubPane: typeof removeSubPane;
|
|
31
33
|
switchSubIndicator: typeof switchSubIndicator;
|
|
32
34
|
clearAllSubPanes: typeof clearAllSubPanes;
|
|
33
|
-
plugin: import('
|
|
35
|
+
plugin: import('../plugin').PluginHostImpl | undefined;
|
|
34
36
|
zoomToLevel: (level: number, anchorX?: number) => void | undefined;
|
|
35
37
|
zoomIn: (anchorX?: number) => void | undefined;
|
|
36
38
|
zoomOut: (anchorX?: number) => void | undefined;
|
|
37
39
|
getZoomLevel: () => number;
|
|
38
40
|
getZoomLevelCount: () => number;
|
|
39
41
|
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
42
|
+
toggleFullscreen: () => any;
|
|
40
43
|
zoomLevelChange: (level: number, kWidth: number) => any;
|
|
41
44
|
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
45
|
+
onToggleFullscreen?: (() => any) | undefined;
|
|
42
46
|
onZoomLevelChange?: ((level: number, kWidth: number) => any) | undefined;
|
|
43
47
|
}>, {
|
|
44
48
|
yPaddingPx: number;
|
|
@@ -49,6 +53,7 @@ declare const _default: import('vue').DefineComponent<__VLS_Props, {
|
|
|
49
53
|
priceLabelWidth: number;
|
|
50
54
|
zoomLevels: number;
|
|
51
55
|
initialZoomLevel: number;
|
|
56
|
+
isFullscreen: boolean;
|
|
52
57
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
|
|
53
58
|
containerRef: HTMLDivElement;
|
|
54
59
|
canvasLayerRef: HTMLDivElement;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface ToolDef {
|
|
2
|
+
id: string;
|
|
3
|
+
title: string;
|
|
4
|
+
icon: unknown;
|
|
5
|
+
children?: ToolDef[];
|
|
6
|
+
}
|
|
7
|
+
type __VLS_Props = {
|
|
8
|
+
isFullscreen?: boolean;
|
|
9
|
+
};
|
|
10
|
+
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
11
|
+
selectTool: (toolId: string) => any;
|
|
12
|
+
toggleFullscreen: () => any;
|
|
13
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
14
|
+
onSelectTool?: ((toolId: string) => any) | undefined;
|
|
15
|
+
onToggleFullscreen?: (() => any) | undefined;
|
|
16
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLElement>;
|
|
17
|
+
export default _default;
|
package/dist/src/core/chart.d.ts
CHANGED
|
@@ -87,6 +87,7 @@ export declare class Chart {
|
|
|
87
87
|
private viewport;
|
|
88
88
|
private paneRenderers;
|
|
89
89
|
private markerManager;
|
|
90
|
+
private drawingStore;
|
|
90
91
|
readonly interaction: InteractionController;
|
|
91
92
|
/** 插件宿主 */
|
|
92
93
|
private pluginHost;
|
|
@@ -224,6 +225,8 @@ export declare class Chart {
|
|
|
224
225
|
upsertPane(def: PaneSpec): void;
|
|
225
226
|
removePaneDefinition(paneId: string): void;
|
|
226
227
|
bindIndicatorToPane(paneId: string, indicatorId: SubIndicatorType, params?: Record<string, number>): void;
|
|
228
|
+
/** 更新绘图对象 */
|
|
229
|
+
setDrawings(drawings: import('../plugin').DrawingObject[]): void;
|
|
227
230
|
/** 获取当前 pane 布局快照(含 ratio) */
|
|
228
231
|
getPaneLayoutSpecs(): PaneSpec[];
|
|
229
232
|
private emitPaneLayoutChange;
|
|
@@ -287,6 +290,8 @@ export declare class Chart {
|
|
|
287
290
|
updateData(data: KLineData[]): void;
|
|
288
291
|
/** 获取当前数据源(供 renderers 和 interaction 使用) */
|
|
289
292
|
getData(): KLineData[];
|
|
293
|
+
/** 根据视口内 X 坐标反查数据索引(用于绘图落点) */
|
|
294
|
+
getDataIndexAtX(mouseX: number): number | null;
|
|
290
295
|
/** 获取内容总宽度(用于外部 scroll-content 撑开 scrollWidth) */
|
|
291
296
|
getContentWidth(): number;
|
|
292
297
|
/** 容器尺寸变化时调用 */
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { DrawingObject, DrawingKind, DrawingDefinition, DrawingComputeContext, DrawingGeometry, DrawingStyle, PointPrimitive, LinePrimitive, AreaPrimitive, TextPrimitive } from '../../plugin';
|
|
2
|
+
export type { DrawingObject, DrawingKind, DrawingDefinition, DrawingComputeContext, DrawingGeometry, DrawingStyle, PointPrimitive, LinePrimitive, AreaPrimitive, TextPrimitive, };
|
|
3
|
+
export declare class DrawingStore {
|
|
4
|
+
private drawings;
|
|
5
|
+
getAll(): DrawingObject[];
|
|
6
|
+
getVisibleByPane(paneId: string): DrawingObject[];
|
|
7
|
+
setAll(drawings: DrawingObject[]): void;
|
|
8
|
+
upsert(drawing: DrawingObject): void;
|
|
9
|
+
remove(id: string): void;
|
|
10
|
+
clear(): void;
|
|
11
|
+
}
|
|
12
|
+
export declare class DrawingDefinitionRegistry {
|
|
13
|
+
private definitions;
|
|
14
|
+
register<TParams = Record<string, unknown>>(definition: DrawingDefinition<TParams>): void;
|
|
15
|
+
get(kind: DrawingKind): DrawingDefinition | undefined;
|
|
16
|
+
compute(drawing: DrawingObject, context: DrawingComputeContext): DrawingGeometry | null;
|
|
17
|
+
}
|
|
18
|
+
export type PrimitiveRendererSet = {
|
|
19
|
+
point: (ctx: CanvasRenderingContext2D, primitive: PointPrimitive, dpr: number) => void;
|
|
20
|
+
line: (ctx: CanvasRenderingContext2D, primitive: LinePrimitive, viewportClip: {
|
|
21
|
+
left: number;
|
|
22
|
+
top: number;
|
|
23
|
+
right: number;
|
|
24
|
+
bottom: number;
|
|
25
|
+
}, dpr: number) => void;
|
|
26
|
+
area: (ctx: CanvasRenderingContext2D, primitive: AreaPrimitive, dpr: number) => void;
|
|
27
|
+
text: (ctx: CanvasRenderingContext2D, primitive: TextPrimitive, dpr: number) => void;
|
|
28
|
+
};
|
|
29
|
+
export declare function createDefaultPrimitiveRendererSet(): PrimitiveRendererSet;
|
|
30
|
+
export declare function createTwoPointLineDefinition(kind: DrawingKind, extend: LinePrimitive['extend']): DrawingDefinition;
|
|
31
|
+
export declare function createSingleAnchorLineDefinition(kind: DrawingKind): DrawingDefinition;
|
|
32
|
+
export declare function createInfoLineDefinition(): DrawingDefinition;
|
|
33
|
+
export declare function createParallelChannelDefinition(): DrawingDefinition;
|
|
34
|
+
export declare function createRegressionChannelDefinition(): DrawingDefinition;
|
|
35
|
+
export declare function registerDefaultDrawingDefinitions(registry: DrawingDefinitionRegistry): void;
|
|
36
|
+
export { DrawingInteractionController } from './interaction';
|
|
37
|
+
export type { DrawingToolId, DrawingAnchorInput, DrawingInteractionCallbacks } from './interaction';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { DrawingObject } from '../../plugin';
|
|
2
|
+
import { Chart } from '../chart';
|
|
3
|
+
export type DrawingToolId = 'cursor' | 'trend-line' | 'ray' | 'h-line' | 'h-ray' | 'v-line' | 'crosshair-line' | 'info-line' | 'text' | 'measure';
|
|
4
|
+
export interface DrawingAnchorInput {
|
|
5
|
+
time: number;
|
|
6
|
+
price: number;
|
|
7
|
+
}
|
|
8
|
+
export interface DrawingInteractionCallbacks {
|
|
9
|
+
onDrawingCreated?: (drawing: DrawingObject) => void;
|
|
10
|
+
onToolChange?: (toolId: DrawingToolId) => void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 绘图交互控制器
|
|
14
|
+
* 封装绘图工具的交互逻辑,与 Vue 组件解耦
|
|
15
|
+
*/
|
|
16
|
+
export declare class DrawingInteractionController {
|
|
17
|
+
private chart;
|
|
18
|
+
private activeTool;
|
|
19
|
+
private pendingAnchor;
|
|
20
|
+
private drawings;
|
|
21
|
+
private callbacks;
|
|
22
|
+
private static readonly SINGLE_ANCHOR_TOOLS;
|
|
23
|
+
private static readonly DOUBLE_ANCHOR_TOOLS;
|
|
24
|
+
constructor(chart: Chart);
|
|
25
|
+
setCallbacks(callbacks: DrawingInteractionCallbacks): void;
|
|
26
|
+
getActiveTool(): DrawingToolId;
|
|
27
|
+
setTool(toolId: DrawingToolId): void;
|
|
28
|
+
getDrawings(): DrawingObject[];
|
|
29
|
+
setDrawings(drawings: DrawingObject[]): void;
|
|
30
|
+
clear(): void;
|
|
31
|
+
/**
|
|
32
|
+
* 处理指针按下事件
|
|
33
|
+
* @returns 是否处理了事件(阻止冒泡)
|
|
34
|
+
*/
|
|
35
|
+
onPointerDown(e: PointerEvent, container: HTMLElement): boolean;
|
|
36
|
+
private resolveAnchorFromPointer;
|
|
37
|
+
private createSingleAnchorDrawing;
|
|
38
|
+
private createDoubleAnchorDrawing;
|
|
39
|
+
private getDrawingKind;
|
|
40
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { RendererPlugin } from '../../plugin';
|
|
2
|
+
import { DrawingStore, DrawingDefinitionRegistry, PrimitiveRendererSet } from './index';
|
|
3
|
+
export declare function createDrawingRendererPlugin(options: {
|
|
4
|
+
store: DrawingStore;
|
|
5
|
+
paneId?: string;
|
|
6
|
+
definitions?: DrawingDefinitionRegistry;
|
|
7
|
+
renderers?: PrimitiveRendererSet;
|
|
8
|
+
}): RendererPlugin;
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* 插件系统核心类型定义
|
|
3
|
-
*/
|
|
1
|
+
import { KLineData } from '../types/price';
|
|
4
2
|
/** 插件生命周期状态 */
|
|
5
3
|
export declare enum PluginState {
|
|
6
4
|
Registered = "registered",
|
|
@@ -171,6 +169,107 @@ export interface RenderContext {
|
|
|
171
169
|
zoomLevel?: number;
|
|
172
170
|
/** 总缩放级别数 */
|
|
173
171
|
zoomLevelCount?: number;
|
|
172
|
+
viewport?: {
|
|
173
|
+
scrollLeft: number;
|
|
174
|
+
plotWidth: number;
|
|
175
|
+
plotHeight: number;
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
export type DrawingAnchor = {
|
|
179
|
+
id: string;
|
|
180
|
+
time: number | string;
|
|
181
|
+
price: number;
|
|
182
|
+
};
|
|
183
|
+
export type DrawingKind = 'trend-line' | 'ray' | 'extended-line' | 'horizontal-line' | 'horizontal-ray' | 'vertical-line' | 'cross-line' | 'info-line' | 'parallel-channel' | 'regression-channel';
|
|
184
|
+
export type DrawingStyle = {
|
|
185
|
+
stroke?: string;
|
|
186
|
+
strokeWidth?: number;
|
|
187
|
+
strokeStyle?: 'solid' | 'dashed' | 'dotted';
|
|
188
|
+
fill?: string;
|
|
189
|
+
fillOpacity?: number;
|
|
190
|
+
pointRadius?: number;
|
|
191
|
+
textColor?: string;
|
|
192
|
+
fontSize?: number;
|
|
193
|
+
};
|
|
194
|
+
export type DrawingObject<TParams = Record<string, unknown>> = {
|
|
195
|
+
id: string;
|
|
196
|
+
kind: DrawingKind;
|
|
197
|
+
paneId: string;
|
|
198
|
+
visible: boolean;
|
|
199
|
+
locked?: boolean;
|
|
200
|
+
zIndex?: number;
|
|
201
|
+
anchors: DrawingAnchor[];
|
|
202
|
+
params: TParams;
|
|
203
|
+
style: DrawingStyle;
|
|
204
|
+
};
|
|
205
|
+
export type ScreenPoint = {
|
|
206
|
+
x: number;
|
|
207
|
+
y: number;
|
|
208
|
+
};
|
|
209
|
+
export type PointPrimitive = {
|
|
210
|
+
kind: 'point';
|
|
211
|
+
point: ScreenPoint;
|
|
212
|
+
role?: 'anchor' | 'handle' | 'marker' | 'center';
|
|
213
|
+
style?: DrawingStyle;
|
|
214
|
+
};
|
|
215
|
+
export type LinePrimitive = {
|
|
216
|
+
kind: 'line';
|
|
217
|
+
a: ScreenPoint;
|
|
218
|
+
b: ScreenPoint;
|
|
219
|
+
extend?: 'none' | 'left' | 'right' | 'both';
|
|
220
|
+
showEndpoints?: boolean;
|
|
221
|
+
style?: DrawingStyle;
|
|
222
|
+
};
|
|
223
|
+
export type AreaPrimitive = {
|
|
224
|
+
kind: 'area';
|
|
225
|
+
points: ScreenPoint[];
|
|
226
|
+
closed: boolean;
|
|
227
|
+
style?: DrawingStyle;
|
|
228
|
+
};
|
|
229
|
+
export type TextPrimitive = {
|
|
230
|
+
kind: 'text';
|
|
231
|
+
point: ScreenPoint;
|
|
232
|
+
text: string;
|
|
233
|
+
align?: 'left' | 'center' | 'right';
|
|
234
|
+
baseline?: 'top' | 'middle' | 'bottom';
|
|
235
|
+
style?: DrawingStyle;
|
|
236
|
+
};
|
|
237
|
+
export type DrawingPrimitive = PointPrimitive | LinePrimitive | AreaPrimitive | TextPrimitive;
|
|
238
|
+
export type DrawingGeometry = {
|
|
239
|
+
primitives: DrawingPrimitive[];
|
|
240
|
+
bounds?: {
|
|
241
|
+
left: number;
|
|
242
|
+
top: number;
|
|
243
|
+
right: number;
|
|
244
|
+
bottom: number;
|
|
245
|
+
};
|
|
246
|
+
meta?: Record<string, unknown>;
|
|
247
|
+
};
|
|
248
|
+
export type DrawingComputeContext = {
|
|
249
|
+
pane: PaneInfo;
|
|
250
|
+
visibleData: KLineData[];
|
|
251
|
+
seriesData: KLineData[];
|
|
252
|
+
range: {
|
|
253
|
+
start: number;
|
|
254
|
+
end: number;
|
|
255
|
+
};
|
|
256
|
+
kLinePositions: number[];
|
|
257
|
+
kWidth: number;
|
|
258
|
+
kGap: number;
|
|
259
|
+
dpr: number;
|
|
260
|
+
paneWidth: number;
|
|
261
|
+
viewport: {
|
|
262
|
+
scrollLeft: number;
|
|
263
|
+
plotWidth: number;
|
|
264
|
+
plotHeight: number;
|
|
265
|
+
};
|
|
266
|
+
toScreen(anchor: DrawingAnchor): ScreenPoint;
|
|
267
|
+
};
|
|
268
|
+
export interface DrawingDefinition<TParams = Record<string, unknown>> {
|
|
269
|
+
kind: DrawingKind;
|
|
270
|
+
minAnchors: number;
|
|
271
|
+
maxAnchors: number;
|
|
272
|
+
compute(drawing: DrawingObject<TParams>, context: DrawingComputeContext): DrawingGeometry;
|
|
174
273
|
}
|
|
175
274
|
/** 全局 Pane ID(渲染到所有 pane) */
|
|
176
275
|
export declare const GLOBAL_PANE_ID: unique symbol;
|
|
@@ -185,13 +284,12 @@ export declare const RENDERER_PRIORITY: {
|
|
|
185
284
|
* 所有指标渲染器必须使用此优先级或 ≤30 的值
|
|
186
285
|
*/
|
|
187
286
|
readonly INDICATOR: 30;
|
|
287
|
+
readonly MAIN: 50;
|
|
188
288
|
/**
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
* 确保每次绘制时指标更新先于刻度。
|
|
289
|
+
* 指标刻度渲染器(依赖于前方指标写入的共享状态)
|
|
290
|
+
* 必须晚于 INDICATOR 和 MAIN,确保每次绘制时先更新指标状态再绘制刻度。
|
|
192
291
|
*/
|
|
193
|
-
readonly INDICATOR_SCALE:
|
|
194
|
-
readonly MAIN: 50;
|
|
292
|
+
readonly INDICATOR_SCALE: 55;
|
|
195
293
|
readonly OVERLAY: 80;
|
|
196
294
|
readonly FOREGROUND: 100;
|
|
197
295
|
readonly SYSTEM_BORDER: 120;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@363045841yyt/klinechart",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0-alpha.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": "^20.19.0 || >=22.12.0"
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"axios": "^1.16.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
+
"@iconify-json/tabler": "^1.2.34",
|
|
44
45
|
"@tsconfig/node24": "^24.0.4",
|
|
45
46
|
"@types/jsdom": "^28.0.1",
|
|
46
47
|
"@types/node": "^25.6.0",
|
|
@@ -53,6 +54,8 @@
|
|
|
53
54
|
"prettier": "3.8.3",
|
|
54
55
|
"typedoc": "^0.28.19",
|
|
55
56
|
"typescript": "~6.0.3",
|
|
57
|
+
"unplugin-icons": "^23.0.1",
|
|
58
|
+
"unplugin-vue-components": "^32.0.0",
|
|
56
59
|
"vite": "^8.0.10",
|
|
57
60
|
"vite-plugin-dts": "^4.5.4",
|
|
58
61
|
"vite-plugin-vue-devtools": "^8.1.1",
|