Cropperを使ってトリミングをしながら画像アップロード

Cropper.jsは、画像のトリミングができるJavaScriptライブラリです。 トリミングとアップロードの作業がブラウザ上で一括して行えるので、作業の効率化が図れそうです。

※jQueryプラグイン版のCropperも公開されていますが、本記事ではCropper.jsの紹介をします。

サンプル

画像をトリミングしながらアップロードします。

フォーム設定

コード

まず、cropper.min.jsとcropper.min.cssを登録したのち、下記sample.jsとsample.cssを登録します。
※Cropper.js v1.4.1で動作を確認しています。

JavaScript

sample.js

(function(){"use strict";varcropper,file,cropperFile,cropperPreview,cropperCanvas,cropperHeight,cropperWidth;kintone.events.on(['app.record.create.show','app.record.edit.show',],function(event){kintone.app.record.setFieldShown('添付ファイル',false);kintone.app.record.getSpaceElement('space').innerHTML='\<div class="control-label-gaia"\>\<span class="control-label-text-gaia"\>添付ファイル\</span\>\</div\>\<div id="cropperWrapper"\>\<input id="cropperFile" type="file"\>\<div class="cropperContent"\>\<div id="cropperPreview"\>\</div\>\<p\>\<span id="cropperHeight"\>\</span\>\*\<span id="cropperWidth"\>\</span\>px\</p\>\</div\>\<div class="cropperContent"\>\<div id="cropperCanvas"\>\</div\>\</div\>\</div\>';cropperFile=document.getElementById('cropperFile');cropperPreview=document.getElementById('cropperPreview');cropperCanvas=document.getElementById('cropperCanvas');cropperHeight=document.getElementById('cropperHeight');cropperWidth=document.getElementById('cropperWidth');if(event.type==='app.record.edit.show'){varxhr=newXMLHttpRequest();xhr.open('GET','/k/v1/file.json?fileKey='+event.record.添付ファイル.value[0].fileKey);xhr.setRequestHeader('X-Requested-With','XMLHttpRequest');xhr.responseType='blob';xhr.addEventListener('load',function(){varimage=newImage();image.addEventListener('load',function(){cropperPreview.appendChild(image);cropperHeight.innerHTML=image.naturalHeight;cropperWidth.innerHTML=image.naturalWidth;document.getElementsByClassName('cropperContent')[0].style.display='block';});image.src=(window.URL||window.webkitURL).createObjectURL(xhr.response);});xhr.send();}cropperFile.addEventListener('change',function(e){varreader=newFileReader();file=e.target.files[0]||file;if(file.type.indexOf("image")\<0){returnfalse;}reader.addEventListener('load',function(e){cropperCanvas.innerHTML='\<img src="'+e.target.result+'"\>';cropper=newCropper(cropperCanvas.children[0],{aspectRatio:1,preview:cropperPreview});cropperCanvas.children[0].addEventListener('crop',function(e){cropperHeight.innerHTML=Math.floor(e.detail.height);cropperWidth.innerHTML=Math.floor(e.detail.width);});[].forEach.call(document.getElementsByClassName('cropperContent'),function(element){element.style.display='block';});});reader.readAsDataURL(file);});});kintone.events.on(['app.record.create.submit.success','app.record.edit.submit.success',],function(event){if(!file)returnevent;returnnewkintone.Promise(function(resolve){cropper.getCroppedCanvas().toBlob(function(blob){varformData=newFormData();varxhr=newXMLHttpRequest();formData.append('\_\_REQUEST\_TOKEN\_\_',kintone.getRequestToken());formData.append('file',blob,file.name);xhr.open('POST',encodeURI('/k/v1/file.json'));xhr.setRequestHeader('X-Requested-With','XMLHttpRequest');xhr.addEventListener('load',function(){kintone.api('/k/v1/record','PUT',{app:kintone.app.getId(),id:event.recordId,record:{添付ファイル:{value:[{fileKey:JSON.parse(xhr.responseText).fileKey}]}}}).then(function(){resolve(event);});});xhr.send(formData);},file.type);});});})();// ポリフィル(参考URL:https://developer.mozilla.org/ja/docs/Web/API/HTMLCanvasElement/toBlob)if(!HTMLCanvasElement.prototype.toBlob){Object.defineProperty(HTMLCanvasElement.prototype,'toBlob',{value:function(callback,type,quality){varbinStr=atob(this.toDataURL(type,quality).split(',')[1]),len=binStr.length,arr=newUint8Array(len);for(vari=0;i\<len;i++){arr[i]=binStr.charCodeAt(i);}callback(newBlob([arr],{type:type||'image/png'}));}});}

CSS

sample.css

#cropperWrapper{width:600px;}#croppeWrapper:after{content:'';display:block;clear:both;}.cropperContent{float:left;margin:10px;display:none;}#cropperFile{width:100%;}#cropperPreview{text-align:center;overflow:hidden;}#cropperPreview,#cropperPreviewimg{width:100px;height:100px;}#cropperCanvas{width:400px;height:200px;}

トリミングのアスペクト比等々は、オプションで変更できます。 こちらを参考にしてください。

江田さん、いつもお世話になっております。本件の記事に関してですが、Mobile版に移植することは可能でしょうか?Mobile版で写真を撮影し加工(余白削除、明るさ調整等)したいニーズがございます。良いアイデアがありましたら、お知らせいただけると幸甚です。よろしくお願いします。