UNPKG

@progress/kendo-charts

Version:

Kendo UI platform-independent Charts library

416 lines (333 loc) 12.3 kB
import { geometry as geom, drawing as draw } from '@progress/kendo-drawing'; import { Class, addClass, setDefaultOptions, deepExtend, defaultErrorHandler } from '../common'; import { Box } from '../core'; import { encodeData } from './encodings/encoding'; import { extend } from './utils'; import { surfaceSize } from '../barcode/surface-size'; var round = Math.round; var crossPattern = [[0, 1], [1, 1], [1, 2], [2, 2], [2, 1], [3, 1], [3, 0], [2, 0], [2, -1], [1, -1], [1, 0]]; var squarePattern = [[0, 1], [1, 1], [1, 0]]; var QRCodeDefaults = { DEFAULT_SIZE: 200, QUIET_ZONE_LENGTH: 4, DEFAULT_ERROR_CORRECTION_LEVEL: "L", DEFAULT_BACKGROUND: "#fff", DEFAULT_DARK_MODULE_COLOR: "#000", MIN_BASE_UNIT_SIZE: 1, DEFAULT_LOGO_SIZE: 7 }; var QRCode = (function (Class) { function QRCode(element, options, errorHandler) { if ( errorHandler === void 0 ) errorHandler = defaultErrorHandler; Class.call(this); this.options = deepExtend({}, this.options, options); this.element = element; this.wrapper = this.element; this.onError = errorHandler; this._initElement(); this._initSurface(); this.setOptions(options); } if ( Class ) QRCode.__proto__ = Class; QRCode.prototype = Object.create( Class && Class.prototype ); QRCode.prototype.constructor = QRCode; QRCode.prototype.destroy = function destroy () { this._destroySurface(); }; QRCode.prototype._initElement = function _initElement () { addClass(this.element, "k-qrcode"); }; QRCode.prototype._initSurface = function _initSurface () { var ref = this; var options = ref.options; var surface = ref.surface; if (!surface || surface.options.type !== options.renderAs) { this._destroySurface(); this._initSurfaceElement(); this.surface = this._createSurface(); } }; QRCode.prototype._createSurface = function _createSurface () { return draw.Surface.create(this.surfaceElement, { type: this.options.renderAs }); }; QRCode.prototype._destroySurface = function _destroySurface () { if (this.surface) { this.surface.destroy(); this.surface = null; this._destroySurfaceElement(); } }; QRCode.prototype._initSurfaceElement = function _initSurfaceElement () { if (!this.surfaceElement) { this.surfaceElement = document.createElement('div'); this.surfaceElement.style.position = "relative"; this.element.appendChild(this.surfaceElement); } }; QRCode.prototype._destroySurfaceElement = function _destroySurfaceElement () { if (this.surfaceElement && this.surfaceElement.parentNode) { this.surfaceElement.parentNode.removeChild(this.surfaceElement); this.surfaceElement = null; } }; QRCode.prototype.redraw = function redraw () { var size = this._getSize(); this.surface.clear(); this.surface.setSize({ width: size, height: size }); this.createVisual(); this.surface.draw(this.visual); }; QRCode.prototype.getSize = function getSize () { var element = this.element; var elementWidth = element.clientWidth; var elementHeight = element.clientHeight; var size = { width: 0, height: 0 }; if (elementWidth > 0) { size.width = elementWidth; } if (elementHeight) { size.height = elementHeight; } return size; }; QRCode.prototype._resize = function _resize () { this.redraw(); }; QRCode.prototype.createVisual = function createVisual () { this.visual = this._render(); }; QRCode.prototype.exportVisual = function exportVisual () { return this._render(); }; QRCode.prototype._render = function _render () { var value = this._value, baseUnit, border = this.options.border || {}, padding = this.options.padding || 0, borderWidth = border.width || 0, quietZoneSize, matrix, size, dataSize, contentSize; border.width = borderWidth; var visual = new draw.Group(); try { if (value) { matrix = encodeData(value, this.options.errorCorrection, this.options.encoding); size = this._getSize(); contentSize = size - 2 * (borderWidth + padding); baseUnit = this._calculateBaseUnit(contentSize, matrix.length); dataSize = matrix.length * baseUnit; quietZoneSize = borderWidth + padding + (contentSize - dataSize) / 2; visual.append(this._renderBackground(size, border)); visual.append(this._renderMatrix(matrix, baseUnit, quietZoneSize)); if (this._hasCustomLogo()) { visual.append(this._renderLogo(size, baseUnit)); } else if (this._isSwiss()) { visual.append(this._renderSwissCode(size, baseUnit)); } } } catch (error) { this.onError(error); } return visual; }; QRCode.prototype._renderLogo = function _renderLogo (qrSize, baseUnit) { var image; var imageRect; var center = round(qrSize / 2); var logoSize = this._getLogoSize(baseUnit * QRCodeDefaults.DEFAULT_LOGO_SIZE); var logoUrl = this.options.overlay.imageUrl; var position = { x: center - logoSize.width / 2, y: center - logoSize.height / 2 }; imageRect = new geom.Rect( new geom.Point(position.x, position.y), new geom.Size(logoSize.width, logoSize.height) ); image = new draw.Image(logoUrl, imageRect); return image; }; QRCode.prototype._renderSwissCode = function _renderSwissCode (qrSize, baseUnit) { var logoSize = this._getLogoSize(baseUnit * QRCodeDefaults.DEFAULT_LOGO_SIZE); logoSize = Math.max(logoSize.width, logoSize.height); var crossSize = logoSize / 4; var crossOffset = crossSize / 2; var center = qrSize / 2; var start = {}; var visual = new draw.Group(); start.x = start.y = Math.ceil(center - baseUnit - logoSize / 2); visual.append(this._renderShape(start, Math.ceil(logoSize + baseUnit * 2), squarePattern, "#fff")); start.x = start.y = center - logoSize / 2; visual.append(this._renderShape(start, logoSize, squarePattern, this.options.color)); start.x = center + crossOffset - logoSize / 2; start.y = center + crossOffset + crossSize - logoSize / 2; visual.append(this._renderShape(start, crossSize, crossPattern, "#fff")); return visual; }; QRCode.prototype._renderShape = function _renderShape (start, step, pattern, color) { var path = new draw.MultiPath({ fill: { color: color }, stroke: null }); path.moveTo(start.x, start.y); for (var i = 0; i < pattern.length; i++) { path.lineTo(start.x + step * pattern[i][0], start.y + step * pattern[i][1]); } path.close(); return path; }; QRCode.prototype._getSize = function _getSize () { var size; if (this.options.size) { size = parseInt(this.options.size, 10); } else { var element = this.element; var elementSize = surfaceSize(element, this.options.renderAs); var min = Math.min(elementSize.width, elementSize.height); if (min > 0) { size = min; } else { size = QRCodeDefaults.DEFAULT_SIZE; } } return size; }; QRCode.prototype._calculateBaseUnit = function _calculateBaseUnit (size, matrixSize) { var baseUnit = Math.floor(size / matrixSize); if (baseUnit < QRCodeDefaults.MIN_BASE_UNIT_SIZE) { var minSize = Math.ceil(matrixSize * QRCodeDefaults.MIN_BASE_UNIT_SIZE); this.onError(new Error( ("Insufficient size for QR Code: the current size is " + size + "px and the minimum size is " + minSize + "px.") )); } else if (baseUnit * matrixSize >= size && baseUnit - 1 >= QRCodeDefaults.MIN_BASE_UNIT_SIZE) { baseUnit--; } return baseUnit; }; QRCode.prototype._renderMatrix = function _renderMatrix (matrix, baseUnit, quietZoneSize) { var path = new draw.MultiPath({ fill: { color: this.options.color }, stroke: null }); for (var row = 0; row < matrix.length; row++) { var y = quietZoneSize + row * baseUnit; var column = 0; while (column < matrix.length) { while (matrix[row][column] === 0 && column < matrix.length) { column++; } if (column < matrix.length) { var x = column; while (matrix[row][column] === 1) { column++; } var x1 = round(quietZoneSize + x * baseUnit); var y1 = round(y); var x2 = round(quietZoneSize + column * baseUnit); var y2 = round(y + baseUnit); path.moveTo(x1, y1) .lineTo(x1, y2) .lineTo(x2, y2) .lineTo(x2, y1) .close(); } } } return path; }; QRCode.prototype._renderBackground = function _renderBackground (size, border) { var box = new Box(0, 0, size, size).unpad(border.width / 2); var background = draw.Path.fromRect(box.toRect(), { fill: { color: this.options.background }, stroke: { color: border.color, width: border.width } }); return background; }; QRCode.prototype.setOptions = function setOptions (options) { var newOptions = options || {}; this.options = extend(this.options, newOptions); if (options.value !== undefined) { this._value = String(this.options.value); } this._initSurface(); this.redraw(); }; QRCode.prototype.value = function value (value$1) { if (value$1 === undefined) { return this._value; } this._value = String(value$1); this.redraw(); }; QRCode.prototype._hasCustomLogo = function _hasCustomLogo () { return Boolean(this.options.overlay.imageUrl); }; QRCode.prototype._isSwiss = function _isSwiss () { return this.options.overlay.type === "swiss"; }; QRCode.prototype._getLogoSize = function _getLogoSize (defautLogoSize) { var width = this.options.overlay.width; var height = this.options.overlay.height; if (!width && !height) { width = height = defautLogoSize; } else if (width && !height) { height = width; } else if (!width && height) { width = height; } return { width: width, height: height }; }; return QRCode; }(Class)); setDefaultOptions(QRCode, { name: "QRCode", renderAs: "svg", encoding: "ISO_8859_1", value: "", errorCorrection: QRCodeDefaults.DEFAULT_ERROR_CORRECTION_LEVEL, background: QRCodeDefaults.DEFAULT_BACKGROUND, color: QRCodeDefaults.DEFAULT_DARK_MODULE_COLOR, size: "", padding: 0, border: { color: "", width: 0 }, overlay: { type: "image", imageUrl: "", width: 0, height: 0 } }); export default QRCode;