@363045841yyt/klinechart 0.4.5 → 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 +11 -5
- package/dist/index.cjs +5 -5
- package/dist/index.js +3017 -1707
- 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 -5
- package/dist/src/components/LeftToolbar.vue.d.ts +17 -0
- package/dist/src/core/chart.d.ts +21 -22
- package/dist/src/core/controller/interaction.d.ts +29 -3
- 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/core/renderers/Indicator/scale/indicator_scale.d.ts +3 -0
- package/dist/src/core/renderers/Indicator/scale/volume_scale.d.ts +14 -0
- package/dist/src/core/renderers/subVolume.d.ts +6 -2
- package/dist/src/core/theme/colors.d.ts +12 -1
- package/dist/src/plugin/types.d.ts +106 -8
- package/dist/src/utils/kLineDraw/axis.d.ts +2 -0
- 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-0ddb3f15]{width:80%;margin:20px;position:relative}.indicator-scroll-container[data-v-0ddb3f15]{scrollbar-width:none;-webkit-overflow-scrolling:touch;text-align:center;width:100%;overflow:auto hidden}.indicator-scroll-container[data-v-0ddb3f15]::-webkit-scrollbar{display:none}.indicator-list[data-v-0ddb3f15]{gap:8px;margin:0 auto;padding:2px;display:inline-flex}.indicator-divider[data-v-0ddb3f15]{background:#d9d9d9;align-self:center;width:1px;height:20px}.indicator-item[data-v-0ddb3f15]{align-items:center;gap:4px;display:flex}.indicator-item.draggable[data-v-0ddb3f15],.indicator-item.draggable .indicator-btn[data-v-0ddb3f15],.indicator-item.draggable[data-v-0ddb3f15]:hover,.indicator-item.draggable:hover .indicator-btn[data-v-0ddb3f15]{cursor:move}.indicator-item.is-dragging[data-v-0ddb3f15]{opacity:.6}.indicator-item.drag-over .indicator-btn[data-v-0ddb3f15]{border-color:#1a1a1a;box-shadow:0 0 0 2px #1a1a1a1f}.indicator-btn-wrapper[data-v-0ddb3f15]{position:relative}.indicator-btn[data-v-0ddb3f15]{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-0ddb3f15]:hover:not(.hovering){color:#333;background:#f8f8f8;border-color:#ccc}.indicator-btn.active[data-v-0ddb3f15]{color:#1a1a1a;background:#f8f8f8;border-color:#1a1a1a}.indicator-btn.active[data-v-0ddb3f15]:hover:not(.hovering){background:#f0f0f0;border-color:#333}.btn-content[data-v-0ddb3f15]{z-index:1;position:relative}.param-hint[data-v-0ddb3f15]{opacity:.85;font-size:11px}.hover-overlay[data-v-0ddb3f15]{-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-0ddb3f15]{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-0ddb3f15]:hover{color:#333;background:#0000000f}.settings-btn[data-v-0ddb3f15]:hover{color:#1a1a1a}.remove-btn[data-v-0ddb3f15]:hover{color:#ff4d4f}.divider[data-v-0ddb3f15]{background:#e0e0e0;width:1px;height:14px}.add-btn[data-v-0ddb3f15]{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-0ddb3f15]:hover{color:#1a1a1a;background:#1a1a1a0a;border-color:#1a1a1a}.add-menu[data-v-0ddb3f15]{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-0ddb3f15]{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-0ddb3f15]{padding:4px 0}.menu-section[data-v-0ddb3f15]:not(:last-child){border-bottom:1px solid #f0f0f0}.menu-title[data-v-0ddb3f15]{color:#999;padding:4px 16px;font-size:12px;font-weight:500}.menu-items[data-v-0ddb3f15]{flex-direction:column;gap:2px;display:flex}.menu-item[data-v-0ddb3f15]{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-0ddb3f15]:hover:not(.disabled){background:#f5f5f5}.menu-item.disabled[data-v-0ddb3f15]{color:#999;cursor:not-allowed}.menu-item .param-hint[data-v-0ddb3f15]{color:#999;font-size:11px}.active-tag[data-v-0ddb3f15]{color:#1a1a1a;align-items:center;margin-left:auto;display:flex}.fade-enter-active[data-v-0ddb3f15],.fade-leave-active[data-v-0ddb3f15]{transition:opacity .2s}.fade-enter-from[data-v-0ddb3f15],.fade-leave-to[data-v-0ddb3f15]{opacity:0}.slide-enter-active[data-v-0ddb3f15],.slide-leave-active[data-v-0ddb3f15]{transition:all .2s}.slide-enter-from[data-v-0ddb3f15],.slide-leave-to[data-v-0ddb3f15]{opacity:0;transform:translate(-50%)translateY(8px)}.chart-wrapper[data-v-288af50a]{--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-288af50a]{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-288af50a]::-webkit-scrollbar{display:none}.chart-container[data-v-288af50a]:hover{cursor:grab}.chart-container.is-resizing-pane[data-v-288af50a],.chart-container.is-hovering-pane-separator[data-v-288af50a]{cursor:row-resize}.scroll-content[data-v-288af50a]{height:100%;min-height:inherit;position:relative}.canvas-layer[data-v-288af50a]{pointer-events:none;position:sticky;top:0;left:0}.tooltip-anchor[data-v-288af50a]{pointer-events:none;width:1px;height:1px;position:absolute}.tooltip-anchor.kline-tooltip-anchor.use-anchor[data-v-288af50a]{anchor-name:--kline-tooltip-anchor}.tooltip-anchor.marker-tooltip-anchor.use-anchor[data-v-288af50a]{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 };
|
|
@@ -3,8 +3,6 @@ import { SubIndicatorType } from '../core/renderers/Indicator';
|
|
|
3
3
|
type __VLS_Props = {
|
|
4
4
|
/** 语义化配置(必需,唯一控制源) */
|
|
5
5
|
semanticConfig: SemanticChartConfig;
|
|
6
|
-
kWidth?: number;
|
|
7
|
-
kGap?: number;
|
|
8
6
|
yPaddingPx?: number;
|
|
9
7
|
minKWidth?: number;
|
|
10
8
|
maxKWidth?: number;
|
|
@@ -18,6 +16,8 @@ type __VLS_Props = {
|
|
|
18
16
|
zoomLevels?: number;
|
|
19
17
|
/** 初始缩放级别(1 ~ zoomLevels,默认居中) */
|
|
20
18
|
initialZoomLevel?: number;
|
|
19
|
+
/** 是否全屏 */
|
|
20
|
+
isFullscreen?: boolean;
|
|
21
21
|
};
|
|
22
22
|
declare function scheduleRender(): void;
|
|
23
23
|
declare function addSubPane(indicatorId?: SubIndicatorType, params?: Record<string, number>): boolean;
|
|
@@ -32,19 +32,19 @@ declare const _default: import('vue').DefineComponent<__VLS_Props, {
|
|
|
32
32
|
removeSubPane: typeof removeSubPane;
|
|
33
33
|
switchSubIndicator: typeof switchSubIndicator;
|
|
34
34
|
clearAllSubPanes: typeof clearAllSubPanes;
|
|
35
|
-
plugin: import('
|
|
35
|
+
plugin: import('../plugin').PluginHostImpl | undefined;
|
|
36
36
|
zoomToLevel: (level: number, anchorX?: number) => void | undefined;
|
|
37
37
|
zoomIn: (anchorX?: number) => void | undefined;
|
|
38
38
|
zoomOut: (anchorX?: number) => void | undefined;
|
|
39
39
|
getZoomLevel: () => number;
|
|
40
40
|
getZoomLevelCount: () => number;
|
|
41
41
|
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
42
|
+
toggleFullscreen: () => any;
|
|
42
43
|
zoomLevelChange: (level: number, kWidth: number) => any;
|
|
43
44
|
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
45
|
+
onToggleFullscreen?: (() => any) | undefined;
|
|
44
46
|
onZoomLevelChange?: ((level: number, kWidth: number) => any) | undefined;
|
|
45
47
|
}>, {
|
|
46
|
-
kWidth: number;
|
|
47
|
-
kGap: number;
|
|
48
48
|
yPaddingPx: number;
|
|
49
49
|
rightAxisWidth: number;
|
|
50
50
|
bottomAxisHeight: number;
|
|
@@ -53,6 +53,7 @@ declare const _default: import('vue').DefineComponent<__VLS_Props, {
|
|
|
53
53
|
priceLabelWidth: number;
|
|
54
54
|
zoomLevels: number;
|
|
55
55
|
initialZoomLevel: number;
|
|
56
|
+
isFullscreen: boolean;
|
|
56
57
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
|
|
57
58
|
containerRef: HTMLDivElement;
|
|
58
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
|
@@ -37,8 +37,10 @@ export type PaneRendererDom = {
|
|
|
37
37
|
yAxisCanvas: HTMLCanvasElement;
|
|
38
38
|
};
|
|
39
39
|
export type ChartOptions = {
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
/** K 线宽度(可选,由 zoomLevel 派生) */
|
|
41
|
+
kWidth?: number;
|
|
42
|
+
/** K 线间隙(可选,由 DPR 计算) */
|
|
43
|
+
kGap?: number;
|
|
42
44
|
yPaddingPx: number;
|
|
43
45
|
rightAxisWidth: number;
|
|
44
46
|
bottomAxisHeight: number;
|
|
@@ -58,8 +60,8 @@ export type ChartOptions = {
|
|
|
58
60
|
*/
|
|
59
61
|
zoomLevels?: number;
|
|
60
62
|
/**
|
|
61
|
-
* 初始缩放级别(1 ~ zoomLevels
|
|
62
|
-
*
|
|
63
|
+
* 初始缩放级别(1 ~ zoomLevels,默认 1)
|
|
64
|
+
* 未指定时默认为最小级别
|
|
63
65
|
*/
|
|
64
66
|
initialZoomLevel?: number;
|
|
65
67
|
};
|
|
@@ -73,6 +75,10 @@ export type Viewport = {
|
|
|
73
75
|
scrollLeft: number;
|
|
74
76
|
dpr: number;
|
|
75
77
|
};
|
|
78
|
+
type ResolvedChartOptions = Omit<ChartOptions, 'kWidth' | 'kGap'> & {
|
|
79
|
+
kWidth: number;
|
|
80
|
+
kGap: number;
|
|
81
|
+
};
|
|
76
82
|
export declare class Chart {
|
|
77
83
|
private dom;
|
|
78
84
|
private opt;
|
|
@@ -81,6 +87,7 @@ export declare class Chart {
|
|
|
81
87
|
private viewport;
|
|
82
88
|
private paneRenderers;
|
|
83
89
|
private markerManager;
|
|
90
|
+
private drawingStore;
|
|
84
91
|
readonly interaction: InteractionController;
|
|
85
92
|
/** 插件宿主 */
|
|
86
93
|
private pluginHost;
|
|
@@ -139,31 +146,19 @@ export declare class Chart {
|
|
|
139
146
|
*/
|
|
140
147
|
zoomAt(mouseX: number, scrollLeft: number, deltaY: number): void;
|
|
141
148
|
/**
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
* @param kWidth 新的 K 线宽度
|
|
145
|
-
* @param kGap 新的 K 线间隙
|
|
149
|
+
* 应用缩放级别(在 scrollLeft 落地后调用)
|
|
150
|
+
* @param level 缩放级别
|
|
146
151
|
*/
|
|
147
|
-
applyZoom(
|
|
148
|
-
/**
|
|
152
|
+
applyZoom(level: number): void;
|
|
153
|
+
/** 缩放回调 */
|
|
149
154
|
private onZoomChange?;
|
|
150
|
-
|
|
151
|
-
* 注册缩放回调函数
|
|
152
|
-
* @param cb 缩放回调函数
|
|
153
|
-
*/
|
|
154
|
-
setOnZoomChange(cb: (kWidth: number, kGap: number, targetScrollLeft: number) => void): void;
|
|
155
|
+
setOnZoomChange(cb: (level: number, kWidth: number, kGap: number, targetScrollLeft: number) => void): void;
|
|
155
156
|
/**
|
|
156
157
|
* 将缩放级别转换为 K 线宽度
|
|
157
158
|
* @param level 缩放级别(1 ~ zoomLevels)
|
|
158
159
|
* @returns K 线宽度(逻辑像素)
|
|
159
160
|
*/
|
|
160
161
|
private zoomLevelToKWidth;
|
|
161
|
-
/**
|
|
162
|
-
* 将 K 线宽度转换为缩放级别
|
|
163
|
-
* @param kWidth K 线宽度
|
|
164
|
-
* @returns 缩放级别(1 ~ zoomLevels)
|
|
165
|
-
*/
|
|
166
|
-
private kWidthToZoomLevel;
|
|
167
162
|
/**
|
|
168
163
|
* 缩放到指定级别
|
|
169
164
|
* @param level 目标级别(1 ~ zoomLevels)
|
|
@@ -210,7 +205,7 @@ export declare class Chart {
|
|
|
210
205
|
/** 获取 ChartDom(供 InteractionController 使用) */
|
|
211
206
|
getDom(): ChartDom;
|
|
212
207
|
/** 获取当前 ChartOptions(返回内部当前快照) */
|
|
213
|
-
getOption():
|
|
208
|
+
getOption(): ResolvedChartOptions;
|
|
214
209
|
/**
|
|
215
210
|
* 计算 K 线起始 x 坐标数组,与 candle.ts 的像素对齐方式保持一致
|
|
216
211
|
* @param range 可见 K 线索引范围
|
|
@@ -230,6 +225,8 @@ export declare class Chart {
|
|
|
230
225
|
upsertPane(def: PaneSpec): void;
|
|
231
226
|
removePaneDefinition(paneId: string): void;
|
|
232
227
|
bindIndicatorToPane(paneId: string, indicatorId: SubIndicatorType, params?: Record<string, number>): void;
|
|
228
|
+
/** 更新绘图对象 */
|
|
229
|
+
setDrawings(drawings: import('../plugin').DrawingObject[]): void;
|
|
233
230
|
/** 获取当前 pane 布局快照(含 ratio) */
|
|
234
231
|
getPaneLayoutSpecs(): PaneSpec[];
|
|
235
232
|
private emitPaneLayoutChange;
|
|
@@ -293,6 +290,8 @@ export declare class Chart {
|
|
|
293
290
|
updateData(data: KLineData[]): void;
|
|
294
291
|
/** 获取当前数据源(供 renderers 和 interaction 使用) */
|
|
295
292
|
getData(): KLineData[];
|
|
293
|
+
/** 根据视口内 X 坐标反查数据索引(用于绘图落点) */
|
|
294
|
+
getDataIndexAtX(mouseX: number): number | null;
|
|
296
295
|
/** 获取内容总宽度(用于外部 scroll-content 撑开 scrollWidth) */
|
|
297
296
|
getContentWidth(): number;
|
|
298
297
|
/** 容器尺寸变化时调用 */
|
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
import { Chart } from '../chart';
|
|
2
2
|
import { MarkerEntity, CustomMarkerEntity } from '../marker/registry';
|
|
3
3
|
/** 标记 hover 事件数据 */
|
|
4
|
-
export interface
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
export interface InteractionSnapshot {
|
|
5
|
+
crosshairPos: {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
} | null;
|
|
9
|
+
crosshairIndex: number | null;
|
|
10
|
+
crosshairPrice: number | null;
|
|
11
|
+
hoveredIndex: number | null;
|
|
12
|
+
activePaneId: string | null;
|
|
13
|
+
tooltipPos: {
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
};
|
|
17
|
+
tooltipAnchorPlacement: 'right-bottom' | 'left-bottom';
|
|
18
|
+
hoveredMarkerData: MarkerEntity | null;
|
|
19
|
+
hoveredCustomMarker: CustomMarkerEntity | null;
|
|
20
|
+
isDragging: boolean;
|
|
21
|
+
isResizingPaneBoundary: boolean;
|
|
22
|
+
isHoveringPaneBoundary: boolean;
|
|
23
|
+
isHoveringRightAxis: boolean;
|
|
7
24
|
}
|
|
8
25
|
/**
|
|
9
26
|
* 交互控制器,处理拖拽滚动、缩放、十字线 hover 等交互逻辑
|
|
@@ -20,6 +37,8 @@ export declare class InteractionController {
|
|
|
20
37
|
/** 分隔线拖拽相关 */
|
|
21
38
|
private activeSeparatorUpperPaneId;
|
|
22
39
|
private hoveredSeparatorUpperPaneId;
|
|
40
|
+
/** 右轴悬浮相关 */
|
|
41
|
+
private hoveredRightAxisPaneId;
|
|
23
42
|
/** [触屏]:触摸会话标记,避免触摸触发的模拟 mouse 事件干扰 */
|
|
24
43
|
private isTouchSession;
|
|
25
44
|
/** 十字线位置 */
|
|
@@ -49,6 +68,8 @@ export declare class InteractionController {
|
|
|
49
68
|
tooltipAnchorPlacement: 'right-bottom' | 'left-bottom';
|
|
50
69
|
/** 是否使用 CSS 锚定位 */
|
|
51
70
|
private useTooltipAnchorPositioning;
|
|
71
|
+
/** 统一交互状态变更回调 */
|
|
72
|
+
private onInteractionChangeCallback?;
|
|
52
73
|
/** 当前 hover 的 marker ID */
|
|
53
74
|
hoveredMarkerId: string | null;
|
|
54
75
|
/** 当前点击的 marker ID */
|
|
@@ -74,6 +95,9 @@ export declare class InteractionController {
|
|
|
74
95
|
/** K 线宽度(物理像素),用于计算 K 线中心偏移 */
|
|
75
96
|
private kWidthPx;
|
|
76
97
|
constructor(chart: Chart);
|
|
98
|
+
getInteractionSnapshot(): InteractionSnapshot;
|
|
99
|
+
setOnInteractionChange(callback: (snapshot: InteractionSnapshot) => void): void;
|
|
100
|
+
private notifyInteractionChange;
|
|
77
101
|
/**
|
|
78
102
|
* 处理滚轮缩放事件
|
|
79
103
|
* @param e WheelEvent
|
|
@@ -140,6 +164,8 @@ export declare class InteractionController {
|
|
|
140
164
|
isResizingPaneBoundaryState(): boolean;
|
|
141
165
|
/** 是否悬停在可拖拽分隔线上 */
|
|
142
166
|
isHoveringPaneBoundaryState(): boolean;
|
|
167
|
+
/** 是否悬停在右轴区域 */
|
|
168
|
+
isHoveringRightAxisState(): boolean;
|
|
143
169
|
/** 设置 marker hover 回调 */
|
|
144
170
|
setOnMarkerHover(callback: (marker: MarkerEntity | null) => void): void;
|
|
145
171
|
/** 设置 marker click 回调 */
|
|
@@ -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;
|
|
@@ -11,6 +11,8 @@ export interface IndicatorScaleRendererOptions {
|
|
|
11
11
|
price: number;
|
|
12
12
|
activePaneId: string | null;
|
|
13
13
|
} | null;
|
|
14
|
+
formatTickLabel?: (value: number) => string;
|
|
15
|
+
formatCrosshairLabel?: (value: number) => string;
|
|
14
16
|
}
|
|
15
17
|
export interface DrawScaleTicksOptions {
|
|
16
18
|
ctx: CanvasRenderingContext2D;
|
|
@@ -24,6 +26,7 @@ export interface DrawScaleTicksOptions {
|
|
|
24
26
|
isMain: boolean;
|
|
25
27
|
decimals?: number;
|
|
26
28
|
hideEdgeTicks?: boolean;
|
|
29
|
+
formatLabel?: (value: number) => string;
|
|
27
30
|
}
|
|
28
31
|
export declare function drawScaleTicks(options: DrawScaleTicksOptions): void;
|
|
29
32
|
export declare function createIndicatorScaleRendererPlugin(options: IndicatorScaleRendererOptions): RendererPluginWithHost;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { RendererPluginWithHost } from '../../../../plugin';
|
|
2
|
+
/**
|
|
3
|
+
* 创建成交量刻度渲染器插件
|
|
4
|
+
*/
|
|
5
|
+
export declare function createVolumeScaleRendererPlugin(options: {
|
|
6
|
+
axisWidth: number;
|
|
7
|
+
paneId: string;
|
|
8
|
+
yPaddingPx?: number;
|
|
9
|
+
getCrosshair?: () => {
|
|
10
|
+
y: number;
|
|
11
|
+
price: number;
|
|
12
|
+
activePaneId: string | null;
|
|
13
|
+
} | null;
|
|
14
|
+
}): RendererPluginWithHost;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RendererPluginWithHost, BaseIndicatorState } from '../../plugin';
|
|
2
2
|
export interface VolumeRendererOptions {
|
|
3
3
|
/** 目标 pane ID(默认 'sub') */
|
|
4
4
|
paneId?: string;
|
|
5
5
|
}
|
|
6
|
+
export interface VolumeRenderState extends BaseIndicatorState {
|
|
7
|
+
valueMin: number;
|
|
8
|
+
valueMax: number;
|
|
9
|
+
}
|
|
6
10
|
/**
|
|
7
11
|
* 创建副图成交量渲染器插件
|
|
8
12
|
*/
|
|
9
|
-
export declare function createVolumeRendererPlugin(options?: VolumeRendererOptions):
|
|
13
|
+
export declare function createVolumeRendererPlugin(options?: VolumeRendererOptions): RendererPluginWithHost;
|
|
@@ -45,7 +45,7 @@ export declare const PRICE_COLORS: {
|
|
|
45
45
|
/** 中性颜色 */
|
|
46
46
|
readonly NEUTRAL: "rgba(0, 0, 0, 0.78)";
|
|
47
47
|
/** 最新价颜色 */
|
|
48
|
-
readonly LAST_PRICE: "
|
|
48
|
+
readonly LAST_PRICE: "rgba(196, 74, 86, 0.95)";
|
|
49
49
|
};
|
|
50
50
|
/**
|
|
51
51
|
* 十字线标签背景颜色
|
|
@@ -129,6 +129,17 @@ export declare const MACD_COLORS: {
|
|
|
129
129
|
/** MACD 柱淡绿色(负值上升) */
|
|
130
130
|
readonly BAR_DOWN_LIGHT: "#ace5dc";
|
|
131
131
|
};
|
|
132
|
+
/**
|
|
133
|
+
* 成交量颜色(与 MACD 柱子配色一致)
|
|
134
|
+
*/
|
|
135
|
+
export declare const VOLUME_COLORS: {
|
|
136
|
+
/** 上涨柱子(与 MACD BAR_UP 一致) */
|
|
137
|
+
readonly UP: "#ff5252";
|
|
138
|
+
/** 下跌柱子(与 MACD BAR_DOWN 一致) */
|
|
139
|
+
readonly DOWN: "#22ab94";
|
|
140
|
+
/** 中性/平盘柱子 */
|
|
141
|
+
readonly NEUTRAL: "rgba(0, 0, 0, 0.78)";
|
|
142
|
+
};
|
|
132
143
|
/**
|
|
133
144
|
* RSI 颜色
|
|
134
145
|
*/
|
|
@@ -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;
|
|
@@ -87,6 +87,7 @@ export interface CrosshairPriceLabelOptions {
|
|
|
87
87
|
yPaddingPx?: number;
|
|
88
88
|
dpr: number;
|
|
89
89
|
bgColor?: string;
|
|
90
|
+
borderColor?: string;
|
|
90
91
|
textColor?: string;
|
|
91
92
|
fontSize?: number;
|
|
92
93
|
paddingX?: number;
|
|
@@ -94,6 +95,7 @@ export interface CrosshairPriceLabelOptions {
|
|
|
94
95
|
priceOffset?: number;
|
|
95
96
|
/** 优先显示的价格(如十字线已按 active pane 算好) */
|
|
96
97
|
price?: number;
|
|
98
|
+
formatPrice?: (price: number) => string;
|
|
97
99
|
}
|
|
98
100
|
export interface CrosshairTimeLabelOptions {
|
|
99
101
|
x: number;
|