diff --git a/src/playground/playground.css b/src/playground/playground.css index f6144dfe..0b8e3f3d 100644 --- a/src/playground/playground.css +++ b/src/playground/playground.css @@ -4,7 +4,7 @@ body { margin: 0px; } -body, html { +body, html, .wrapper { height: 100% } @@ -12,4 +12,12 @@ body, html { height: 90%; width: 90%; margin: auto; -} \ No newline at end of file +} + +#fileInput { + display: none; +} + +.playgroundButton { + margin: 4px; +} diff --git a/src/playground/playground.jsx b/src/playground/playground.jsx index e5cd5813..963ed980 100644 --- a/src/playground/playground.jsx +++ b/src/playground/playground.jsx @@ -29,19 +29,23 @@ class Playground extends React.Component { constructor (props) { super(props); bindAll(this, [ + 'downloadImage', 'handleUpdateName', - 'handleUpdateImage' + 'handleUpdateImage', + 'onUploadImage' ]); // Append ?dir=rtl to URL to get RTL layout const match = location.search.match(/dir=([^&]+)/); const rtl = match && match[1] == 'rtl'; + this.id = 0; this.state = { name: 'meow', rotationCenterX: 20, rotationCenterY: 400, imageFormat: 'svg', // 'svg', 'png', or 'jpg' 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'); } @@ -49,7 +53,12 @@ class Playground extends React.Component { this.setState({name}); } 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}`); if (isVector) { 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 () { return ( - +
+ + + + +
); }