| @@ 6-138 (lines=133) @@ | ||
| 3 | ||
| 4 | var svgns = "http://www.w3.org/2000/svg"; |
|
| 5 | ||
| 6 | class SVGRenderer{ |
|
| 7 | constructor(svg, encodings, options){ |
|
| 8 | this.svg = svg; |
|
| 9 | this.encodings = encodings; |
|
| 10 | this.options = options; |
|
| 11 | } |
|
| 12 | ||
| 13 | render(){ |
|
| 14 | var currentX = this.options.marginLeft; |
|
| 15 | ||
| 16 | this.prepareSVG(); |
|
| 17 | for(let i = 0; i < this.encodings.length; i++){ |
|
| 18 | var encoding = this.encodings[i]; |
|
| 19 | var encodingOptions = merge(this.options, encoding.options); |
|
| 20 | ||
| 21 | var group = createGroup(currentX, encodingOptions.marginTop, this.svg); |
|
| 22 | ||
| 23 | setGroupOptions(group, encodingOptions); |
|
| 24 | ||
| 25 | this.drawSvgBarcode(group, encodingOptions, encoding); |
|
| 26 | this.drawSVGText(group, encodingOptions, encoding); |
|
| 27 | ||
| 28 | currentX += encoding.width; |
|
| 29 | } |
|
| 30 | } |
|
| 31 | ||
| 32 | prepareSVG(){ |
|
| 33 | // Clear the SVG |
|
| 34 | while (this.svg.firstChild) { |
|
| 35 | this.svg.removeChild(this.svg.firstChild); |
|
| 36 | } |
|
| 37 | ||
| 38 | calculateEncodingAttributes(this.encodings, this.options); |
|
| 39 | var totalWidth = getTotalWidthOfEncodings(this.encodings); |
|
| 40 | var maxHeight = getMaximumHeightOfEncodings(this.encodings); |
|
| 41 | ||
| 42 | var width = totalWidth + this.options.marginLeft + this.options.marginRight; |
|
| 43 | this.setSvgAttributes(width, maxHeight); |
|
| 44 | } |
|
| 45 | ||
| 46 | drawSvgBarcode(parent, options, encoding){ |
|
| 47 | var binary = encoding.data; |
|
| 48 | ||
| 49 | // Creates the barcode out of the encoded binary |
|
| 50 | var yFrom; |
|
| 51 | if(options.textPosition == "top"){ |
|
| 52 | yFrom = options.fontSize + options.textMargin; |
|
| 53 | } |
|
| 54 | else{ |
|
| 55 | yFrom = 0; |
|
| 56 | } |
|
| 57 | ||
| 58 | var barWidth = 0; |
|
| 59 | var x = 0; |
|
| 60 | for(var b = 0; b < binary.length; b++){ |
|
| 61 | x = b * options.width + encoding.barcodePadding; |
|
| 62 | ||
| 63 | if(binary[b] === "1"){ |
|
| 64 | barWidth++; |
|
| 65 | } |
|
| 66 | else if(barWidth > 0){ |
|
| 67 | drawLine(x - options.width * barWidth, yFrom, options.width * barWidth, options.height, parent); |
|
| 68 | barWidth = 0; |
|
| 69 | } |
|
| 70 | } |
|
| 71 | ||
| 72 | // Last draw is needed since the barcode ends with 1 |
|
| 73 | if(barWidth > 0){ |
|
| 74 | drawLine(x - options.width * (barWidth - 1), yFrom, options.width * barWidth, options.height, parent); |
|
| 75 | } |
|
| 76 | } |
|
| 77 | ||
| 78 | drawSVGText(parent, options, encoding){ |
|
| 79 | var textElem = document.createElementNS(svgns, 'text'); |
|
| 80 | ||
| 81 | // Draw the text if displayValue is set |
|
| 82 | if(options.displayValue){ |
|
| 83 | var x, y; |
|
| 84 | ||
| 85 | textElem.setAttribute("style", |
|
| 86 | "font:" + options.fontOptions + " " + options.fontSize + "px " + options.font |
|
| 87 | ); |
|
| 88 | ||
| 89 | if(options.textPosition == "top"){ |
|
| 90 | y = options.fontSize - options.textMargin; |
|
| 91 | } |
|
| 92 | else{ |
|
| 93 | y = options.height + options.textMargin + options.fontSize; |
|
| 94 | } |
|
| 95 | ||
| 96 | // Draw the text in the correct X depending on the textAlign option |
|
| 97 | if(options.textAlign == "left" || encoding.barcodePadding > 0){ |
|
| 98 | x = 0; |
|
| 99 | textElem.setAttribute("text-anchor", "start"); |
|
| 100 | } |
|
| 101 | else if(options.textAlign == "right"){ |
|
| 102 | x = encoding.width - 1; |
|
| 103 | textElem.setAttribute("text-anchor", "end"); |
|
| 104 | } |
|
| 105 | // In all other cases, center the text |
|
| 106 | else{ |
|
| 107 | x = encoding.width / 2; |
|
| 108 | textElem.setAttribute("text-anchor", "middle"); |
|
| 109 | } |
|
| 110 | ||
| 111 | textElem.setAttribute("x", x); |
|
| 112 | textElem.setAttribute("y", y); |
|
| 113 | ||
| 114 | textElem.appendChild(document.createTextNode(encoding.text)); |
|
| 115 | ||
| 116 | parent.appendChild(textElem); |
|
| 117 | } |
|
| 118 | } |
|
| 119 | ||
| 120 | ||
| 121 | setSvgAttributes(width, height){ |
|
| 122 | var svg = this.svg; |
|
| 123 | svg.setAttribute("width", width + "px"); |
|
| 124 | svg.setAttribute("height", height + "px"); |
|
| 125 | svg.setAttribute("x", "0px"); |
|
| 126 | svg.setAttribute("y", "0px"); |
|
| 127 | svg.setAttribute("viewBox", "0 0 " + width + " " + height); |
|
| 128 | ||
| 129 | svg.setAttribute("xmlns", svgns); |
|
| 130 | svg.setAttribute("version", "1.1"); |
|
| 131 | ||
| 132 | svg.style.transform = "translate(0,0)"; |
|
| 133 | ||
| 134 | if(this.options.background){ |
|
| 135 | svg.style.background = this.options.background; |
|
| 136 | } |
|
| 137 | } |
|
| 138 | } |
|
| 139 | ||
| 140 | ||
| 141 | ||
| @@ 4-135 (lines=132) @@ | ||
| 1 | import merge from "../help/merge.js"; |
|
| 2 | import {calculateEncodingAttributes, getTotalWidthOfEncodings, getMaximumHeightOfEncodings} from "./shared.js"; |
|
| 3 | ||
| 4 | class CanvasRenderer{ |
|
| 5 | constructor(canvas, encodings, options){ |
|
| 6 | this.canvas = canvas; |
|
| 7 | this.encodings = encodings; |
|
| 8 | this.options = options; |
|
| 9 | } |
|
| 10 | ||
| 11 | render(){ |
|
| 12 | // Abort if the browser does not support HTML5 canvas |
|
| 13 | if (!this.canvas.getContext) { |
|
| 14 | throw new Error('The browser does not support canvas.'); |
|
| 15 | } |
|
| 16 | ||
| 17 | this.prepareCanvas(); |
|
| 18 | for(let i = 0; i < this.encodings.length; i++){ |
|
| 19 | var encodingOptions = merge(this.options, this.encodings[i].options); |
|
| 20 | ||
| 21 | this.drawCanvasBarcode(encodingOptions, this.encodings[i]); |
|
| 22 | this.drawCanvasText(encodingOptions, this.encodings[i]); |
|
| 23 | ||
| 24 | this.moveCanvasDrawing(this.encodings[i]); |
|
| 25 | } |
|
| 26 | ||
| 27 | this.restoreCanvas(); |
|
| 28 | } |
|
| 29 | ||
| 30 | prepareCanvas(){ |
|
| 31 | // Get the canvas context |
|
| 32 | var ctx = this.canvas.getContext("2d"); |
|
| 33 | ||
| 34 | ctx.save(); |
|
| 35 | ||
| 36 | calculateEncodingAttributes(this.encodings, this.options, ctx); |
|
| 37 | var totalWidth = getTotalWidthOfEncodings(this.encodings); |
|
| 38 | var maxHeight = getMaximumHeightOfEncodings(this.encodings); |
|
| 39 | ||
| 40 | this.canvas.width = totalWidth + this.options.marginLeft + this.options.marginRight; |
|
| 41 | ||
| 42 | this.canvas.height = maxHeight; |
|
| 43 | ||
| 44 | // Paint the canvas |
|
| 45 | ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); |
|
| 46 | if(this.options.background){ |
|
| 47 | ctx.fillStyle = this.options.background; |
|
| 48 | ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); |
|
| 49 | } |
|
| 50 | ||
| 51 | ctx.translate(this.options.marginLeft, 0); |
|
| 52 | } |
|
| 53 | ||
| 54 | drawCanvasBarcode(options, encoding){ |
|
| 55 | // Get the canvas context |
|
| 56 | var ctx = this.canvas.getContext("2d"); |
|
| 57 | ||
| 58 | var binary = encoding.data; |
|
| 59 | ||
| 60 | // Creates the barcode out of the encoded binary |
|
| 61 | var yFrom; |
|
| 62 | if(options.textPosition == "top"){ |
|
| 63 | yFrom = options.marginTop + options.fontSize + options.textMargin; |
|
| 64 | } |
|
| 65 | else{ |
|
| 66 | yFrom = options.marginTop; |
|
| 67 | } |
|
| 68 | ||
| 69 | ctx.fillStyle = options.lineColor; |
|
| 70 | ||
| 71 | for(var b = 0; b < binary.length; b++){ |
|
| 72 | var x = b * options.width + encoding.barcodePadding; |
|
| 73 | ||
| 74 | if(binary[b] === "1"){ |
|
| 75 | ctx.fillRect(x, yFrom, options.width, options.height); |
|
| 76 | } |
|
| 77 | else if(binary[b]){ |
|
| 78 | ctx.fillRect(x, yFrom, options.width, options.height * binary[b]); |
|
| 79 | } |
|
| 80 | } |
|
| 81 | } |
|
| 82 | ||
| 83 | drawCanvasText(options, encoding){ |
|
| 84 | // Get the canvas context |
|
| 85 | var ctx = this.canvas.getContext("2d"); |
|
| 86 | ||
| 87 | var font = options.fontOptions + " " + options.fontSize + "px " + options.font; |
|
| 88 | ||
| 89 | // Draw the text if displayValue is set |
|
| 90 | if(options.displayValue){ |
|
| 91 | var x, y; |
|
| 92 | ||
| 93 | if(options.textPosition == "top"){ |
|
| 94 | y = options.marginTop + options.fontSize - options.textMargin; |
|
| 95 | } |
|
| 96 | else{ |
|
| 97 | y = options.height + options.textMargin + options.marginTop + options.fontSize; |
|
| 98 | } |
|
| 99 | ||
| 100 | ctx.font = font; |
|
| 101 | ||
| 102 | // Draw the text in the correct X depending on the textAlign option |
|
| 103 | if(options.textAlign == "left" || encoding.barcodePadding > 0){ |
|
| 104 | x = 0; |
|
| 105 | ctx.textAlign = 'left'; |
|
| 106 | } |
|
| 107 | else if(options.textAlign == "right"){ |
|
| 108 | x = encoding.width - 1; |
|
| 109 | ctx.textAlign = 'right'; |
|
| 110 | } |
|
| 111 | // In all other cases, center the text |
|
| 112 | else{ |
|
| 113 | x = encoding.width / 2; |
|
| 114 | ctx.textAlign = 'center'; |
|
| 115 | } |
|
| 116 | ||
| 117 | ctx.fillText(encoding.text, x, y); |
|
| 118 | } |
|
| 119 | } |
|
| 120 | ||
| 121 | ||
| 122 | ||
| 123 | moveCanvasDrawing(encoding){ |
|
| 124 | var ctx = this.canvas.getContext("2d"); |
|
| 125 | ||
| 126 | ctx.translate(encoding.width, 0); |
|
| 127 | } |
|
| 128 | ||
| 129 | restoreCanvas(){ |
|
| 130 | // Get the canvas context |
|
| 131 | var ctx = this.canvas.getContext("2d"); |
|
| 132 | ||
| 133 | ctx.restore(); |
|
| 134 | } |
|
| 135 | } |
|
| 136 | ||
| 137 | export default CanvasRenderer; |
|
| 138 | ||