Skip to content

Instantly share code, notes, and snippets.

@trevorhreed
Last active August 29, 2015 14:10
Show Gist options
  • Save trevorhreed/225dd884a89ea22f5a6a to your computer and use it in GitHub Desktop.
Save trevorhreed/225dd884a89ea22f5a6a to your computer and use it in GitHub Desktop.
function(){
var
MIN_IMAGE_RESOLUTION = 800,
MAX_CANVAS_SIZE = 375
;
return {
restrict: 'E',
scope: {
showMessage: '&onmessage',
api: '='
},
template: '',
link: function(scope, element, attrs) {
var
image = {},
canvas = {},
cropPts = false,
lastImageTooSmall = false
;
scope.showMessage = scope.showMessage();
scope.api.getImage = function(){
var parts = canvas.element[0].toDataURL('image/jpg', 1).split(',');
return {
"mimeType": parts[0].substring(5, parts[0].length-7),
"base64Data": parts[1]
};
};
scope.api.browse = function(){
var file = document.createElement('input');
file.type = 'file';
file.addEventListener('change', function(e){
e.stopPropagation();
e.preventDefault();
load(e.target.files);
});
// IE FIX: In ie, you can't call `click()` on a file input unless it's attached to the DOM
file.style.display = 'none';
$('body').append(file);
// END -- IE FIX
file.click();
};
scope.api.crop = function(){
if(!cropPts) { return; }
image.sx = image.sx + Math.floor((cropPts.x / canvas.w) * image.sw);
image.sy = image.sy + Math.floor((cropPts.y / canvas.h) * image.sh);
image.sw = Math.floor((cropPts.w / canvas.w) * image.sw);
image.sh = Math.floor((cropPts.h / canvas.h) * image.sh);
cropPts = false;
paint();
};
scope.api.reset = function(){
image.sx = 0;
image.sy = 0;
image.sw = image.data.naturalWidth;
image.sh = image.data.naturalHeight;
paint();
};
var getCanvas = function(image){
var width, height, canvas;
width = image.sw < image.sh ? MAX_CANVAS_SIZE * (image.sw / image.sh) : MAX_CANVAS_SIZE;
height = image.sh < image.sw ? MAX_CANVAS_SIZE * (image.sh / image.sw) : MAX_CANVAS_SIZE;
// We set the CSS size differently from the DOM size as a way to ensure the highest resolution possible while still providing a small enough editing experience that users won't have to scroll to crop (see http://stackoverflow.com/a/26047748/269061)
canvas = $("<canvas style='margin-left:auto;margin-right:auto;width:"+ width +"px;height:"+ height +"px;' width='" + image.sw + "' height='" + image.sh + "'></canvas>");
if(height < MAX_CANVAS_SIZE){
var extraSpace = (MAX_CANVAS_SIZE - height)/2;
canvas.css('margin-top', extraSpace +'px');
canvas.css('margin-bottom', extraSpace +'px')
}
return {
'element': canvas,
'ctx': canvas[0].getContext('2d'),
'w': width,
'h': height
}
}
var paint = function(){
canvas = getCanvas(image);
canvas.ctx.drawImage(image.data,
image.sx,image.sy,image.sw,image.sh,
0,0, image.sw, image.sh
);
element.html('');
element.append(canvas.element);
canvas.element.Jcrop({
keySupport: false,
aspectRatio: 1,
onSelect: function(pts){
cropPts = pts;
}
});
}
var load = function(files){
element.html('Loading...');
var file = files[0];
if(file){
var reader = new FileReader();
reader.onload = function(e){
var img = document.createElement('img');
img.src = e.target.result;
img.onload = function(){
if(img.naturalWidth < MIN_IMAGE_RESOLUTION || img.naturalHeight < MIN_IMAGE_RESOLUTION){
if(lastImageTooSmall){
scope.showMessage(scope.api.stillTooSmallMsg);
}else{
scope.showMessage(scope.api.tooSmallMsg);
}
lastImageTooSmall = true;
}else{
if(lastImageTooSmall){
scope.showMessage(scope.api.thatsBetterMsg);
}else{
scope.showMessage();
}
lastImageTooSmall = false;
}
image.data = img;
image.sx = 0;
image.sy = 0;
image.sw = img.naturalWidth;
image.sh = img.naturalHeight;
paint();
}
}
reader.readAsDataURL(file);
}
};
var el = element[0];
el.addEventListener('dragover', function(e){
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
}, false);
el.addEventListener('drop', function(e){
e.stopPropagation();
e.preventDefault();
load(e.dataTransfer.files);
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment