jquery - 在 Jcrop 中需要帮助 - 类 jcrop-tracker
问题描述
我已经使用 Live Camera 和 Upload File 开发了一个 Picture Capture WebApp。
除了以下用例外,它工作正常:
- 使用实时相机拍摄照片。
- 图片设置为裁剪。
- 裁剪图像后,将在右侧栏中捕获图像。
- 现在,当您使用实时相机重新捕获图像时 - 新图像将根据裁剪坐标显示。
我试图找到根本原因,但无法找到它为什么会这样。
这是 HTML 代码及其 Javascript 代码和小提琴:https ://jsfiddle.net/w6ahp7k9/
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Upload Image</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-jcrop/0.9.9/js/jquery.Jcrop.min.js"></script>
<style>
.center {
text-align: center;
}
</style>
<script type="text/javascript">
$(function () {
//Create variables (in this scope) to hold the Jcrop API and image size
var jcrop_api, boundx, boundy;
//#region WebCam
// Grab elements, create settings, etc.
let video = document.getElementById('video');
// Get access to the camera!
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
// Not adding `{ audio: true }` since we only want video now
navigator.mediaDevices.getUserMedia({ video: true }).then(function (stream) {
//video.src = window.URL.createObjectURL(stream);
video.srcObject = stream;
video.play();
});
}
// Elements for taking the snapshot
let canvas = document.getElementById('canvas');
let context = canvas.getContext('2d');
// Trigger photo take
document.getElementById("btnCapture").addEventListener("click", function () {
//Set Ratio
var ratio;
var width = 600;//window.innerWidth;
var height = 600;//window.innerHeight;
if (video.width > width) {
ratio = width / video.width;
}
else if (video.height > height) {
ratio = height / video.height;
}
else {
ratio = 1;
}
context.drawImage(video, 0, 0, video.width * ratio, video.height * ratio);
console.log('Video w:' + video.width * ratio);
console.log('Video h:' + video.height * ratio);
//Set the canvas to Image1
$("#Image1")[0].src = canvas.toDataURL();
$("#Image1").show();
$("#canvas").hide();
// destroy Jcrop if it is existed
if (typeof jcrop_api != 'undefined') {
jcrop_api.destroy();
jcrop_api = null;
}
$('#Image1').Jcrop({
onChange: SetCoordinates,
onSelect: SetCoordinates
},
function () {
// use the Jcrop API to get the real image size
var bounds = this.getBounds();
boundx = bounds[0];
boundy = bounds[1];
// Store the Jcrop API in the jcrop_api variable
jcrop_api = this;
});
});
//#endregion WebCam
//#region FileUpload, Resize, JCrop, Crop & Clear
$('#FileUpload1').change(function (event) {
try {
var files = event.target.files;
var file = files[0];
console.log('FileUpload1 Length:' + files.length);
if (file) {
$('#Image1').hide();
var reader = new FileReader();
reader.onload = function (e) {
//$('#Image1').show();
$('#Image1').attr("src", e.target.result);
};
reader.readAsDataURL($(this)[0].files[0]);
//#region Resize & JCrop
var reader = new FileReader();
// Set the image for the FileReader
reader.onload = function (e) {
var img = document.createElement("img");
img.src = e.target.result;
// Create your canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var MAX_WIDTH = 400;
var MAX_HEIGHT = 400;
let width = img.width;
let height = img.height;
console.log('Image w & h:' + width + '-' + height);
if (width == 0 && height == 0) {
throw new UserException("An internal error occured - please try again or contact your administrator!");
return;
}
// Add the resizing logic
if (width > height) {
if (width > MAX_WIDTH) {
height *= MAX_WIDTH / width;
width = MAX_WIDTH;
}
} else {
if (height > MAX_HEIGHT) {
width *= MAX_HEIGHT / height;
height = MAX_HEIGHT;
}
}
//Specify the resizing result
canvas.width = width;
canvas.height = height;
console.log('Canvas w & h:' + canvas.width + '-' + canvas.height);
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
dataurl = canvas.toDataURL(file.type);
document.getElementById("Image1").src = dataurl;
$('#Image1').show();
// destroy Jcrop if it is existed
if (typeof jcrop_api != 'undefined') {
jcrop_api.destroy();
jcrop_api = null;
}
$('#Image1').Jcrop({
onChange: SetCoordinates,
onSelect: SetCoordinates
},
function () {
// use the Jcrop API to get the real image size
var bounds = this.getBounds();
boundx = bounds[0];
boundy = bounds[1];
// Store the Jcrop API in the jcrop_api variable
jcrop_api = this;
});
};
reader.readAsDataURL(file);
//#endregion Resize & JCrop
}
}
catch (err) {
alert(err.message);
}
});
$('#btnCrop').click(function () {
var x1 = $('#imgX1').val();
var y1 = $('#imgY1').val();
var width = $('#imgWidth').val();
var height = $('#imgHeight').val();
var canvas = $("#canvas")[0];
var context = canvas.getContext('2d');
var img = new Image();
img.onload = function () {
canvas.height = height;
canvas.width = width;
context.drawImage(img, x1, y1, width, height, 0, 0, width, height);
$('#imgCropped').val(canvas.toDataURL());
$("#capturedImage")[0].src = canvas.toDataURL();
document.getElementById("<%=ImgExSrc.ClientID%>").value = canvas.toDataURL();
document.getElementById("btnSubmit").disabled = true;
$('#btnSubmit').show();
$('#lblTermsConditions').show();
$('#chkApprove').show();
};
img.src = $('#Image1').attr("src");
$("#canvas").hide();
});
$('#btnClear').click(function () {
Clear();
});
//#endregion FileUpload, Resize, JCrop, Crop & Clear
});
function Clear() {
$('#Image1').attr('src', 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==');
$("div.jcrop-holder").remove();
$("div.jcrop-tracker").remove();
$('#btnCrop').hide();
$('#btnClear').hide();
}
function SetCoordinates(c) {
$('#imgX1').val(c.x);
$('#imgY1').val(c.y);
$('#imgWidth').val(c.w);
$('#imgHeight').val(c.h);
$('#btnCrop').show();
$('#btnClear').show();
};
function UserException(message) {
alert(message);
console.log(message);
}
</script>
</head>
<body>
<form id="form2" runat="server">
<div class="container">
<div class="jumbotron">
<h1>Upload Image</h1>
<p class="lead">This application offer to capture image along with crop functionality using either a Live Camera or an Upload File Control.</p>
</div>
<div class="row">
<div class="col-md-4" style="background-color: lavender;">
<div class="center">
<p><b>Live Camera</b></p>
<video id="video" width="400" height="400" autoplay></video>
<br />
<input type="button" id="btnCapture" value="Capture" />
<br />
<br />
</div>
</div>
<div class="col-md-4" style="background-color: orange;">
<div class="center">
<p><b>Upload File</b></p>
<input type="file" id="FileUpload1" accept=".jpg,.png,.gif" />
<br />
<br />
</div>
<table class="table" border="0">
<tbody>
<tr>
<td>
<img id="Image1" src="" style="display: none" />
</td>
<td>
<canvas id="canvas" height="380" width="380"></canvas>
</td>
</tr>
</tbody>
</table>
<br />
<input type="hidden" name="imgX1" id="imgX1" />
<input type="hidden" name="imgY1" id="imgY1" />
<input type="hidden" name="imgWidth" id="imgWidth" />
<input type="hidden" name="imgHeight" id="imgHeight" />
<input type="hidden" name="imgCropped" id="imgCropped" />
<div class="align-items-center">
<input type="button" id="btnCrop" value="Crop" style="display: none" />
<input type="button" id="btnClear" value="Clear" style="display: none" />
<br />
<br />
</div>
</div>
<div class="col-md-4" style="background-color: lavender;">
<div class="center">
<p><b>Captured Image</b></p>
<img id="capturedImage" src="" runat="server" />
<asp:HiddenField runat="server" ID="ImgExSrc" />
<br />
<br />
<input type="checkbox" id="chkApprove" onchange="document.getElementById('btnSubmit').disabled = !this.checked;" style="display: none">
<asp:Label ID="lblTermsConditions" runat="server" Style="display: none" Text="I have read and understood the declaration of consent. I agree to the terms and conditions."></asp:Label>
<br />
<br />
<asp:Button ID="btnSubmit" OnClick="btnSubmit_Click" runat="server" Text="Submit" Style="display: none" />
<br />
<br />
</div>
</div>
</div>
</div>
</form>
</body>
</html>
解决方案
这是最终代码 - 工作代码:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head >
<title>Upload Image</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-jcrop/0.9.9/js/jquery.Jcrop.min.js"></script>
<style>
.center {
text-align: center;
}
</style>
<script type="text/javascript">
$(function () {
//Create variables (in this scope) to hold the Jcrop API and image size
var jcrop_api, boundx, boundy;
//#region WebCam
// Grab elements, create settings, etc.
let video = document.getElementById('video');
// Get access to the camera!
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
// Not adding `{ audio: true }` since we only want video now
navigator.mediaDevices.getUserMedia({ video: true }).then(function (stream) {
//video.src = window.URL.createObjectURL(stream);
video.srcObject = stream;
video.play();
});
}
// Elements for taking the snapshot
let canvas = document.getElementById('canvas');
let context = canvas.getContext('2d');
// Trigger photo take
document.getElementById("btnCapture").addEventListener("click", function () {
//Set Ratio
var ratio;
var width = 600;//window.innerWidth;
var height = 600;//window.innerHeight;
if (video.width > width) {
ratio = width / video.width;
}
else if (video.height > height) {
ratio = height / video.height;
}
else {
ratio = 1;
}
context.drawImage(video, 0, 0, video.width * ratio, video.height * ratio);
console.log('Video w:' + video.width * ratio);
console.log('Video h:' + video.height * ratio);
//Set the canvas to Image1
$("#Image1")[0].src = canvas.toDataURL();
$("#Image1").show();
$("#canvas").hide();
// destroy Jcrop if it is existed
if (typeof jcrop_api != 'undefined') {
jcrop_api.destroy();
jcrop_api = null;
}
$('#Image1').Jcrop({
onChange: SetCoordinates,
onSelect: SetCoordinates
},
function () {
// use the Jcrop API to get the real image size
var bounds = this.getBounds();
boundx = bounds[0];
boundy = bounds[1];
// Store the Jcrop API in the jcrop_api variable
jcrop_api = this;
});
});
//#endregion WebCam
//#region FileUpload, Resize, JCrop, Crop & Clear
$('#FileUpload1').change(function (event) {
try {
var files = event.target.files;
var file = files[0];
console.log('FileUpload1 Length:' + files.length);
if (file) {
$('#Image1').hide();
var reader = new FileReader();
reader.onload = function (e) {
//$('#Image1').show();
$('#Image1').attr("src", e.target.result);
};
reader.readAsDataURL($(this)[0].files[0]);
//#region Resize & JCrop
var reader = new FileReader();
// Set the image for the FileReader
reader.onload = function (e) {
var img = document.createElement("img");
img.src = e.target.result;
// Create your canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var MAX_WIDTH = 400;
var MAX_HEIGHT = 400;
let width = img.width;
let height = img.height;
console.log('Image w & h:' + width + '-' + height);
if (width == 0 && height == 0) {
throw new UserException("An internal error occured - please try again or contact your administrator!");
return;
}
// Add the resizing logic
if (width > height) {
if (width > MAX_WIDTH) {
height *= MAX_WIDTH / width;
width = MAX_WIDTH;
}
} else {
if (height > MAX_HEIGHT) {
width *= MAX_HEIGHT / height;
height = MAX_HEIGHT;
}
}
//Specify the resizing result
canvas.width = width;
canvas.height = height;
console.log('Canvas w & h:' + canvas.width + '-' + canvas.height);
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
dataurl = canvas.toDataURL(file.type);
document.getElementById("Image1").src = dataurl;
$('#Image1').show();
// destroy Jcrop if it is existed
if (typeof jcrop_api != 'undefined') {
jcrop_api.destroy();
jcrop_api = null;
}
$('#Image1').Jcrop({
onChange: SetCoordinates,
onSelect: SetCoordinates
},
function () {
// use the Jcrop API to get the real image size
var bounds = this.getBounds();
boundx = bounds[0];
boundy = bounds[1];
// Store the Jcrop API in the jcrop_api variable
jcrop_api = this;
});
};
reader.readAsDataURL(file);
//#endregion Resize & JCrop
}
}
catch (err) {
alert(err.message);
}
});
$('#btnCrop').click(function () {
var x1 = $('#imgX1').val();
var y1 = $('#imgY1').val();
var width = $('#imgWidth').val();
var height = $('#imgHeight').val();
var canvas = $("#canvas")[0];
var context = canvas.getContext('2d');
var img = new Image();
img.onload = function () {
canvas.height = height;
canvas.width = width;
context.drawImage(img, x1, y1, width, height, 0, 0, width, height);
$('#imgCropped').val(canvas.toDataURL());
$("#capturedImage")[0].src = canvas.toDataURL();
document.getElementById("<%=ImgExSrc.ClientID%>").value = canvas.toDataURL();
document.getElementById("btnSubmit").disabled = true;
$('#btnSubmit').show();
$('#lblTermsConditions').show();
$('#chkApprove').show();
//Reset the canvas height & width
console.log('before:' + canvas.height + '-' + canvas.width);
canvas.height = 380;
canvas.width = 380;
console.log('after:' + canvas.height + '-' + canvas.width);
};
img.src = $('#Image1').attr("src");
$("#canvas").hide();
});
$('#btnClear').click(function () {
Clear();
});
//#endregion FileUpload, Resize, JCrop, Crop & Clear
});
function Clear() {
$('#Image1').attr('src', 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==');
$("div.jcrop-holder").remove();
$("div.jcrop-tracker").remove();
$('#btnCrop').hide();
$('#btnClear').hide();
}
function SetCoordinates(c) {
$('#imgX1').val(c.x);
$('#imgY1').val(c.y);
$('#imgWidth').val(c.w);
$('#imgHeight').val(c.h);
$('#btnCrop').show();
$('#btnClear').show();
};
function UserException(message) {
alert(message);
console.log(message);
}
</script>
</head>
<body>
<form id="form2" >
<div class="container">
<div class="jumbotron">
<h1>Upload Image</h1>
<p class="lead">This application offer to capture image along with crop functionality using either a Live Camera or an Upload File Control.</p>
</div>
<div class="row">
<div class="col-md-4" style="background-color: lavender;">
<div class="center">
<p><b>Live Camera</b></p>
<video id="video" width="400" height="400" autoplay></video>
<br />
<input type="button" id="btnCapture" value="Capture" />
<br />
<br />
</div>
</div>
<div class="col-md-4" style="background-color: orange;">
<div class="center">
<p><b>Upload File</b></p>
<input type="file" id="FileUpload1" accept=".jpg,.png,.gif" />
<br />
<br />
</div>
<table class="table" border="0">
<tbody>
<tr>
<td>
<img id="Image1" src="" style="display: none" />
</td>
<td>
<canvas id="canvas" height="380" width="380"></canvas>
</td>
</tr>
</tbody>
</table>
<br />
<input type="hidden" name="imgX1" id="imgX1" />
<input type="hidden" name="imgY1" id="imgY1" />
<input type="hidden" name="imgWidth" id="imgWidth" />
<input type="hidden" name="imgHeight" id="imgHeight" />
<input type="hidden" name="imgCropped" id="imgCropped" />
<div class="align-items-center">
<input type="button" id="btnCrop" value="Crop" style="display: none" />
<input type="button" id="btnClear" value="Clear" style="display: none" />
<br />
<br />
</div>
</div>
<div class="col-md-4" style="background-color: lavender;">
<div class="center">
<p><b>Captured Image</b></p>
<img id="capturedImage" src="" />
<asp:HiddenField runat="server" ID="ImgExSrc" />
<br />
<br />
<input type="checkbox" id="chkApprove" onchange="document.getElementById('btnSubmit').disabled = !this.checked;" style="display: none">
<asp:Label ID="lblTermsConditions" runat="server" Style="display: none" Text="I have read and understood the declaration of consent. I agree to the terms and conditions."></asp:Label>
<br />
<br />
<asp:Button ID="btnSubmit" OnClientClick="alert('Submitted successfully!'); return false;" runat="server" Text="Submit" Style="display: none" />
<br />
<br />
</div>
</div>
</div>
</div>
</form>
</body>
</html>
推荐阅读
- django - Django allauth google extra_data
- javascript - 如何在浏览器内存中保存信息并在按下时显示而不使用react刷新页面?
- ruby-on-rails - 我在 Rails 应用程序中的表单未捕获数据
- bison - 需要帮助确定“默认操作的类型冲突”的原因
- tensorflow - LSTM 预测结果无法拟合真实值
- java - SAXParser 在 62 元素之后给我一个空值,原因不明,为什么?
- javascript - Rail 6 Webpack 导入 JS 第三方库 Uncaught ReferenceError: x is not defined
- python - 如何修复'消息:无法找到元素:{“method”:“name”,“selector”:“username”}'
- javascript - 选择特定选择选项时如何调用函数?
- java - 如何将下面的代码转换为常规的 java for 循环?