@363045841yyt/klinechart 0.5.5-alpha.0 → 0.5.6
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 +5 -3
- package/dist/index.cjs +4 -4
- package/dist/index.js +2864 -2333
- package/dist/klinechart.css +1 -1
- package/dist/src/components/KLineChart.vue.d.ts +34 -0
- package/dist/src/components/LeftToolbar.vue.d.ts +8 -2
- package/dist/src/composables/useFullscreenTeleportTarget.d.ts +3 -0
- package/dist/src/config/chartSettings.d.ts +13 -0
- package/dist/src/core/chart.d.ts +4 -0
- package/dist/src/core/drawing/interaction.d.ts +1 -0
- package/dist/src/core/renderers/Indicator/scale/indicator_scale.d.ts +3 -0
- package/dist/src/core/scale/logFormula.d.ts +66 -0
- package/dist/src/core/scale/priceScale.d.ts +36 -2
- package/dist/src/core/theme/fonts.d.ts +11 -0
- package/dist/src/core/utils/tickPosition.d.ts +24 -0
- package/dist/src/plugin/types.d.ts +66 -0
- package/dist/src/utils/kLineDraw/axis.d.ts +37 -0
- package/package.json +37 -1
- package/dist/src/semantic/schema.json.d.ts +0 -259
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)}.drawing-style-toolbar[data-v-088ccef5]{-webkit-backdrop-filter:blur(8px);z-index:100;-webkit-user-select:none;user-select:none;pointer-events:auto;background:#fafbfce0;border:1px solid #e5e7eb;border-radius:6px;align-items:center;gap:6px;height:32px;padding:4px 8px;display:flex;position:absolute;top:8px;left:50%;transform:translate(-50%);box-shadow:0 1px 3px #0000000f}.toolbar-item[data-v-088ccef5]{justify-content:center;align-items:center;display:inline-flex}.color-item[data-v-088ccef5]{width:24px;height:24px;position:relative}.color-swatch[data-v-088ccef5]{cursor:pointer;border:1px solid #d1d5db;border-radius:4px;width:100%;height:100%;display:block}.color-input[data-v-088ccef5]{opacity:0;cursor:pointer;width:100%;height:100%;position:absolute;inset:0}.toolbar-select[data-v-088ccef5]{color:#374151;cursor:pointer;background:#fff;border:1px solid #d1d5db;border-radius:4px;outline:none;height:24px;padding:0 4px;font-size:12px}.toolbar-select[data-v-088ccef5]:hover{border-color:#9ca3af}.toolbar-btn[data-v-088ccef5]{color:#6b7280;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:4px;justify-content:center;align-items:center;width:24px;height:24px;padding:0;transition:border-color .15s,background .15s,color .15s;display:inline-flex}.toolbar-btn[data-v-088ccef5]:hover{color:#374151;background:#f3f4f6;border-color:#d1d5db}.delete-btn[data-v-088ccef5]:hover{color:#dc2626;background:#fef2f2;border-color:#fca5a5}.delete-icon[data-v-088ccef5]{width:14px;height:14px}.left-toolbar[data-v-f1125609]{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-f1125609]{flex-direction:column;gap:4px;display:flex}.left-toolbar__divider[data-v-f1125609]{background:#e5e7eb;width:18px;height:1px}.left-toolbar__button[data-v-f1125609]{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-f1125609]:hover{color:#374151;background:#f3f4f6;border-color:#d1d5db}.left-toolbar__button.active[data-v-f1125609]{color:#1f2937;background:#e5e7eb;border-color:#9ca3af}.left-toolbar__button[data-v-f1125609]:focus-visible{border-color:#6b7280;outline:none}.tool-icon[data-v-f1125609]{width:16px;height:16px}.corner-indicator[data-v-f1125609]{cursor:pointer;width:8px;height:8px;position:absolute;bottom:0;right:0;overflow:hidden}.corner-indicator[data-v-f1125609]: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-f1125609]:after,.left-toolbar__button.active .corner-indicator[data-v-f1125609]:after{opacity:.7}.corner-indicator.open[data-v-f1125609]:after{opacity:.8}.tool-dropdown[data-v-f1125609]{-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-f1125609]{position:relative}.dropdown-enter-active[data-v-f1125609],.dropdown-leave-active[data-v-f1125609]{transition:opacity .15s,transform .15s}.dropdown-enter-from[data-v-f1125609],.dropdown-leave-to[data-v-f1125609]{opacity:0;transform:translateY(-50%)translate(-6px)}@media (width<=768px),(height<=640px){.left-toolbar[data-v-f1125609]{border-radius:5px;flex-basis:36px;gap:5px;padding:6px 4px}.left-toolbar__group[data-v-f1125609]{gap:3px}.left-toolbar__button[data-v-f1125609]{border-radius:3px;width:26px;height:26px}.left-toolbar__divider[data-v-f1125609]{width:16px}.corner-indicator[data-v-f1125609]{width:7px;height:7px}.corner-indicator[data-v-f1125609]:after{border-bottom-width:4px;border-left-width:4px}.tool-dropdown[data-v-f1125609]{height:36px}}.chart-wrapper[data-v-c53b9583]{--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-c53b9583]{align-items:stretch;gap:8px;width:95%;height:85%;min-height:255px;display:flex}.chart-main[data-v-c53b9583]{flex:auto;align-items:stretch;gap:0;min-width:0;height:100%;display:flex;position:relative}.pane-separator-layer[data-v-c53b9583]{pointer-events:none;z-index:20;position:absolute;inset:0}.pane-separator-line[data-v-c53b9583]{opacity:1;box-sizing:border-box;border-top:1px solid #e5e7eb;height:0;transition:border-top-color .12s,border-top-width .12s,margin-top .12s,opacity .12s;position:absolute;left:0;right:0}.pane-separator-line.is-active[data-v-c53b9583]{border-top-width:2px;border-top-color:#3b82f6;margin-top:-1px}.chart-stage.is-resizing-pane[data-v-c53b9583],.chart-stage.is-hovering-pane-separator[data-v-c53b9583]{cursor:ns-resize}.chart-stage.is-hovering-kline[data-v-c53b9583]{cursor:pointer}.chart-stage.is-hovering-right-axis[data-v-c53b9583]{cursor:ns-resize}.chart-stage.is-dragging[data-v-c53b9583]{cursor:grabbing}.chart-container[data-v-c53b9583]{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-right:0;border-radius:6px 0 0 6px;flex:auto;position:relative;overflow:auto hidden}.chart-container[data-v-c53b9583]::-webkit-scrollbar{display:none}.chart-container[data-v-c53b9583]:hover{cursor:crosshair}.chart-stage.is-resizing-pane .chart-container[data-v-c53b9583],.chart-stage.is-hovering-pane-separator .chart-container[data-v-c53b9583]{cursor:ns-resize}.chart-stage.is-hovering-kline .chart-container[data-v-c53b9583]{cursor:pointer}.chart-stage.is-dragging .chart-container[data-v-c53b9583]{cursor:grabbing}.right-axis-host[data-v-c53b9583]{height:100%;min-height:inherit;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-top-right-radius:6px;border-bottom-right-radius:6px;flex:none;position:relative;overflow:visible}.scroll-content[data-v-c53b9583]{height:100%;min-height:inherit;position:relative}.canvas-layer[data-v-c53b9583]{pointer-events:none;position:sticky;top:0;left:0}.tooltip-layer[data-v-c53b9583]{pointer-events:none;z-index:30;position:absolute;inset:0}.tooltip-anchor[data-v-c53b9583]{pointer-events:none;width:1px;height:1px;position:absolute}.tooltip-anchor.kline-tooltip-anchor.use-anchor[data-v-c53b9583]{anchor-name:--kline-tooltip-anchor}.tooltip-anchor.marker-tooltip-anchor.use-anchor[data-v-c53b9583]{anchor-name:--marker-tooltip-anchor}@media (width<=768px),(height<=640px){.chart-stage[data-v-c53b9583]{gap:6px}}.plot-canvas{display:block;position:absolute;top:0;left:0}.right-axis{display:block;position:absolute;left:0}.x-axis-canvas{z-index:10;display:block;position:absolute;bottom:0;left:0}.right-axis{z-index:15}
|
|
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-bb1d1eb3]{-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-bb1d1eb3]{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-bb1d1eb3]{background:#f8f8f8;border-bottom:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:16px 20px;display:flex}.header-left[data-v-bb1d1eb3]{align-items:baseline;gap:8px;display:flex}.header-right[data-v-bb1d1eb3]{align-items:center;gap:8px;display:flex}.params-title[data-v-bb1d1eb3]{color:#1a1a1a;letter-spacing:.2px;font-size:14px;font-weight:600}.params-subtitle[data-v-bb1d1eb3]{color:#999;font-size:11px}.toggle-desc-btn[data-v-bb1d1eb3]{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-bb1d1eb3]:hover{color:#555;background:#f0f0f0;border-color:#ccc}.toggle-desc-btn.active[data-v-bb1d1eb3]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.toggle-desc-btn svg[data-v-bb1d1eb3]{width:14px;height:14px}.params-close[data-v-bb1d1eb3]{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-bb1d1eb3]:hover{color:#333;background:#f0f0f0;border-color:#ccc}.params-close svg[data-v-bb1d1eb3]{width:14px;height:14px}.indicator-description[data-v-bb1d1eb3]{background:#f0f7ff;border-bottom:1px solid #d6e8f5;padding:12px 20px}.indicator-description p[data-v-bb1d1eb3]{color:#2c5282;margin:0;font-size:12px;line-height:1.6}.params-body[data-v-bb1d1eb3]{flex-direction:column;gap:10px;padding:16px 20px;display:flex}.param-item[data-v-bb1d1eb3]{background:#f8f8f8;border:1px solid #e8e8e8;border-radius:8px;padding:10px 14px;transition:border-color .2s}.param-item[data-v-bb1d1eb3]:has(.param-input:focus){border-color:#bbb}.param-item.has-desc[data-v-bb1d1eb3]{padding:10px 14px 8px}.param-header[data-v-bb1d1eb3]{justify-content:space-between;align-items:center;gap:16px;display:flex}.param-label[data-v-bb1d1eb3]{flex-direction:column;gap:3px;display:flex}.param-label-text[data-v-bb1d1eb3]{color:#333;font-size:13px;font-weight:500}.param-range[data-v-bb1d1eb3]{color:#999;font-size:11px}.param-description[data-v-bb1d1eb3]{color:#666;border-top:1px dashed #e0e0e0;margin-top:8px;padding-top:8px;font-size:11px;line-height:1.5}.input-wrapper[data-v-bb1d1eb3]{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-bb1d1eb3]:focus-within{border-color:#999}.stepper-btn[data-v-bb1d1eb3]{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-bb1d1eb3]:hover:not(:disabled){color:#333;background:#e0e0e0}.stepper-btn[data-v-bb1d1eb3]:disabled{color:#ccc;cursor:not-allowed}.param-input[data-v-bb1d1eb3]{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-bb1d1eb3]::-webkit-inner-spin-button{-webkit-appearance:none}.param-input[data-v-bb1d1eb3]::-webkit-outer-spin-button{-webkit-appearance:none}.param-input[data-v-bb1d1eb3]:focus{outline:none}.params-footer[data-v-bb1d1eb3]{background:#f8f8f8;border-top:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:12px 20px;display:flex}.footer-right[data-v-bb1d1eb3]{gap:8px;display:flex}.params-btn[data-v-bb1d1eb3]{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-bb1d1eb3]{flex-shrink:0;width:12px;height:12px}.params-btn.reset[data-v-bb1d1eb3]{color:#666;background:0 0;border-color:#d0d0d0}.params-btn.reset[data-v-bb1d1eb3]:hover{color:#e74c3c;background:#e74c3c14;border-color:#c0392b}.params-btn.cancel[data-v-bb1d1eb3]{color:#666;background:0 0;border-color:#d0d0d0}.params-btn.cancel[data-v-bb1d1eb3]:hover{color:#333;background:#f0f0f0;border-color:#bbb}.params-btn.confirm[data-v-bb1d1eb3]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.params-btn.confirm[data-v-bb1d1eb3]:hover{background:#333;border-color:#333;transform:translateY(-1px);box-shadow:0 2px 10px #00000026}.params-btn.confirm[data-v-bb1d1eb3]:active{box-shadow:none;transform:translateY(0)}.overlay-enter-active[data-v-bb1d1eb3],.overlay-leave-active[data-v-bb1d1eb3]{transition:opacity .2s}.overlay-enter-from[data-v-bb1d1eb3],.overlay-leave-to[data-v-bb1d1eb3]{opacity:0}.modal-enter-active[data-v-bb1d1eb3]{transition:all .22s cubic-bezier(.34,1.56,.64,1)}.modal-leave-active[data-v-bb1d1eb3]{transition:all .16s ease-in}.modal-enter-from[data-v-bb1d1eb3]{opacity:0;transform:scale(.88)translateY(-16px)}.modal-leave-to[data-v-bb1d1eb3]{opacity:0;transform:scale(.94)translateY(8px)}.slide-enter-active[data-v-bb1d1eb3],.slide-leave-active[data-v-bb1d1eb3]{transition:all .2s;overflow:hidden}.slide-enter-from[data-v-bb1d1eb3],.slide-leave-to[data-v-bb1d1eb3]{opacity:0;max-height:0;margin-top:0;padding-top:0;padding-bottom:0}.indicator-selector[data-v-0f3a76b5]{width:80%;margin:20px;position:relative}.indicator-scroll-container[data-v-0f3a76b5]{scrollbar-width:none;-webkit-overflow-scrolling:touch;text-align:center;width:100%;overflow:auto hidden}.indicator-scroll-container[data-v-0f3a76b5]::-webkit-scrollbar{display:none}.indicator-list[data-v-0f3a76b5]{gap:8px;margin:0 auto;padding:2px;display:inline-flex}.indicator-divider[data-v-0f3a76b5]{background:#d9d9d9;align-self:center;width:1px;height:20px}.indicator-item[data-v-0f3a76b5]{align-items:center;gap:4px;display:flex}.indicator-item.draggable[data-v-0f3a76b5],.indicator-item.draggable .indicator-btn[data-v-0f3a76b5],.indicator-item.draggable[data-v-0f3a76b5]:hover,.indicator-item.draggable:hover .indicator-btn[data-v-0f3a76b5]{cursor:move}.indicator-item.is-dragging[data-v-0f3a76b5]{opacity:.6}.indicator-item.drag-over .indicator-btn[data-v-0f3a76b5]{border-color:#1a1a1a;box-shadow:0 0 0 2px #1a1a1a1f}.indicator-btn-wrapper[data-v-0f3a76b5]{position:relative}.indicator-btn[data-v-0f3a76b5]{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-0f3a76b5]:hover:not(.hovering){color:#333;background:#f8f8f8;border-color:#ccc}.indicator-btn.active[data-v-0f3a76b5]{color:#1a1a1a;background:#f8f8f8;border-color:#1a1a1a}.indicator-btn.active[data-v-0f3a76b5]:hover:not(.hovering){background:#f0f0f0;border-color:#333}.btn-content[data-v-0f3a76b5]{z-index:1;position:relative}.param-hint[data-v-0f3a76b5]{opacity:.85;font-size:11px}.hover-overlay[data-v-0f3a76b5]{-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-0f3a76b5]{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-0f3a76b5]:hover{color:#333;background:#0000000f}.settings-btn[data-v-0f3a76b5]:hover{color:#1a1a1a}.remove-btn[data-v-0f3a76b5]:hover{color:#ff4d4f}.divider[data-v-0f3a76b5]{background:#e0e0e0;width:1px;height:14px}.add-btn[data-v-0f3a76b5]{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-0f3a76b5]:hover{color:#1a1a1a;background:#1a1a1a0a;border-color:#1a1a1a}.add-menu[data-v-0f3a76b5]{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-0f3a76b5]{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-0f3a76b5]{padding:4px 0}.menu-section[data-v-0f3a76b5]:not(:last-child){border-bottom:1px solid #f0f0f0}.menu-title[data-v-0f3a76b5]{color:#999;padding:4px 16px;font-size:12px;font-weight:500}.menu-items[data-v-0f3a76b5]{flex-direction:column;gap:2px;display:flex}.menu-item[data-v-0f3a76b5]{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-0f3a76b5]:hover:not(.disabled){background:#f5f5f5}.menu-item.disabled[data-v-0f3a76b5]{color:#999;cursor:not-allowed}.menu-item .param-hint[data-v-0f3a76b5]{color:#999;font-size:11px}.active-tag[data-v-0f3a76b5]{color:#1a1a1a;align-items:center;margin-left:auto;display:flex}.fade-enter-active[data-v-0f3a76b5],.fade-leave-active[data-v-0f3a76b5]{transition:opacity .2s}.fade-enter-from[data-v-0f3a76b5],.fade-leave-to[data-v-0f3a76b5]{opacity:0}.slide-enter-active[data-v-0f3a76b5],.slide-leave-active[data-v-0f3a76b5]{transition:all .2s}.slide-enter-from[data-v-0f3a76b5],.slide-leave-to[data-v-0f3a76b5]{opacity:0;transform:translate(-50%)translateY(8px)}.drawing-style-toolbar[data-v-088ccef5]{-webkit-backdrop-filter:blur(8px);z-index:100;-webkit-user-select:none;user-select:none;pointer-events:auto;background:#fafbfce0;border:1px solid #e5e7eb;border-radius:6px;align-items:center;gap:6px;height:32px;padding:4px 8px;display:flex;position:absolute;top:8px;left:50%;transform:translate(-50%);box-shadow:0 1px 3px #0000000f}.toolbar-item[data-v-088ccef5]{justify-content:center;align-items:center;display:inline-flex}.color-item[data-v-088ccef5]{width:24px;height:24px;position:relative}.color-swatch[data-v-088ccef5]{cursor:pointer;border:1px solid #d1d5db;border-radius:4px;width:100%;height:100%;display:block}.color-input[data-v-088ccef5]{opacity:0;cursor:pointer;width:100%;height:100%;position:absolute;inset:0}.toolbar-select[data-v-088ccef5]{color:#374151;cursor:pointer;background:#fff;border:1px solid #d1d5db;border-radius:4px;outline:none;height:24px;padding:0 4px;font-size:12px}.toolbar-select[data-v-088ccef5]:hover{border-color:#9ca3af}.toolbar-btn[data-v-088ccef5]{color:#6b7280;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:4px;justify-content:center;align-items:center;width:24px;height:24px;padding:0;transition:border-color .15s,background .15s,color .15s;display:inline-flex}.toolbar-btn[data-v-088ccef5]:hover{color:#374151;background:#f3f4f6;border-color:#d1d5db}.delete-btn[data-v-088ccef5]:hover{color:#dc2626;background:#fef2f2;border-color:#fca5a5}.delete-icon[data-v-088ccef5]{width:14px;height:14px}.left-toolbar[data-v-1f5465f7]{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-1f5465f7]{flex-direction:column;gap:4px;display:flex}.left-toolbar__divider[data-v-1f5465f7]{background:#e5e7eb;width:18px;height:1px}.left-toolbar__button[data-v-1f5465f7]{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-1f5465f7]:hover{color:#374151;background:#f3f4f6;border-color:#d1d5db}.left-toolbar__button.active[data-v-1f5465f7]{color:#1f2937;background:#e5e7eb;border-color:#9ca3af}.left-toolbar__button[data-v-1f5465f7]:focus-visible{border-color:#6b7280;outline:none}.tool-icon[data-v-1f5465f7]{width:16px;height:16px}.corner-indicator[data-v-1f5465f7]{cursor:pointer;width:8px;height:8px;position:absolute;bottom:0;right:0;overflow:hidden}.corner-indicator[data-v-1f5465f7]: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-1f5465f7]:after,.left-toolbar__button.active .corner-indicator[data-v-1f5465f7]:after{opacity:.7}.corner-indicator.open[data-v-1f5465f7]:after{opacity:.8}.tool-dropdown[data-v-1f5465f7]{-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-1f5465f7]{position:relative}.dropdown-enter-active[data-v-1f5465f7],.dropdown-leave-active[data-v-1f5465f7]{transition:opacity .15s,transform .15s}.dropdown-enter-from[data-v-1f5465f7],.dropdown-leave-to[data-v-1f5465f7]{opacity:0;transform:translateY(-50%)translate(-6px)}@media (width<=768px),(height<=640px){.left-toolbar[data-v-1f5465f7]{border-radius:5px;flex-basis:36px;gap:5px;padding:6px 4px}.left-toolbar__group[data-v-1f5465f7]{gap:3px}.left-toolbar__button[data-v-1f5465f7]{border-radius:3px;width:26px;height:26px}.left-toolbar__divider[data-v-1f5465f7]{width:16px}.corner-indicator[data-v-1f5465f7]{width:7px;height:7px}.corner-indicator[data-v-1f5465f7]:after{border-bottom-width:4px;border-left-width:4px}.tool-dropdown[data-v-1f5465f7]{height:36px}}.settings-overlay[data-v-1f5465f7]{-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}.settings-modal[data-v-1f5465f7]{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}.settings-header[data-v-1f5465f7]{background:#f8f8f8;border-bottom:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:16px 20px;display:flex}.header-left[data-v-1f5465f7]{align-items:baseline;gap:8px;display:flex}.header-right[data-v-1f5465f7]{align-items:center;gap:8px;display:flex}.settings-title[data-v-1f5465f7]{color:#1a1a1a;letter-spacing:.2px;font-size:14px;font-weight:600}.settings-subtitle[data-v-1f5465f7]{color:#999;font-size:11px}.settings-close[data-v-1f5465f7]{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}.settings-close[data-v-1f5465f7]:hover{color:#333;background:#f0f0f0;border-color:#ccc}.settings-close svg[data-v-1f5465f7]{width:14px;height:14px}.settings-body[data-v-1f5465f7]{flex-direction:column;gap:10px;padding:16px 20px;display:flex}.settings-item[data-v-1f5465f7]{background:#f8f8f8;border:1px solid #e8e8e8;border-radius:8px;padding:8px 12px}.settings-label[data-v-1f5465f7]{color:#333;cursor:pointer;justify-content:space-between;align-items:center;font-size:13px;display:flex}.settings-checkbox[data-v-1f5465f7]{cursor:pointer;accent-color:#1a1a1a;width:16px;height:16px}.settings-footer[data-v-1f5465f7]{background:#f8f8f8;border-top:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:12px 20px;display:flex}.footer-right[data-v-1f5465f7]{gap:8px;display:flex}.settings-btn[data-v-1f5465f7]{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}.settings-btn svg[data-v-1f5465f7]{flex-shrink:0;width:12px;height:12px}.settings-btn.reset[data-v-1f5465f7]{color:#666;background:0 0;border-color:#d0d0d0}.settings-btn.reset[data-v-1f5465f7]:hover{color:#e74c3c;background:#e74c3c14;border-color:#c0392b}.settings-btn.cancel[data-v-1f5465f7]{color:#666;background:0 0;border-color:#d0d0d0}.settings-btn.cancel[data-v-1f5465f7]:hover{color:#333;background:#f0f0f0;border-color:#bbb}.settings-btn.confirm[data-v-1f5465f7]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.settings-btn.confirm[data-v-1f5465f7]:hover{background:#333;border-color:#333;transform:translateY(-1px);box-shadow:0 2px 10px #00000026}.settings-btn.confirm[data-v-1f5465f7]:active{box-shadow:none;transform:translateY(0)}.chart-wrapper[data-v-fff9d345]{--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-fff9d345]{align-items:stretch;gap:8px;width:95%;height:85%;min-height:255px;display:flex}.chart-main[data-v-fff9d345]{flex:auto;align-items:stretch;gap:0;min-width:0;height:100%;display:flex;position:relative}.pane-separator-layer[data-v-fff9d345]{pointer-events:none;z-index:20;position:absolute;inset:0}.pane-separator-line[data-v-fff9d345]{opacity:1;box-sizing:border-box;border-top:1px solid #e5e7eb;height:0;transition:border-top-color .12s,border-top-width .12s,margin-top .12s,opacity .12s;position:absolute;left:0;right:0}.pane-separator-line.is-active[data-v-fff9d345]{border-top-width:2px;border-top-color:#3b82f6;margin-top:-1px}.chart-stage.is-resizing-pane[data-v-fff9d345],.chart-stage.is-hovering-pane-separator[data-v-fff9d345]{cursor:ns-resize}.chart-stage.is-hovering-kline[data-v-fff9d345]{cursor:pointer}.chart-stage.is-hovering-right-axis[data-v-fff9d345]{cursor:ns-resize}.chart-stage.is-dragging[data-v-fff9d345]{cursor:grabbing}.chart-container[data-v-fff9d345]{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-right:0;border-radius:6px 0 0 6px;flex:auto;position:relative;overflow:auto hidden}.chart-container[data-v-fff9d345]::-webkit-scrollbar{display:none}.chart-container[data-v-fff9d345]:hover{cursor:crosshair}.chart-stage.is-resizing-pane .chart-container[data-v-fff9d345],.chart-stage.is-hovering-pane-separator .chart-container[data-v-fff9d345]{cursor:ns-resize}.chart-stage.is-hovering-kline .chart-container[data-v-fff9d345]{cursor:pointer}.chart-stage.is-dragging .chart-container[data-v-fff9d345]{cursor:grabbing}.right-axis-host[data-v-fff9d345]{height:100%;min-height:inherit;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-top-right-radius:6px;border-bottom-right-radius:6px;flex:none;position:relative;overflow:visible}.scroll-content[data-v-fff9d345]{height:100%;min-height:inherit;position:relative}.canvas-layer[data-v-fff9d345]{pointer-events:none;position:sticky;top:0;left:0}.tooltip-layer[data-v-fff9d345]{pointer-events:none;z-index:30;position:absolute;inset:0}.tooltip-anchor[data-v-fff9d345]{pointer-events:none;width:1px;height:1px;position:absolute}.tooltip-anchor.kline-tooltip-anchor.use-anchor[data-v-fff9d345]{anchor-name:--kline-tooltip-anchor}.tooltip-anchor.marker-tooltip-anchor.use-anchor[data-v-fff9d345]{anchor-name:--marker-tooltip-anchor}@media (width<=768px),(height<=640px){.chart-stage[data-v-fff9d345]{gap:6px}}.plot-canvas{display:block;position:absolute;top:0;left:0}.right-axis{display:block;position:absolute;left:0}.x-axis-canvas{z-index:10;display:block;position:absolute;bottom:0;left:0}.right-axis{z-index:15}
|
|
2
2
|
/*$vite$:1*/
|
|
@@ -56,6 +56,40 @@ declare const _default: import('vue').DefineComponent<__VLS_Props, {
|
|
|
56
56
|
initialZoomLevel: number;
|
|
57
57
|
isFullscreen: boolean;
|
|
58
58
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
|
|
59
|
+
toolbarRef: import('vue').CreateComponentPublicInstanceWithMixins<Readonly<{
|
|
60
|
+
isFullscreen?: boolean;
|
|
61
|
+
}> & Readonly<{
|
|
62
|
+
onSelectTool?: ((toolId: string) => any) | undefined;
|
|
63
|
+
onToggleFullscreen?: (() => any) | undefined;
|
|
64
|
+
onZoomIn?: (() => any) | undefined;
|
|
65
|
+
onZoomOut?: (() => any) | undefined;
|
|
66
|
+
onSettingsChange?: ((settings: Record<string, boolean>) => any) | undefined;
|
|
67
|
+
}>, {
|
|
68
|
+
getSettings: () => Record<string, boolean>;
|
|
69
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
70
|
+
selectTool: (toolId: string) => any;
|
|
71
|
+
toggleFullscreen: () => any;
|
|
72
|
+
zoomIn: () => any;
|
|
73
|
+
zoomOut: () => any;
|
|
74
|
+
settingsChange: (settings: Record<string, boolean>) => any;
|
|
75
|
+
}, import('vue').PublicProps, {}, false, {}, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, {}, any, import('vue').ComponentProvideOptions, {
|
|
76
|
+
P: {};
|
|
77
|
+
B: {};
|
|
78
|
+
D: {};
|
|
79
|
+
C: {};
|
|
80
|
+
M: {};
|
|
81
|
+
Defaults: {};
|
|
82
|
+
}, Readonly<{
|
|
83
|
+
isFullscreen?: boolean;
|
|
84
|
+
}> & Readonly<{
|
|
85
|
+
onSelectTool?: ((toolId: string) => any) | undefined;
|
|
86
|
+
onToggleFullscreen?: (() => any) | undefined;
|
|
87
|
+
onZoomIn?: (() => any) | undefined;
|
|
88
|
+
onZoomOut?: (() => any) | undefined;
|
|
89
|
+
onSettingsChange?: ((settings: Record<string, boolean>) => any) | undefined;
|
|
90
|
+
}>, {
|
|
91
|
+
getSettings: () => Record<string, boolean>;
|
|
92
|
+
}, {}, {}, {}, {}> | null;
|
|
59
93
|
chartMainRef: HTMLDivElement;
|
|
60
94
|
tooltipLayerRef: HTMLDivElement;
|
|
61
95
|
containerRef: HTMLDivElement;
|
|
@@ -7,15 +7,21 @@ export interface ToolDef {
|
|
|
7
7
|
type __VLS_Props = {
|
|
8
8
|
isFullscreen?: boolean;
|
|
9
9
|
};
|
|
10
|
-
|
|
10
|
+
export type { SettingItem } from '../config/chartSettings';
|
|
11
|
+
declare function getCurrentSettings(): Record<string, boolean>;
|
|
12
|
+
declare const _default: import('vue').DefineComponent<__VLS_Props, {
|
|
13
|
+
getSettings: typeof getCurrentSettings;
|
|
14
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
11
15
|
selectTool: (toolId: string) => any;
|
|
12
16
|
toggleFullscreen: () => any;
|
|
13
17
|
zoomIn: () => any;
|
|
14
18
|
zoomOut: () => any;
|
|
19
|
+
settingsChange: (settings: Record<string, boolean>) => any;
|
|
15
20
|
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
16
21
|
onSelectTool?: ((toolId: string) => any) | undefined;
|
|
17
22
|
onToggleFullscreen?: (() => any) | undefined;
|
|
18
23
|
onZoomIn?: (() => any) | undefined;
|
|
19
24
|
onZoomOut?: (() => any) | undefined;
|
|
20
|
-
|
|
25
|
+
onSettingsChange?: ((settings: Record<string, boolean>) => any) | undefined;
|
|
26
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
21
27
|
export default _default;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 图表设置配置
|
|
3
|
+
*/
|
|
4
|
+
export interface SettingItem {
|
|
5
|
+
key: string;
|
|
6
|
+
label: string;
|
|
7
|
+
type: 'boolean';
|
|
8
|
+
default: boolean;
|
|
9
|
+
}
|
|
10
|
+
/** 默认设置配置 */
|
|
11
|
+
export declare const DEFAULT_SETTINGS: SettingItem[];
|
|
12
|
+
/** localStorage 存储键名 */
|
|
13
|
+
export declare const SETTINGS_STORAGE_KEY = "kline-chart-settings";
|
package/dist/src/core/chart.d.ts
CHANGED
|
@@ -105,6 +105,8 @@ export declare class Chart {
|
|
|
105
105
|
private resizeObserver?;
|
|
106
106
|
/** 最近一次观测到的容器尺寸 */
|
|
107
107
|
private observedSize;
|
|
108
|
+
/** 用户设置配置(传递给渲染器) */
|
|
109
|
+
private settings;
|
|
108
110
|
/** pane ratio 状态(按 paneId 维护,sum=1 仅对可见 pane) */
|
|
109
111
|
private paneRatios;
|
|
110
112
|
/** 视口变化回调(供外部同步 DPR/尺寸) */
|
|
@@ -142,6 +144,8 @@ export declare class Chart {
|
|
|
142
144
|
setRendererEnabled(name: string, enabled: boolean): void;
|
|
143
145
|
/** 获取所有渲染器 */
|
|
144
146
|
getAllRenderers(): RendererPlugin[];
|
|
147
|
+
/** 更新用户设置(触发重绘) */
|
|
148
|
+
updateSettings(settings: Record<string, boolean>): void;
|
|
145
149
|
/** 绘制一帧 */
|
|
146
150
|
draw(): void;
|
|
147
151
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RendererPluginWithHost } from '../../../../plugin';
|
|
2
|
+
import { ScaleType } from '../../../utils/tickPosition';
|
|
2
3
|
export interface IndicatorScaleRendererOptions {
|
|
3
4
|
axisWidth: number;
|
|
4
5
|
paneId: string;
|
|
@@ -6,6 +7,7 @@ export interface IndicatorScaleRendererOptions {
|
|
|
6
7
|
label: string;
|
|
7
8
|
decimals?: number;
|
|
8
9
|
yPaddingPx?: number;
|
|
10
|
+
scaleType?: ScaleType;
|
|
9
11
|
getCrosshair?: () => {
|
|
10
12
|
y: number;
|
|
11
13
|
price: number;
|
|
@@ -26,6 +28,7 @@ export interface DrawScaleTicksOptions {
|
|
|
26
28
|
isMain: boolean;
|
|
27
29
|
decimals?: number;
|
|
28
30
|
hideEdgeTicks?: boolean;
|
|
31
|
+
scaleType?: ScaleType;
|
|
29
32
|
formatLabel?: (value: number) => string;
|
|
30
33
|
}
|
|
31
34
|
export declare function drawScaleTicks(options: DrawScaleTicksOptions): void;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { PriceRange } from './price';
|
|
2
|
+
/**
|
|
3
|
+
* LogFormula 接口
|
|
4
|
+
* 用于对数变换的动态偏移,保证极小值下的精度
|
|
5
|
+
*
|
|
6
|
+
* - logicalOffset: 逻辑偏移,使输出值落在合理范围
|
|
7
|
+
* - coordOffset: 坐标偏移,避免 log10(0) 并提升精度
|
|
8
|
+
*/
|
|
9
|
+
export interface LogFormula {
|
|
10
|
+
logicalOffset: number;
|
|
11
|
+
coordOffset: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 真实价格 → log 逻辑空间
|
|
15
|
+
* 公式: sign(price) * (log10(|price| + coordOffset) + logicalOffset)
|
|
16
|
+
*
|
|
17
|
+
* @param price 真实价格(可为负数)
|
|
18
|
+
* @param f LogFormula
|
|
19
|
+
* @returns log 逻辑空间值
|
|
20
|
+
*/
|
|
21
|
+
export declare function toLog(price: number, f: LogFormula): number;
|
|
22
|
+
/**
|
|
23
|
+
* log 逻辑空间 → 真实价格
|
|
24
|
+
* 公式: sign(logical) * (10^(|logical| - logicalOffset) - coordOffset)
|
|
25
|
+
*
|
|
26
|
+
* @param logical log 逻辑空间值
|
|
27
|
+
* @param f LogFormula
|
|
28
|
+
* @returns 真实价格
|
|
29
|
+
*/
|
|
30
|
+
export declare function fromLog(logical: number, f: LogFormula): number;
|
|
31
|
+
/**
|
|
32
|
+
* 根据价格范围动态计算 LogFormula
|
|
33
|
+
*
|
|
34
|
+
* 对于常规价格范围 (diff >= 1),使用默认值。
|
|
35
|
+
* 对于极小价格范围 (diff < 1),自动增大 logicalOffset 以维持精度。
|
|
36
|
+
*
|
|
37
|
+
* @param range 价格范围,可为 null
|
|
38
|
+
* @returns 最优的 LogFormula
|
|
39
|
+
*/
|
|
40
|
+
export declare function logFormulaForPriceRange(range: PriceRange | null): LogFormula;
|
|
41
|
+
/**
|
|
42
|
+
* 范围转 log 空间
|
|
43
|
+
* 将价格的 min/max 都转换到 log 空间
|
|
44
|
+
*
|
|
45
|
+
* @param range 真实价格范围
|
|
46
|
+
* @param f LogFormula
|
|
47
|
+
* @returns log 空间的价格范围
|
|
48
|
+
*/
|
|
49
|
+
export declare function convertPriceRangeToLog(range: PriceRange, f: LogFormula): PriceRange;
|
|
50
|
+
/**
|
|
51
|
+
* 范围从 log 空间转回
|
|
52
|
+
* 将 log 空间的 min/max 转换回真实价格
|
|
53
|
+
*
|
|
54
|
+
* @param range log 空间的价格范围
|
|
55
|
+
* @param f LogFormula
|
|
56
|
+
* @returns 真实价格范围
|
|
57
|
+
*/
|
|
58
|
+
export declare function convertPriceRangeFromLog(range: PriceRange, f: LogFormula): PriceRange;
|
|
59
|
+
/**
|
|
60
|
+
* 判断两个 LogFormula 是否相同
|
|
61
|
+
*
|
|
62
|
+
* @param a LogFormula A
|
|
63
|
+
* @param b LogFormula B
|
|
64
|
+
* @returns 是否相同
|
|
65
|
+
*/
|
|
66
|
+
export declare function logFormulasAreSame(a: LogFormula, b: LogFormula): boolean;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PriceRange } from './price';
|
|
2
|
+
import { ScaleType } from '../utils/tickPosition';
|
|
2
3
|
/**
|
|
3
4
|
* Pane 级别的价格坐标系(价格 -> pane 内 Y)
|
|
4
5
|
* - y=0 在 pane 顶部,y=height 在 pane 底部
|
|
@@ -8,10 +9,15 @@ export declare class PriceScale {
|
|
|
8
9
|
private height;
|
|
9
10
|
private paddingTop;
|
|
10
11
|
private paddingBottom;
|
|
11
|
-
/** 价格偏移量(用于上下拖动平移价格轴)
|
|
12
|
+
/** 价格偏移量(用于上下拖动平移价格轴)
|
|
13
|
+
* 在对数模式下,此偏移量为 log 空间偏移 */
|
|
12
14
|
private priceOffset;
|
|
13
15
|
/** 垂直缩放系数(1=默认,>1 放大,<1 缩小) */
|
|
14
16
|
private verticalScale;
|
|
17
|
+
/** 刻度类型:线性或对数 */
|
|
18
|
+
private scaleType;
|
|
19
|
+
/** 对数变换公式(动态计算,适配极小价格) */
|
|
20
|
+
private logFormula;
|
|
15
21
|
setRange(r: PriceRange): void;
|
|
16
22
|
setHeight(h: number): void;
|
|
17
23
|
setPadding(top: number, bottom: number): void;
|
|
@@ -20,7 +26,9 @@ export declare class PriceScale {
|
|
|
20
26
|
getPaddingBottom(): number;
|
|
21
27
|
/**
|
|
22
28
|
* 设置价格偏移量
|
|
23
|
-
* @param offset
|
|
29
|
+
* @param offset 价格偏移
|
|
30
|
+
* - 线性模式:真实价格的线性偏移
|
|
31
|
+
* - 对数模式:log 空间的偏移量
|
|
24
32
|
*/
|
|
25
33
|
setPriceOffset(offset: number): void;
|
|
26
34
|
/**
|
|
@@ -41,13 +49,39 @@ export declare class PriceScale {
|
|
|
41
49
|
*/
|
|
42
50
|
scaleByDelta(deltaY: number): void;
|
|
43
51
|
getVerticalScale(): number;
|
|
52
|
+
/**
|
|
53
|
+
* 设置刻度类型
|
|
54
|
+
* 切换时会自动转换 priceOffset 以保持视口位置
|
|
55
|
+
*/
|
|
56
|
+
setScaleType(type: ScaleType): void;
|
|
57
|
+
/**
|
|
58
|
+
* 获取当前刻度类型
|
|
59
|
+
*/
|
|
60
|
+
getScaleType(): ScaleType;
|
|
61
|
+
/**
|
|
62
|
+
* 获取显示范围(考虑 priceOffset 和 verticalScale)
|
|
63
|
+
*
|
|
64
|
+
* 对数模式下:
|
|
65
|
+
* - 内部计算在 log 空间进行
|
|
66
|
+
* - 返回的价格为真实价格
|
|
67
|
+
*/
|
|
44
68
|
getDisplayRange(baseRange?: PriceRange): PriceRange;
|
|
69
|
+
/**
|
|
70
|
+
* 价格 → Y 坐标
|
|
71
|
+
* 统一使用 getDisplayRange 的结果进行映射
|
|
72
|
+
*/
|
|
45
73
|
priceToY(price: number): number;
|
|
74
|
+
/**
|
|
75
|
+
* Y 坐标 → 价格
|
|
76
|
+
* 统一使用 getDisplayRange 的结果进行映射
|
|
77
|
+
*/
|
|
46
78
|
yToPrice(y: number): number;
|
|
47
79
|
/**
|
|
48
80
|
* 根据像素偏移计算价格偏移
|
|
49
81
|
* @param deltaY Y轴像素偏移(正数向下拖动)
|
|
50
82
|
* @returns 对应的价格偏移量
|
|
83
|
+
* - 线性模式:真实价格的偏移
|
|
84
|
+
* - 对数模式:log 空间的偏移
|
|
51
85
|
*/
|
|
52
86
|
deltaYToPriceOffset(deltaY: number): number;
|
|
53
87
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 图表字体配置
|
|
3
|
+
* 字体栈:Trebuchet MS (Windows系统字体) -> Roboto -> Ubuntu -> 通用无衬线字体
|
|
4
|
+
* 通过 Google Fonts CDN 加载 Roboto 和 Ubuntu
|
|
5
|
+
*/
|
|
6
|
+
/** 数字和文本的标准字体栈 */
|
|
7
|
+
export declare const FONT_FAMILY = "\"Trebuchet MS\", Roboto, Ubuntu, sans-serif";
|
|
8
|
+
/** 获取指定字号的字体字符串,用于 Canvas ctx.font */
|
|
9
|
+
export declare function getFont(size: number, options?: {
|
|
10
|
+
bold?: boolean;
|
|
11
|
+
}): string;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface TickPosition {
|
|
2
|
+
index: number;
|
|
3
|
+
t: number;
|
|
4
|
+
y: number;
|
|
5
|
+
}
|
|
6
|
+
export type ScaleType = 'linear' | 'log';
|
|
7
|
+
export interface CalculateTickPositionsOptions {
|
|
8
|
+
height: number;
|
|
9
|
+
paddingTop: number;
|
|
10
|
+
paddingBottom: number;
|
|
11
|
+
isMain?: boolean;
|
|
12
|
+
hideEdgeTicks?: boolean;
|
|
13
|
+
scaleType?: ScaleType;
|
|
14
|
+
}
|
|
15
|
+
export declare function calculateTickPositions(options: CalculateTickPositionsOptions): TickPosition[];
|
|
16
|
+
export interface TickPositionWithValue extends TickPosition {
|
|
17
|
+
value: number;
|
|
18
|
+
}
|
|
19
|
+
export interface CalculateValueTickPositionsOptions extends CalculateTickPositionsOptions {
|
|
20
|
+
valueMin: number;
|
|
21
|
+
valueMax: number;
|
|
22
|
+
logBase?: number;
|
|
23
|
+
}
|
|
24
|
+
export declare function calculateValueTickPositions(options: CalculateValueTickPositionsOptions): TickPositionWithValue[];
|
|
@@ -116,6 +116,7 @@ export interface PaneInfo {
|
|
|
116
116
|
maxPrice: number;
|
|
117
117
|
minPrice: number;
|
|
118
118
|
};
|
|
119
|
+
getScaleType(): 'linear' | 'log';
|
|
119
120
|
};
|
|
120
121
|
priceRange: {
|
|
121
122
|
maxPrice: number;
|
|
@@ -139,6 +140,59 @@ export declare function wrapPaneInfo(pane: {
|
|
|
139
140
|
yAxis: PaneInfo['yAxis'];
|
|
140
141
|
priceRange: PaneInfo['priceRange'];
|
|
141
142
|
}): Readonly<PaneInfo>;
|
|
143
|
+
/** Y轴标签(价格标签) */
|
|
144
|
+
export interface YAxisLabel {
|
|
145
|
+
/** 关联的数据索引 */
|
|
146
|
+
dataIndex: number;
|
|
147
|
+
/** 价格值 */
|
|
148
|
+
price: number;
|
|
149
|
+
/** 标签在轴上的Y坐标(世界坐标,相对pane) */
|
|
150
|
+
y: number;
|
|
151
|
+
/** 标签类型,用于区分不同渲染外观 */
|
|
152
|
+
type?: 'lastPrice' | 'extrema' | 'anchor' | string;
|
|
153
|
+
/** 标签样式覆盖 */
|
|
154
|
+
style?: {
|
|
155
|
+
bgColor?: string;
|
|
156
|
+
borderColor?: string;
|
|
157
|
+
textColor?: string;
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
/** X轴标签(时间标签) */
|
|
161
|
+
export interface XAxisLabel {
|
|
162
|
+
/** 关联的数据索引 */
|
|
163
|
+
dataIndex: number;
|
|
164
|
+
/** 时间戳(毫秒) */
|
|
165
|
+
timestamp: number;
|
|
166
|
+
/** 标签在轴上的X坐标(世界坐标,未减去scrollLeft) */
|
|
167
|
+
x: number;
|
|
168
|
+
/** 标签样式覆盖 */
|
|
169
|
+
style?: {
|
|
170
|
+
bgColor?: string;
|
|
171
|
+
textColor?: string;
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/** Y轴范围带(半透明填充区域) */
|
|
175
|
+
export interface YAxisRange {
|
|
176
|
+
/** 范围上界Y坐标(相对pane,canvas方向:小值=上方) */
|
|
177
|
+
topY: number;
|
|
178
|
+
/** 范围下界Y坐标(相对pane,canvas方向:大值=下方) */
|
|
179
|
+
bottomY: number;
|
|
180
|
+
/** 填充颜色(hex 或 rgba) */
|
|
181
|
+
color: string;
|
|
182
|
+
/** 填充不透明度 */
|
|
183
|
+
opacity: number;
|
|
184
|
+
}
|
|
185
|
+
/** X轴范围带(半透明填充区域) */
|
|
186
|
+
export interface XAxisRange {
|
|
187
|
+
/** 范围左界X坐标(世界坐标,未减去scrollLeft) */
|
|
188
|
+
leftX: number;
|
|
189
|
+
/** 范围右界X坐标(世界坐标,未减去scrollLeft) */
|
|
190
|
+
rightX: number;
|
|
191
|
+
/** 填充颜色(hex 或 rgba) */
|
|
192
|
+
color: string;
|
|
193
|
+
/** 填充不透明度 */
|
|
194
|
+
opacity: number;
|
|
195
|
+
}
|
|
142
196
|
/** 渲染上下文 */
|
|
143
197
|
/** MarkerManager 接口(用于 RenderContext) */
|
|
144
198
|
export interface MarkerManagerLike {
|
|
@@ -181,6 +235,16 @@ export interface RenderContext {
|
|
|
181
235
|
plotWidth: number;
|
|
182
236
|
plotHeight: number;
|
|
183
237
|
};
|
|
238
|
+
/** 用户设置配置(渲染器只读) */
|
|
239
|
+
settings?: Record<string, boolean>;
|
|
240
|
+
/** 需要在Y轴上绘制的标签列表(由各类标记渲染器填充) */
|
|
241
|
+
yAxisLabels?: YAxisLabel[];
|
|
242
|
+
/** 需要在X轴上绘制的标签列表(由各类标记渲染器填充) */
|
|
243
|
+
xAxisLabels?: XAxisLabel[];
|
|
244
|
+
/** 需要在Y轴上绘制的范围带列表(由绘图渲染器填充,先于标签绘制) */
|
|
245
|
+
yAxisRanges?: YAxisRange[];
|
|
246
|
+
/** 需要在X轴上绘制的范围带列表(由绘图渲染器填充,先于标签绘制) */
|
|
247
|
+
xAxisRanges?: XAxisRange[];
|
|
184
248
|
}
|
|
185
249
|
export type DrawingAnchor = {
|
|
186
250
|
id: string;
|
|
@@ -252,6 +316,7 @@ export type DrawingGeometry = {
|
|
|
252
316
|
bottom: number;
|
|
253
317
|
};
|
|
254
318
|
meta?: Record<string, unknown>;
|
|
319
|
+
computedAnchors?: DrawingAnchor[];
|
|
255
320
|
};
|
|
256
321
|
export type DrawingComputeContext = {
|
|
257
322
|
pane: PaneInfo;
|
|
@@ -288,6 +353,7 @@ export interface DrawingDefinition<TParams = Record<string, unknown>> {
|
|
|
288
353
|
export declare const GLOBAL_PANE_ID: unique symbol;
|
|
289
354
|
/** 优先级推荐范围 */
|
|
290
355
|
export declare const RENDERER_PRIORITY: {
|
|
356
|
+
readonly LAST_PRICE_LABEL: -25;
|
|
291
357
|
readonly SYSTEM_YAXIS: -20;
|
|
292
358
|
readonly SYSTEM_XAXIS: -20;
|
|
293
359
|
readonly BACKGROUND: 0;
|
|
@@ -127,3 +127,40 @@ export declare function drawCrosshairPriceLabel(ctx: CanvasRenderingContext2D, o
|
|
|
127
127
|
export declare function drawLastPriceDashedLine(ctx: CanvasRenderingContext2D, opts: LastPriceLineOptions): void;
|
|
128
128
|
/** 底部时间轴(X方向随 scrollLeft 变化) */
|
|
129
129
|
export declare function drawTimeAxis(ctx: CanvasRenderingContext2D, opts: TimeAxisOptions): void;
|
|
130
|
+
/** ============ 轴标签绘制函数 ============ */
|
|
131
|
+
export interface AxisPriceLabelOptions {
|
|
132
|
+
x: number;
|
|
133
|
+
y: number;
|
|
134
|
+
width: number;
|
|
135
|
+
height: number;
|
|
136
|
+
priceY: number;
|
|
137
|
+
price: number;
|
|
138
|
+
dpr: number;
|
|
139
|
+
bgColor?: string;
|
|
140
|
+
borderColor?: string;
|
|
141
|
+
textColor?: string;
|
|
142
|
+
fontSize?: number;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* 在右侧价格轴上绘制价格标签
|
|
146
|
+
* 与 drawCrosshairPriceLabel 类似,但简化了参数(价格直接传入,无需计算)
|
|
147
|
+
*/
|
|
148
|
+
export declare function drawAxisPriceLabel(ctx: CanvasRenderingContext2D, opts: AxisPriceLabelOptions): void;
|
|
149
|
+
export interface AxisTimeLabelOptions {
|
|
150
|
+
x: number;
|
|
151
|
+
y: number;
|
|
152
|
+
width: number;
|
|
153
|
+
height: number;
|
|
154
|
+
labelX: number;
|
|
155
|
+
timestamp: number;
|
|
156
|
+
dpr: number;
|
|
157
|
+
bgColor?: string;
|
|
158
|
+
textColor?: string;
|
|
159
|
+
fontSize?: number;
|
|
160
|
+
paddingX?: number;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* 在底部时间轴上绘制时间标签
|
|
164
|
+
* 与 drawCrosshairTimeLabel 类似,但 labelX 是屏幕坐标(已处理 scrollLeft)
|
|
165
|
+
*/
|
|
166
|
+
export declare function drawAxisTimeLabel(ctx: CanvasRenderingContext2D, opts: AxisTimeLabelOptions): void;
|
package/package.json
CHANGED
|
@@ -1,7 +1,43 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@363045841yyt/klinechart",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.6",
|
|
4
|
+
"description": "A lightweight financial K-line charting library with first-class AI Agent support, crisp ResizeObserver-driven rendering, and plugin-based architecture. Focused on quantitative trading scenarios with TradingView-level interaction experience.",
|
|
5
|
+
"author": "363045841 <slslswbsy@qq.com>",
|
|
4
6
|
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/363045841/KLineChartQuant.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": "https://github.com/363045841/KLineChartQuant/issues",
|
|
12
|
+
"homepage": "https://363045841.github.io/KLineChartQuant/",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"kline-chart",
|
|
15
|
+
"candlestick-chart",
|
|
16
|
+
"financial-chart",
|
|
17
|
+
"tradingview",
|
|
18
|
+
"canvas",
|
|
19
|
+
"rendering-engine",
|
|
20
|
+
"resizeobserver",
|
|
21
|
+
"device-pixel-content-box",
|
|
22
|
+
"drawing-tools",
|
|
23
|
+
"chart-drawing",
|
|
24
|
+
"trend-line",
|
|
25
|
+
"fibonacci",
|
|
26
|
+
"high-performance",
|
|
27
|
+
"pixel-perfect",
|
|
28
|
+
"crisp-rendering",
|
|
29
|
+
"sharp-rendering",
|
|
30
|
+
"device-pixel-ratio",
|
|
31
|
+
"responsive",
|
|
32
|
+
"modern-ui",
|
|
33
|
+
"agent",
|
|
34
|
+
"ai-chart",
|
|
35
|
+
"visualization",
|
|
36
|
+
"quantitative-trading",
|
|
37
|
+
"technical-analysis",
|
|
38
|
+
"plugin-architecture",
|
|
39
|
+
"typescript"
|
|
40
|
+
],
|
|
5
41
|
"type": "module",
|
|
6
42
|
"engines": {
|
|
7
43
|
"node": "^20.19.0 || >=22.12.0"
|