UNPKG

@progress/kendo-charts

Version:

Kendo UI platform-independent Charts library

278 lines (228 loc) 7.46 kB
import { drawing as draw, Color } from '@progress/kendo-drawing'; import { ChartElement, Point } from '../../core'; import PointEventsMixin from '../mixins/point-events-mixin'; import NoteMixin from '../mixins/note-mixin'; import Bar from '../bar-chart/bar'; import AccessibilityAttributesMixin from '../mixins/accessibility-attributes-mixin'; import { CHART_POINT_ROLE_DESCRIPTION, CHART_POINT_CLASSNAME, CHART_POINT_ROLE, TOOLTIP_OFFSET } from '../constants'; import hasGradientOverlay from '../utils/has-gradient-overlay'; import { WHITE, LEFT, TOP } from '../../common/constants'; import { alignPathToPixel, deepExtend, defined, setDefaultOptions, valueOrDefault } from '../../common'; import { createPatternFill } from '../../core/pattern'; class Candlestick extends ChartElement { constructor(value, options) { super(options); this.value = value; } getLabelText(options) { return this.formatValue(options.format); } reflow(box) { const { options, value, owner: chart } = this; const valueAxis = chart.seriesValueAxis(options); const ocSlot = valueAxis.getSlot(value.open, value.close); const lhSlot = valueAxis.getSlot(value.low, value.high); ocSlot.x1 = lhSlot.x1 = box.x1; ocSlot.x2 = lhSlot.x2 = box.x2; this.realBody = ocSlot; const mid = lhSlot.center().x; const points = []; points.push([ [ mid, lhSlot.y1 ], [ mid, ocSlot.y1 ] ]); points.push([ [ mid, ocSlot.y2 ], [ mid, lhSlot.y2 ] ]); this.lines = points; this.box = lhSlot.clone().wrap(ocSlot); if (!this._rendered) { this._rendered = true; this.createNote(); } this.reflowNote(); } reflowNote() { if (this.note) { this.note.reflow(this.box); } } createVisual() { super.createVisual(); this.addAccessibilityAttributesToVisual(); this._mainVisual = this.mainVisual(this.options); this.visual.append( this._mainVisual ); this.createOverlay(); } mainVisual(options) { const group = new draw.Group(); this.createBody(group, options); this.createLines(group, options); return group; } createBody(container, options) { const body = draw.Path.fromRect(this.realBody.toRect(), { fill: createPatternFill(options.pattern, { color: this.color, opacity: options.opacity }), stroke: null }); if (options.border.width > 0) { body.options.set("stroke", { color: this.getBorderColor(options), width: options.border.width, dashType: options.border.dashType, opacity: valueOrDefault(options.border.opacity, options.opacity) }); } alignPathToPixel(body); container.append(body); if (hasGradientOverlay(options)) { container.append(this.createGradientOverlay(body, { baseColor: this.color }, deepExtend({ end: !options.vertical ? [ 0, 1 ] : undefined }, options.overlay))); } } createLines(container, options) { this.drawLines(container, options, this.lines, options.line); } drawLines(container, options, lines, lineOptions) { if (!lines) { return; } const lineStyle = { stroke: { color: lineOptions.color || this.color, opacity: valueOrDefault(lineOptions.opacity, options.opacity), width: lineOptions.width, dashType: lineOptions.dashType, lineCap: "butt" } }; for (let i = 0; i < lines.length; i++) { const line = draw.Path.fromPoints(lines[i], lineStyle); alignPathToPixel(line); container.append(line); } } getBorderColor(options) { const border = options.border; let borderColor = border.color; if (!defined(borderColor)) { borderColor = new Color(this.color).brightness(this.options.border._brightness).toHex(); } return borderColor; } createOverlay() { const overlay = draw.Path.fromRect(this.box.toRect(), { fill: { color: WHITE, opacity: 0 }, stroke: null }); this.visual.append(overlay); } createHighlight() { const highlight = this.options.highlight; const normalColor = this.color; this.color = highlight.color || this.color; const overlay = this.mainVisual( deepExtend({}, this.options, { line: { color: this.getBorderColor(highlight) } }, highlight) ); this.color = normalColor; return overlay; } highlightVisual() { return this._mainVisual; } highlightVisualArgs() { return { options: this.options, rect: this.box.toRect(), visual: this._mainVisual }; } tooltipAnchor() { const box = this.box; const clipBox = this.owner.pane.clipBox() || box; return { point: new Point(box.x2 + TOOLTIP_OFFSET, Math.max(box.y1, clipBox.y1) + TOOLTIP_OFFSET), align: { horizontal: LEFT, vertical: TOP } }; } formatValue(format) { return this.owner.formatPointValue(this, format); } overlapsBox(box) { return this.box.overlaps(box); } pointData() { return { dataItem: this.dataItem, value: this.value, meanPoints: this.meanPoints, medianPoints: this.medianPoints, whiskerPoints: this.whiskerPoints, stackValue: this.stackValue, series: this.series }; } getIndex() { return this.categoryIx; } } Candlestick.prototype.createFocusHighlight = Bar.prototype.createFocusHighlight; setDefaultOptions(Candlestick, { vertical: true, border: { _brightness: 0.8 }, line: { width: 2 }, overlay: { gradient: "glass" }, tooltip: { format: "<table>" + "<tr><th colspan='2'>{4:d}</th></tr>" + "<tr><td>Open:</td><td>{0:C}</td></tr>" + "<tr><td>High:</td><td>{1:C}</td></tr>" + "<tr><td>Low:</td><td>{2:C}</td></tr>" + "<tr><td>Close:</td><td>{3:C}</td></tr>" + "</table>" }, labels: { format: "" }, highlight: { opacity: 1, border: { width: 1, opacity: 1 }, line: { width: 1, opacity: 1 } }, notes: { visible: true, label: {} }, accessibility: { role: CHART_POINT_ROLE, className: CHART_POINT_CLASSNAME, ariaRoleDescription: CHART_POINT_ROLE_DESCRIPTION } }); deepExtend(Candlestick.prototype, PointEventsMixin); deepExtend(Candlestick.prototype, NoteMixin); deepExtend(Candlestick.prototype, AccessibilityAttributesMixin); export default Candlestick;