@progress/kendo-charts
Version:
Kendo UI platform-independent Charts library
416 lines (333 loc) • 12.3 kB
JavaScript
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;