UNPKG

@progress/kendo-charts

Version:

Kendo UI platform-independent Charts library

339 lines (275 loc) 8.4 kB
import { geometry as geom, drawing as draw } from '@progress/kendo-drawing'; import { defined, addClass, setDefaultOptions, deepExtend, getSpacing, isObject, defaultErrorHandler } from '../common'; import { Box, TextBox } from '../core'; import { Encodings } from './encodings/main'; import { surfaceSize } from './surface-size'; const DEFAULT_BARCODE_WIDTH = 300; const DEFAULT_BARCODE_HEIGHT = 100; class Barcode { constructor(element, options, errorHandler = defaultErrorHandler) { this.options = deepExtend({}, this.options, options); this.element = element; this.onError = errorHandler; this._initElement(); this._initSurface(); this._setOptions(options); if (options && defined(options.value)) { this.redraw(); } } destroy() { this._destroySurface(); } _initElement() { addClass(this.element, "k-barcode"); } _initSurface() { const { options, surface } = this; if (!surface || surface.options.type !== options.renderAs) { this._destroySurface(); this._initSurfaceElement(); this.surface = this._createSurface(); } } _createSurface() { return draw.Surface.create(this.surfaceElement, { type: this.options.renderAs }); } _destroySurface() { if (this.surface) { this.surface.destroy(); this.surface = null; this._destroySurfaceElement(); } } _initSurfaceElement() { if (!this.surfaceElement) { this.surfaceElement = document.createElement('div'); this.surfaceElement.style.position = 'relative'; this.element.appendChild(this.surfaceElement); } } _destroySurfaceElement() { if (this.surfaceElement && this.surfaceElement.parentNode) { this.surfaceElement.parentNode.removeChild(this.surfaceElement); this.surfaceElement = null; } } setOptions(options) { this._setOptions(options); this._initSurface(); this.redraw(); } redraw() { let size = this._getSize(); this.surface.clear(); this.surface.setSize({ width: size.width, height: size.height }); this.createVisual(); this.surface.draw(this.visual); } getSize() { return { width: this.element.offsetWidth, height: this.element.offsetHeight }; } _resize() { this.redraw(); } createVisual() { this.visual = this._render(); } _render() { const options = this.options; const value = options.value; const textOptions = options.text; const textMargin = getSpacing(textOptions.margin); const size = this._getSize(); const border = options.border || {}; const encoding = this.encoding; const contentBox = new Box(0, 0, size.width, size.height).unpad(border.width).unpad(options.padding); let barHeight = contentBox.height(); let encodedValue; let textToDisplay; let textHeight; const visual = new draw.Group(); this.contentBox = contentBox; visual.append(this._getBackground(size)); if (textOptions.visible) { textHeight = draw.util.measureText(value, { font: textOptions.font }).height; barHeight -= textHeight + textMargin.top + textMargin.bottom; } try { encodedValue = encoding.encode(value, contentBox.width(), barHeight); } catch (error) { this.onError(error); return visual; } if (textOptions.visible) { textToDisplay = value; if (options.checksum && defined(encoding.checksum)) { textToDisplay += " " + encoding.checksum; } visual.append(this._getText(textToDisplay)); } this.barHeight = barHeight; this._bandsGroup = this._getBands(encodedValue.pattern, encodedValue.baseUnit); visual.append(this._bandsGroup); return visual; } exportVisual() { return this._render(); } _getSize() { const element = this.element; const elementSize = surfaceSize(element, this.options.renderAs); const size = new geom.Size(DEFAULT_BARCODE_WIDTH, DEFAULT_BARCODE_HEIGHT); if (elementSize.width > 0) { size.width = elementSize.width; } if (elementSize.height > 0) { size.height = elementSize.height; } if (this.options.width) { size.width = this.options.width; } if (this.options.height) { size.height = this.options.height; } return size; } value(value) { if (!defined(value)) { return this.options.value; } this.options.value = String(value); this.redraw(); } _getBands(pattern, baseUnit) { const contentBox = this.contentBox; let offsetX = contentBox.x1; let stepX; let patternItem; const group = new draw.Group(); for (let i = 0; i < pattern.length; i++) { patternItem = isObject(pattern[i]) ? pattern[i] : { width: pattern[i], y1: 0, y2: this.barHeight }; stepX = patternItem.width * baseUnit; if (i % 2) { const rect = geom.Rect.fromPoints( new geom.Point(offsetX, patternItem.y1 + contentBox.y1), new geom.Point(offsetX + stepX, patternItem.y2 + contentBox.y1) ); const path = draw.Path.fromRect(rect, { fill: { color: this.options.color }, stroke: null }); group.append(path); } offsetX += stepX; } return group; } _getBackground(size) { const options = this.options; const border = options.border || {}; const box = new Box(0, 0, size.width, size.height).unpad(border.width / 2); const path = draw.Path.fromRect(box.toRect(), { fill: { color: options.background }, stroke: { color: border.width ? border.color : "", width: border.width, dashType: border.dashType } }); return path; } _getText(value) { const textOptions = this.options.text; const text = this._textbox = new TextBox(value, { font: textOptions.font, color: textOptions.color, align: "center", vAlign: "bottom", margin: textOptions.margin }); text.reflow(this.contentBox); text.renderVisual(); return text.visual; } _setOptions(options) { this.type = (options.type || this.options.type).toLowerCase(); if (this.type === "upca") { this.type = "ean13"; options.value = '0' + options.value; } if (this.type === "upce") { this.type = "ean8"; options.value = '0' + options.value; } if (!Encodings[this.type]) { throw new Error(`Encoding '${this.type}' is not supported.`); } this.encoding = new Encodings[this.type](); this.options = deepExtend({}, this.options, options); } } setDefaultOptions(Barcode, { name: "Barcode", renderAs: "svg", value: "", type: "code39", checksum: false, width: 0, height: 0, color: "black", background: "white", text: { visible: true, font: "16px Consolas, Monaco, Sans Mono, monospace, sans-serif", color: "black", margin: { top: 0, bottom: 0, left: 0, right: 0 } }, border: { width: 0, dashType: "solid", color: "black" }, padding: { top: 0, bottom: 0, left: 0, right: 0 } }); export default Barcode;