<!DOCTYPE html>
<html lang="ja">
<head>
<meta content="width=device-width initial-scale=1.0 minimum-scale=1.0 maximum-scale=1.0 user-scalable=no" name="viewport">
<meta charset="utf-8">
<title>カメラ撮影とアップロード</title>
<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<!-- jQuery UI -->
<link id="link" rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/themes/base/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/css/bootstrap.css">
<!-- jQuery.mmenu -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jQuery.mmenu/5.5.3/core/js/jquery.mmenu.min.all.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jQuery.mmenu/5.5.3/core/css/jquery.mmenu.all.css">
<!-- toastr -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.3/toastr.min.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.3/toastr.min.js"></script>
<link rel="stylesheet" href="std/mmenu.css">
<link rel="stylesheet" href="std/basic.css">
<style>
.fields {
width: 85px;
font-size: 12px;
vertical-align: middle!important;
}
legend {
font-size: 18px;
padding-left: 6px;
}
/* 画像表示用 */
#row2 {
vertical-align: top!important;
}
/* カメラ用 */
#camera {
width: 400px;
height: 300px;
object-fit: fill;
}
#canvas {
/* display: none; */
}
</style>
<script>
jQuery.isMobile = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
toastr.options={"closeButton":false,"debug":false,"newestOnTop":false,"progressBar":false,"positionClass":"toast-bottom-center","preventDuplicates":false,"onclick":null,"showDuration":"300","hideDuration":"1000","timeOut":"3000","extendedTimeOut":"1000","showEasing":"swing","hideEasing":"linear","showMethod":"fadeIn","hideMethod":"fadeOut"};
if ( !$.isMobile ) {
toastr.options.positionClass = "toast-top-center";
}
var datepicker_option = {
dateFormat: 'yy/mm/dd',
dayNamesMin: ['日', '月', '火', '水', '木', '金', '土'],
monthNames: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
showMonthAfterYear: true,
yearSuffix: '年',
changeYear: true,
showAnim: 'fadeIn',
yearRange: "c-70:c"
}
$(function(){
var curlink = $("#title").text();
$("#title").html("<a href=\"./\" style=\"color:#fff\">" + curlink + "</a>");
});
var options = {
row1 : { title : "カメラ" },
row2 : { title : "" },
row3 : { title : "画像一覧<br>(ロード順)" },
row4 : { title : "" },
row_last : { title :"メッセージ" },
error : function(message){
$("#row_last").next().text( message );
toastr.error(message);
},
info : function(message){
$("#row_last").next().text( message );
toastr.success(message);
},
cerror : function( message ){
message = message + "<br>代替として動画を表示します"
$("#row_last").next().html( message );
toastr.error( message );
$("#camera")
.prop({
"loop" : true, "muted" : true, "controls" : true,
"src" : "mp4/freebies_018_win.mp4"
})
.css("border", "solid 1px #000");
}
};
// *************************************
// カメラ用データ
// *************************************
var camera;
var canvas;
var copy_count = 0;
$(function(){
// 1) options による行とフィールドの設定
// 2) Bootstrap 用 form-control クラスの追加
$(".fields").each(function(){
if ( options[ $(this).prop("id") ] ) {
$(this).html( options[ $(this).prop("id") ].title );
// 個別 css
if ( options[ $(this).prop("id") ].css ) {
$(this).next().find("input,select").css( options[ $(this).prop("id") ].css );
}
// 入力チェック用属性
if ( options[ $(this).prop("id") ].attr ) {
$(this).next().find("input,select").attr( options[ $(this).prop("id") ].attr );
}
}
$(this).next().find("input,select").addClass("form-control");
});
// スマホでロード時の処理のチラつき防止用
$("#wrapper").css({"visibility":"visible", "margin-bottom" : "0px" });
// 初期フォーカス
setTimeout( function(){$('#row1_fld').focus();}, 100 );
// video 内 camera
camera = $("#camera").get(0);
// *************************************
// 最新 API
// *************************************
if ( navigator.mediaDevices ) {
console.log("navigator.mediaDevices");
if ( $.isMobile ) {
$("#camera").css("width","100%");
}
navigator.mediaDevices.getUserMedia({video: true})
.then(function(stream){
camera.srcObject = stream;
})
.catch(function(err){
// ブラウザで使用を拒否した場合等( 動画で代替 )
options.cerror(err.name);
});
}
// *************************************
// 旧 API
// *************************************
else {
console.log("navigator.getUserMedia");
// 旧 WebRTCチェック用
var api = [
"webkitGetUserMedia", "mozGetUserMedia","msGetUserMedia"
]
$.each(api,function(idx){
if (navigator.getUserMedia = navigator.getUserMedia || navigator[api[idx]]) {
return false;
}
});
// WebRTC 使用可能
if ( navigator.getUserMedia ) {
if ( $.isMobile ) {
$("#camera").css("width","100%");
}
// カメラの表示
navigator.getUserMedia({video: true},
function(stream) {
camera.src = window.URL.createObjectURL(stream);
},
function(err){
// ブラウザで使用を拒否した場合等( 動画で代替 )
options.cerror(err.name);
}
);
}
else {
// WebRTC 使用不可( 動画で代替 )
options.cerror("WebRTC を使用できません");
}
}
// *************************************
// canvas にコピーして画像に変換
// *************************************
$("#copy").on( "click", function(){
copy_count++;
if ( copy_count > 3 ) {
options.error("撮影は3枚までです");
return false;
}
canvas = $("#canvas").get(0);
var ctx = canvas.getContext('2d');
ctx.drawImage(camera, 0, 0, canvas.width, canvas.height);
$("<img>").appendTo("#images")
.prop( {"src": canvas.toDataURL("image/jpeg"), "id": "image"+ copy_count } )
.css( {"width": "100px", "margin": "10px" } );
});
// *************************************
// アップロード処理
// *************************************
$("#frm").submit( function(event){
// 本来の送信処理はキャンセル
event.preventDefault();
if ( $("#images").html() == "" ) {
options.error("アップロードする画像ファイルを作成して下さい");
return;
}
$("fieldset").eq(0).prop("disabled", true);
// エラーメッセージエリアをクリア
$(".error").next().text( "" );
// 結果の表示エリアを全てクリア
$("#result").html( "" );
// **************************************
// ファイルのアップロード
// **************************************
console.log("アップロード処理開始");
var formData = new FormData();
// テストの為、約100K の制限
formData.append("MAX_FILE_SIZE", 100000);
var file_cnt = 0;
$("#images img").each( function() {
var base64 = $(this).prop("src");
var bin = atob(base64.split(',')[1]);
var buffer = new Uint8Array(bin.length);
for (var i = 0; i < bin.length; i++) {
buffer[i] = bin.charCodeAt(i);
}
var blob = new Blob([buffer.buffer], {type: "image/jpeg"});
file_cnt++;
var file_name = (new Date()).getTime();
formData.append("image"+file_cnt, blob, file_name +"_"+file_cnt+".jpg");
});
formData.append("FILE_COUNT", file_cnt );
$.ajax({
url: "./upload.php",
type: "POST",
data: formData,
processData: false, // jQuery がデータを処理しないよう指定
contentType: false // jQuery が contentType を設定しないよう指定
})
.done(function( data, textStatus ){
console.log( "status:" + textStatus );
console.log( "data:" + JSON.stringify(data, null, " ") );
options.info("アップロード処理が完了しました");
// アップロード結果の表示
$.each(data, function(idx,image){
if ( image.error != 0 ) {
$("#result").append("<tr><td><span id=\"result" +idx+"\"></span><b style='color:red'>" + image.name+ " : " + image.result +"</b></td></tr>");
}
else {
$("#result").append("<tr><td><span id=\"result" +idx+"\"></span>" + image.name + " : " + image.result +"</td></tr>");
}
$( "#result"+idx ).append($("#"+idx).clone());
});
$("#images").html("");
copy_count = 0;
})
.fail(function(jqXHR, textStatus, errorThrown ){
console.log( "status:" + textStatus );
console.log( "errorThrown:" + errorThrown );
options.info("アップロードに失敗しました");
})
.always(function() {
// 操作不可を解除
$("fieldset").eq(0).prop("disabled", false);
})
;
} );
// **************************************
// mmenu
// **************************************
$("#mmenu_left").mmenu({
navbar: {
title: "メニュー"
},
offCanvas: {
position : "left",
zposition : "next"
}
});
});
</script>
</head>
<body>
<div id="wrapper">
<script>
// スマホでロード時等の処理のチラつき防止用
$("#wrapper").css( {"visibility": "hidden", "margin-bottom" : "1000px" } );
</script>
<div id="head">
<a id="hamburger" href="#mmenu_left">
<span class="top-bar"></span>
<span class="middle-bar"></span>
<span class="bottom-bar"></span>
</a>
<div id="title">カメラ撮影とアップロード</div>
</div>
<div id="body">
<form id="frm" class="form-inline">
<fieldset>
<legend>アップロード</legend>
<table class="table table-condensed">
<tr>
<td class="fields" id="row1"></td>
<td>
<video
id="camera"
autoplay></video>
<canvas
id="canvas"
width="400"
height="300"></canvas>
</td>
</tr>
<tr>
<td class="fields" id="row2"></td>
<td>
<input id="copy" type="button" class="btn btn-primary btn-sm" value="撮影">
</td>
</tr>
<tr>
<td class="fields" id="row3"></td>
<td>
<div id="images"></div>
</td>
</tr>
<tr>
<td class="fields" id="row4"></td>
<td>
<input id="action" type="submit" class="btn btn-primary btn-sm" value="送信">
</td>
</tr>
<tr>
<td class="fields error" id="row_last"></td>
<td></td>
</tr>
</table>
</fieldset>
<fieldset>
<legend>結果</legend>
<table id="result" class="table table-condensed">
</table>
</fieldset>
</form>
</div>
<div id="comment">
ようこそ jQuery + Bootstrap(css) + mmenu + WebRTC(カメラ) + FormData + PHP<br><a href="https://www.studio-lab01.com/freebies.html" target="_blank">素材提供:らぼわん</a> / カメラが無い場合の動画素材 </div>
</div>
<div id="mmenu_left">
<ul>
<li class="mm_user_title">ページ選択</li>
<li><a class="mm_link_left" href="#" onclick="location='index.php';void(0)">リセット</a></li>
<li><a class="mm_link_left"
href="http://getbootstrap.com/css/"
onclick="location='index.php';void(0)"
target="_blank"
>Bootstrap(css)</a></li>
<li><a class="mm_link_left"
href="http://api.jquery.com/"
onclick="location='index.php';void(0)"
target="_blank"
>jQuery ドキュメント</a></li>
<li><a class="mm_link_left"
href="https://developer.mozilla.org/ja/docs/Web/Guide/Using_FormData_Objects"
onclick="location='index.php';void(0)"
target="_blank"
>FormData オブジェクトの利用 / MDN</a></li>
<li><a class="mm_link_left"
href="https://developer.mozilla.org/ja/docs/Web/API/MediaDevices"
onclick="location='index.php';void(0)"
target="_blank"
>MediaDevices (MDN)</a></li>
<li><a class="mm_link_left"
href="https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Taking_still_photos"
onclick="location='index.php';void(0)"
target="_blank"
>Taking still photos with WebRTC(英文)</a></li>
</ul>
</div>
</body>
</html>