Merge pull request #1077 from fsih/filePlayground

Add upload and download image buttons to the playground
This commit is contained in:
DD Liu 2020-06-01 20:21:30 -04:00 committed by GitHub
commit 7dd437415c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 119 additions and 11 deletions

View file

@ -4,7 +4,7 @@ body {
margin: 0px; margin: 0px;
} }
body, html { body, html, .wrapper {
height: 100% height: 100%
} }
@ -13,3 +13,11 @@ body, html {
width: 90%; width: 90%;
margin: auto; margin: auto;
} }
#fileInput {
display: none;
}
.playgroundButton {
margin: 4px;
}

View file

@ -29,19 +29,23 @@ class Playground extends React.Component {
constructor (props) { constructor (props) {
super(props); super(props);
bindAll(this, [ bindAll(this, [
'downloadImage',
'handleUpdateName', 'handleUpdateName',
'handleUpdateImage' 'handleUpdateImage',
'onUploadImage'
]); ]);
// Append ?dir=rtl to URL to get RTL layout // Append ?dir=rtl to URL to get RTL layout
const match = location.search.match(/dir=([^&]+)/); const match = location.search.match(/dir=([^&]+)/);
const rtl = match && match[1] == 'rtl'; const rtl = match && match[1] == 'rtl';
this.id = 0;
this.state = { this.state = {
name: 'meow', name: 'meow',
rotationCenterX: 20, rotationCenterX: 20,
rotationCenterY: 400, rotationCenterY: 400,
imageFormat: 'svg', // 'svg', 'png', or 'jpg' imageFormat: 'svg', // 'svg', 'png', or 'jpg'
image: svgString, // svg string or data URI image: svgString, // svg string or data URI
rtl: rtl imageId: this.id, // If this changes, the paint editor will reload
rtl: rtl,
}; };
this.reusableCanvas = document.createElement('canvas'); this.reusableCanvas = document.createElement('canvas');
} }
@ -49,7 +53,12 @@ class Playground extends React.Component {
this.setState({name}); this.setState({name});
} }
handleUpdateImage (isVector, image, rotationCenterX, rotationCenterY) { handleUpdateImage (isVector, image, rotationCenterX, rotationCenterY) {
console.log(image); this.setState({
imageFormat: isVector ? 'svg' : 'png'
});
if (!isVector) {
console.log(`Image width: ${image.width} Image height: ${image.height}`);
}
console.log(`rotationCenterX: ${rotationCenterX} rotationCenterY: ${rotationCenterY}`); console.log(`rotationCenterX: ${rotationCenterX} rotationCenterY: ${rotationCenterY}`);
if (isVector) { if (isVector) {
this.setState({image, rotationCenterX, rotationCenterY}); this.setState({image, rotationCenterX, rotationCenterY});
@ -67,14 +76,105 @@ class Playground extends React.Component {
}); });
} }
} }
downloadImage () {
const downloadLink = document.createElement('a');
document.body.appendChild(downloadLink);
const format = this.state.imageFormat;
let data = this.state.image;
if (format === 'png' || format === 'jpg') {
data = this.b64toByteArray(data);
} else {
data = [data];
}
const blob = new Blob(data, {type: format});
const filename = `${this.state.name}.${format}`;
if ('download' in HTMLAnchorElement.prototype) {
const url = window.URL.createObjectURL(blob);
downloadLink.href = url;
downloadLink.download = filename;
downloadLink.type = blob.type;
downloadLink.click();
window.URL.revokeObjectURL(url);
} else {
// iOS Safari, open a new page and set href to data-uri
let popup = window.open('', '_blank');
const reader = new FileReader();
reader.onloadend = function () {
popup.location.href = reader.result;
popup = null;
};
reader.readAsDataURL(blob);
}
document.body.removeChild(downloadLink);
}
b64toByteArray (b64Data, sliceSize=512) {
// Remove header
b64Data = b64Data.substring(b64Data.indexOf('base64,') + 7);
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
return byteArrays;
}
uploadImage() {
document.getElementById(styles.fileInput).click();
}
onUploadImage(event) {
var file = event.target.files[0];
var type = file.type === 'image/svg+xml' ? 'svg' :
file.type === 'image/png' ? 'png' :
file.type === 'image/jpg' ? 'jpg' :
file.type === 'image/jpeg' ? 'jpg' :
null;
var reader = new FileReader();
if (type === 'svg') {
reader.readAsText(file,'UTF-8');
} else if (type === 'png' || type === 'jpg'){
reader.readAsDataURL(file);
} else {
alert("Couldn't read file type: " + file.type);
}
const that = this;
reader.onload = readerEvent => {
var content = readerEvent.target.result; // this is the content!
that.setState({
image: content,
name: file.name.split('.').slice(0, -1).join('.'),
imageId: ++that.id,
imageFormat: type,
rotationCenterX: undefined,
rotationCenterY: undefined,
});
}
}
render () { render () {
return ( return (
<PaintEditor <div className={styles.wrapper}>
{...this.state} <PaintEditor
imageId="meow" {...this.state}
onUpdateName={this.handleUpdateName} onUpdateName={this.handleUpdateName}
onUpdateImage={this.handleUpdateImage} onUpdateImage={this.handleUpdateImage}
/> />
<button className={styles.playgroundButton} onClick={this.uploadImage}>Upload</button>
<input id={styles.fileInput} type="file" name="name" onChange={this.onUploadImage} />
<button className={styles.playgroundButton} onClick={this.downloadImage}>Download</button>
</div>
); );
} }