kopia lustrzana https://github.com/hughchen/qr_image
Completed app
rodzic
9cb36829dd
commit
d3fd9828ae
81
index.css
81
index.css
|
@ -1,5 +1,78 @@
|
||||||
#qrcode {
|
.container {
|
||||||
width:160px;
|
position: relative;
|
||||||
height:160px;
|
}
|
||||||
margin-top:15px;
|
|
||||||
|
.vertical-center {
|
||||||
|
margin: 0;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
-ms-transform: translateY(-50%);
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slidecontainer {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
width: 100%;
|
||||||
|
height: 25px;
|
||||||
|
background: #d3d3d3;
|
||||||
|
outline: none;
|
||||||
|
opacity: 0.7;
|
||||||
|
-webkit-transition: .2s;
|
||||||
|
transition: opacity .2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
background: #04AA6D;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider::-moz-range-thumb {
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
background: #04AA6D;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
border-bottom: 1px dotted black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip .tooltiptext {
|
||||||
|
visibility: hidden;
|
||||||
|
width: 300px;
|
||||||
|
background-color: black;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 5px 0;
|
||||||
|
|
||||||
|
/* Position the tooltip */
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip:hover .tooltiptext {
|
||||||
|
visibility: visible;
|
||||||
}
|
}
|
107
index.html
107
index.html
|
@ -2,26 +2,113 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" href="index.css" />
|
<link rel="stylesheet" href="index.css" />
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://www.w3schools.com/w3css/4/w3.css"
|
||||||
|
/>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<div style="width: 50%; margin: 0 auto">
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<label>Image File (optional):</label>
|
||||||
|
<input type="file" id="imageLoader" name="imageLoader" />
|
||||||
|
<p>
|
||||||
|
Works better for square images (use an
|
||||||
|
<a href="https://www.online-image-editor.com/">editor</a> as
|
||||||
|
needed).
|
||||||
|
</p>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<canvas id="imageCanvas"></canvas>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<label>URL*:</label>
|
||||||
|
<input class="w3-input" id="text" type="text" />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<!-- <p>Bit size: <span id="printSize"></span></p> -->
|
||||||
|
|
||||||
|
<div class="tooltip">
|
||||||
|
Bit size:
|
||||||
|
<span class="tooltiptext"
|
||||||
|
>Larger sizes hide more of the image, but are easier to
|
||||||
|
scan. I found that a size of 30 works well.</span
|
||||||
|
>
|
||||||
|
<span id="printSize"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
<div class="slidecontainer">
|
||||||
<input
|
<input
|
||||||
id="text"
|
type="range"
|
||||||
type="text"
|
min="10"
|
||||||
value=""
|
max="100"
|
||||||
style="width: 80%"
|
value="30"
|
||||||
|
class="slider"
|
||||||
|
id="radiusSize"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<br><br>
|
<br />
|
||||||
|
|
||||||
<button type="button" onclick="makeCode()">Generate code</button>
|
<div class="tooltip">
|
||||||
|
Error Correction:
|
||||||
|
<span class="tooltiptext"
|
||||||
|
>Higher level of error correction makes bigger qr codes, but
|
||||||
|
also allows you to hide more of the QR code. The former is
|
||||||
|
more relevant to this app.</span
|
||||||
|
>
|
||||||
|
<span id="printCorrection"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<br><br>
|
<br /><br />
|
||||||
|
|
||||||
<canvas id="myCanvas" width="300" height="300"></canvas>
|
<div class="slidecontainer">
|
||||||
<div id="qrcode" style="display:none;"></div>
|
<input
|
||||||
|
type="range"
|
||||||
|
min="1"
|
||||||
|
max="3"
|
||||||
|
value="3"
|
||||||
|
class="slider"
|
||||||
|
id="errorCorrection"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="w3-button w3-white w3-border w3-border-blue"
|
||||||
|
style="margin: 0 auto"
|
||||||
|
onclick="makeCode()"
|
||||||
|
>
|
||||||
|
Generate QR code
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
<canvas id="myCanvas"></canvas>
|
||||||
|
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="w3-button w3-white w3-border w3-border-blue"
|
||||||
|
style="margin: 0 auto"
|
||||||
|
onclick="download()"
|
||||||
|
>
|
||||||
|
Download PNG
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<br /><br />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a id="link"></a>
|
||||||
|
<div id="qrcode" style="display: none"></div>
|
||||||
<script src="qrcode.js"></script>
|
<script src="qrcode.js"></script>
|
||||||
<script src="index.js"></script>
|
<script src="index.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
88
index.js
88
index.js
|
@ -1,11 +1,72 @@
|
||||||
|
// Upload image to canvas
|
||||||
|
var imageLoader = document.getElementById("imageLoader");
|
||||||
|
imageLoader.addEventListener("change", handleImage, false);
|
||||||
|
var uploadCanvas = document.getElementById("imageCanvas");
|
||||||
|
var uploadContext = uploadCanvas.getContext("2d");
|
||||||
|
|
||||||
|
img = false;
|
||||||
|
var canvas = false;
|
||||||
|
|
||||||
|
function handleImage(e) {
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onload = function (event) {
|
||||||
|
img = new Image();
|
||||||
|
img.onload = function () {
|
||||||
|
uploadCanvas.width = img.width;
|
||||||
|
uploadCanvas.height = img.height;
|
||||||
|
uploadContext.drawImage(img, 0, 0);
|
||||||
|
};
|
||||||
|
img.src = event.target.result;
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(e.target.files[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var qrcode = new QRCode("qrcode", {
|
var qrcode = new QRCode("qrcode", {
|
||||||
width: 256,
|
width: 256,
|
||||||
height: 256,
|
height: 256,
|
||||||
colorDark: "#000000",
|
colorDark: "#000000",
|
||||||
colorLight: "#ffffff",
|
colorLight: "#ffffff",
|
||||||
correctLevel: QRCode.CorrectLevel.H,
|
correctLevel: QRCode.CorrectLevel.L,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var sizeSlider = document.getElementById("radiusSize");
|
||||||
|
var sizeOutput = document.getElementById("printSize");
|
||||||
|
sizeOutput.innerHTML = sizeSlider.value; // Display the default slider value
|
||||||
|
var radiusRatio = sizeSlider.value/200;
|
||||||
|
|
||||||
|
// Update the current slider value (each time you drag the slider handle)
|
||||||
|
sizeSlider.oninput = function () {
|
||||||
|
sizeOutput.innerHTML = this.value;
|
||||||
|
radiusRatio = this.value/200;
|
||||||
|
};
|
||||||
|
|
||||||
|
var correctionSlider = document.getElementById("errorCorrection");
|
||||||
|
var correctionOutput = document.getElementById("printCorrection");
|
||||||
|
correctionOutput.innerHTML = correctionSlider.value; // Display the default slider value
|
||||||
|
var correctionLevel = correctionSlider.value;
|
||||||
|
if (correctionLevel === '1') {
|
||||||
|
qrcode._htOption.correctLevel = QRCode.CorrectLevel.L;
|
||||||
|
} else if (correctionLevel === '2') {
|
||||||
|
qrcode._htOption.correctLevel = QRCode.CorrectLevel.M;
|
||||||
|
} else if (correctionLevel === '3') {
|
||||||
|
qrcode._htOption.correctLevel = QRCode.CorrectLevel.H;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the current slider value (each time you drag the slider handle)
|
||||||
|
correctionSlider.oninput = function () {
|
||||||
|
correctionOutput.innerHTML = this.value;
|
||||||
|
correctionLevel = correctionSlider.value;
|
||||||
|
if (correctionLevel === '1') {
|
||||||
|
qrcode._htOption.correctLevel = QRCode.CorrectLevel.L;
|
||||||
|
} else if (correctionLevel === '2') {
|
||||||
|
qrcode._htOption.correctLevel = QRCode.CorrectLevel.M;
|
||||||
|
} else if (correctionLevel === '3') {
|
||||||
|
qrcode._htOption.correctLevel = QRCode.CorrectLevel.H;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether bit at current position should be full sized.
|
* Check whether bit at current position should be full sized.
|
||||||
*
|
*
|
||||||
|
@ -15,7 +76,6 @@ var qrcode = new QRCode("qrcode", {
|
||||||
* @return {isPosition} Whether or not the current bit is safe to modify.
|
* @return {isPosition} Whether or not the current bit is safe to modify.
|
||||||
*/
|
*/
|
||||||
function isSafeBit(i, j, QRLength) {
|
function isSafeBit(i, j, QRLength) {
|
||||||
|
|
||||||
// Currently hard coding position bits
|
// Currently hard coding position bits
|
||||||
if (i < 8 && j < 8) {
|
if (i < 8 && j < 8) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -52,6 +112,18 @@ function drawShape(ctx, i, j, bitLength, radiusRatio, QRLength) {
|
||||||
ctx.fillRect(xCenter - radius, yCenter - radius, 2 * radius, 2 * radius);
|
ctx.fillRect(xCenter - radius, yCenter - radius, 2 * radius, 2 * radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function download() {
|
||||||
|
// Download image
|
||||||
|
if (!canvas) {
|
||||||
|
alert("Error: no QR code to download");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var link = document.getElementById('link');
|
||||||
|
link.setAttribute('download', 'qr_image.png');
|
||||||
|
link.setAttribute('href', canvas.toDataURL("image/png").replace("image/png", "image/octet-stream"));
|
||||||
|
link.click();
|
||||||
|
}
|
||||||
|
|
||||||
function makeCode() {
|
function makeCode() {
|
||||||
// Grab url input
|
// Grab url input
|
||||||
elementText = document.getElementById("text");
|
elementText = document.getElementById("text");
|
||||||
|
@ -69,11 +141,6 @@ function makeCode() {
|
||||||
if (url.length < maxLength) {
|
if (url.length < maxLength) {
|
||||||
url += "?/" + "0".repeat(maxLength - url.length);
|
url += "?/" + "0".repeat(maxLength - url.length);
|
||||||
}
|
}
|
||||||
// else {
|
|
||||||
// alert("Input too long");
|
|
||||||
// elementText.focus();
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Generate URL bits
|
// Generate URL bits
|
||||||
qrcode.makeCode(url);
|
qrcode.makeCode(url);
|
||||||
|
@ -93,8 +160,11 @@ function makeCode() {
|
||||||
canvas.height = canvasLength;
|
canvas.height = canvasLength;
|
||||||
|
|
||||||
// Set background of canvas
|
// Set background of canvas
|
||||||
ctx.fillStyle = "#DDDDDD";
|
ctx.fillStyle = "#FFFFFF";
|
||||||
ctx.fillRect(0, 0, canvasLength, canvasLength);
|
ctx.fillRect(0, 0, canvasLength, canvasLength);
|
||||||
|
if (img) {
|
||||||
|
ctx.drawImage(img, 0, 0, canvasLength, canvasLength);
|
||||||
|
}
|
||||||
|
|
||||||
// Colors of true and false bits
|
// Colors of true and false bits
|
||||||
black = "#000000";
|
black = "#000000";
|
||||||
|
@ -108,7 +178,7 @@ function makeCode() {
|
||||||
} else {
|
} else {
|
||||||
ctx.fillStyle = white;
|
ctx.fillStyle = white;
|
||||||
}
|
}
|
||||||
drawShape(ctx, i, j, bitLength, 0.25, QRLength);
|
drawShape(ctx, i, j, bitLength, radiusRatio, QRLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue