Skip to content

Instantly share code, notes, and snippets.

@zackify
Created August 19, 2014 00:19
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zackify/3c690e05df2808391060 to your computer and use it in GitHub Desktop.
Save zackify/3c690e05df2808391060 to your computer and use it in GitHub Desktop.
First stab at a React.js client side cropper component using Jcrop ---comments coming soon---
/** @jsx React.DOM */
import React from 'react';
import {uploadImageBlob} from 'appicus';
export var crop = React.createClass({
contextTypes: {
site: React.PropTypes.object
},
getInitialState: function(){
return {image: this.props.image,scaled: false} || {}
},
componentDidMount: function(){
this.setupImage();
},
componentWillReceiveProps: function(nextProps){
if(nextProps.image != this.props.image) {
var image = nextProps.image
this.setState({image: image,scaled: false})
}
},
componentDidUpdate: function(){
if(this.state.scaled || !this.state.image) return;
console.log('new image selected to crop')
var image = new Image()
image.src = this.state.image;
var self = this
image.onload = function(){
var canvas = document.createElement('canvas');
var ratio = window.devicePixelRatio || 1
var width = 220;
var effectiveWidth = image.width / ratio
if(effectiveWidth < width) width = effectiveWidth
self.setState({width: width})
var height = image.height * (width / image.width);
if(window.devicePixelRatio){
canvas.height = height * ratio
canvas.width = width * ratio
canvas.style.width = width + 'px';
canvas.style.height = height + 'px';
}
else{
canvas.height = height
canvas.width = width
}
var ctx = canvas.getContext('2d');
if(window.devicePixelRatio) ctx.scale(ratio,ratio)
ctx.drawImage(image, 0, 0, width, height);
var scaled = canvas.toDataURL();
self.setState({scaled: scaled});
$(self.refs.crop.getDOMNode()).Jcrop({
bgColor: 'none',
bgOpacity: .4,
aspectRatio: 1,
setSelect: [0, 0, 100, 100],
onSelect: self.cropSelectedArea,
onChange: self.cropSelectedArea
});
}
},
cropSelectedArea: function(selection){
if(!this.state.scaled) return;
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var image = new Image();
image.src = this.state.scaled;
var self = this;
image.onload = function(){
var ratio = 1
if(window.devicePixelRatio) ratio = window.devicePixelRatio
ctx.drawImage(image, selection.x * ratio, selection.y * ratio, selection.w * ratio, selection.h * ratio, 0, 0, selection.w * ratio, selection.h * ratio);
self.setState({cropped: canvas.toDataURL()});
}
},
b64toBlob: function(base64Data, contentType) {
contentType = contentType || '';
var sliceSize = 1024;
var byteCharacters = atob(base64Data);
var bytesLength = byteCharacters.length;
var slicesCount = Math.ceil(bytesLength / sliceSize);
var byteArrays = new Array(slicesCount);
for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
var begin = sliceIndex * sliceSize;
var end = Math.min(begin + sliceSize, bytesLength);
var bytes = new Array(end - begin);
for (var offset = begin, i = 0 ; offset < end; ++i, ++offset) {
bytes[i] = byteCharacters[offset].charCodeAt(0);
}
byteArrays[sliceIndex] = new Uint8Array(bytes);
}
return new Blob(byteArrays, { type: contentType });
},
crop: function(){
var b64 = this.state.cropped
var b64 = b64.substring(b64.indexOf(',') + 1)
var blob = this.b64toBlob(b64,'image/png')
var self = this
uploadImageBlob(this.context.site.site_id,blob,function(image){
self.props.onChange(image)
self.setState({scaled: false, image: false})
})
},
closeCrop: function(){
this.setState({scaled: false, image: false})
},
render: function(){
var image = null;
if(this.state.scaled) image = <div>
<img ref="crop" width={this.state.width} src={this.state.scaled} />
<div className="button" onClick={this.crop}>Crop</div>
<div className="button" onClick={this.closeCrop}>Close</div>
</div>
return this.transferPropsTo(<div>{image}</div>)
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment