<!doctype html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="lib/style.css">
<script src="lib/script.js"></script>
</head>
<body>
<h3>ドロップ</h3>
<span id="info_before" class="info"></span>
<div class="dropable_box"></div>
<h3>変換後</h3>
<span id="info_after" class="info"></span>
<img class="result"/>
</body>
</html>
{
"plnkr": {
"runtime": "system"
},
"dependencies": {
"jquery": "^3.3.1"
}
}
.dropable_box, .result{
display: block;
width: 256px;
height: 256px;
margin: 20px;
border: solid 1px black;
}
.info {
font-size: 8pt;
}
$(function(){
$(".dropable_box").on("dragover", function(e){
e.stopPropagation()
e.preventDefault()
})
//ドロップイベント
$(".dropable_box").on("drop", function(e){
e.stopPropagation()//親DOMへのイベントのバブリング禁止
e.preventDefault()
let self = this;
$.each(e.originalEvent.dataTransfer.files, function(idx, file){
var fr = new FileReader()
fr.self = self //thisエレメント
fr.file = file //SVG用に元ファイルも渡す
fr.onload = checkFileType //イベント定義
fr.readAsArrayBuffer(file) //読み込み開始
})
})
//ファイルタイプのチェック
//Refference from https://stackoverflow.com/questions/18299806/how-to-check-file-mime-type-with-javascript-before-upload
function checkFileType(e){
let arr = (new Uint8Array(e.target.result)).subarray(0, 4)
let header = "",
type = ""
for (let i = 0; i < arr.length; i++) {
header += arr[i].toString(16)
}
switch (header) {
case "89504e47":
type = "image/png"
break;
case "47494638":
type = "image/gif"
break;
case "ffd8ffe0":
case "ffd8ffe1":
case "ffd8ffe2":
type = "image/jpeg"
break;
default:
type = ""
break;
}
if(type!=="") {
//正しく読み込めた
checkFile_callback.call(this.self, type, e.target.result)
return;
}
//SVG形式で読み込みチェック
let fr = new FileReader();
fr.self = this.self; //元エレメント
fr.bin = e.target.result;
fr.onloadend = function(e2) {
//XMLパーサーを使う
let PARSER = new DOMParser()
let doc = null,
type = "image/svg+xml"
try {
doc = PARSER.parseFromString(e2.target.result, type)
} catch(er){
//失敗(異常系)
checkFile_callback.call(this.self, "unknown", null)
return;
}
//失敗(正常系)
if(doc.getElementsByTagName("parsererror").length > 0){
checkFile_callback.call(this.self, "unknown", null)
return;
}
//正しく読み込めた
checkFile_callback.call(this.self, type, this.bin)
return;
}
fr.readAsText(this.file)
}
//ファイルチェック後のコールバック
function checkFile_callback(type, data){
if(type !== "unknown"){
//バイナリをBLOB-URL化
let bin = new Uint8Array(data)
let blob_url = URL.createObjectURL(
new Blob([bin], { 'type': type })
)
//読み込んだファイルを表示
$(this).css({"background": "url("+blob_url+") center center/contain no-repeat"})
//ファイルサイズの変更
let image = new Image() //イメージを作成
image.src = blob_url //画像ファイルを読み込む
//読み込み完了イベント
image.onload = function(){
$("#info_before").html("File-Size: "+getSizeStr(bin.length)+"<br>Type: "+type+"</br>Image-Size: "+this.naturalWidth + " x " + this.naturalHeight)
let canvas = document.createElement("canvas") //キャンバスを作成
let ctx = canvas.getContext('2d')
//256x256より大きければサイズを縮小
if(this.naturalWidth > 256 || this.naturalHeight > 256){
//縮小時のアスペクト値を維持するための計算
let resize = 256 / [this.naturalWidth, this.naturalHeight].sort()[1]
canvas.width = this.naturalWidth * resize
canvas.height = this.naturalHeight * resize
//あらかじめ白で塗りつぶす(透過色対策)
ctx.fillStyle="white";
ctx.fillRect(0,0,canvas.width,canvas.height);
//キャンバスへ縮小描画
ctx.drawImage(this,0,0,canvas.width,canvas.height)
} else {
canvas.width = this.naturalWidth
canvas.height = this.naturalHeight
//あらかじめ白で塗りつぶす(透過色対策)
ctx.fillStyle="white";
ctx.fillRect(0,0,canvas.width,canvas.height);
//そのまま描画
ctx.drawImage(this,0,0)
}
//元のURLをバックアップ(あとで破棄)
this.old_src = this.src
//イメージ形式をJpegへ変換
this.src = canvas.toDataURL("image/jpeg")
//再読込完了イベント
this.onload = function(){
//変換後のURLをセット
$(".result").attr("src", this.src).css({"width": this.naturalWidth, "height": this.naturalHeight})
//URLからファイルサイズを取得する
var xhr = new XMLHttpRequest()
xhr.open("GET", this.src)
xhr.self = this
xhr.responseType = "arraybuffer"
xhr.onload = function() {
let bin = new Uint8Array(xhr.response)
//詳細表示
$("#info_after").html("File-Size: "+getSizeStr(bin.length)+"<br>Type: image/jpeg</br>Image-Size: "+this.self.naturalWidth + " x " + this.self.naturalHeight)
};
xhr.send();
}
}
}
}
//ファイルサイズを単位で表示
function getSizeStr(e){
var t = ["Bytes", "KB", "MB", "GB", "TB"]
if (0 === e) return "n/a"
var n = parseInt(Math.floor(Math.log(e) / Math.log(1024)))
return Math.round(e / Math.pow(1024, n)) + " " + t[n]
}
//加工後のイメージを<input type=file>に変換する
function addFileList(input, url, file) {
if (typeof url === 'string')
url = [url]
else if (!Array.isArray(url)) {
throw new Error('url needs to be a file path string or an Array of file path strings')
}
const file_list = url.map(fp => file)
file_list.__proto__ = Object.create(FileList.prototype)
Object.defineProperty(input, 'files', {
value: file_list
})
return input
}
})