WIP: Add initial meme generator! #748

Merged
skhameneh merged 16 commits from featureTesting into master 2018-11-30 03:54:55 +01:00
3 changed files with 43 additions and 21 deletions
Showing only changes of commit b879baa3c8 - Show all commits

View file

@ -4,6 +4,7 @@
// be a flex container for children // be a flex container for children
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: relative;
} }
.dropzone { .dropzone {
@ -12,6 +13,7 @@
flex: 1 0 auto; flex: 1 0 auto;
// be a flex container for children // be a flex container for children
display: flex; display: flex;
padding: 1em;
-webkit-flex-direction: column; -webkit-flex-direction: column;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
@ -52,13 +54,17 @@
.dropzone-preview-image { .dropzone-preview-image {
display: block; display: block;
padding: 1em; width: 100%;
width: calc(100% - 2em); }
.dropzone-preview-memeify {
margin-top: 3em;
} }
.dropzone-memeify-button { .dropzone-memeify-button {
background: #333; background: $primary-color;
color: #fff; color: #fff;
cursor: pointer;
font-size: .8em; font-size: .8em;
padding: 3px 6px; padding: 3px 6px;
position: absolute; position: absolute;
@ -67,6 +73,14 @@
z-index: 3; z-index: 3;
} }
.dropzone-memeify-toolbar {
/* TODO: Cleanup `!important` */
background: $primary-color !important;
left: -1em !important;
right: -1em !important;
top: -4em !important;
}
.dropzone-instructions-display__chooser-label { .dropzone-instructions-display__chooser-label {
text-decoration: underline; text-decoration: underline;
} }

View file

@ -8,11 +8,10 @@ import RichDraggable from './RichDraggable';
import EditableFontface, { PRESETS as FontPresets } from './EditableFontface'; import EditableFontface, { PRESETS as FontPresets } from './EditableFontface';
import { import {
faEdit,
faFont, faFont,
faMinusCircle,
faPlusCircle,
} from '@fortawesome/free-solid-svg-icons'; } from '@fortawesome/free-solid-svg-icons';
library.add(faEdit);
library.add(faFont);
const getRasterizedCanvas = (contents, width, height) => { const getRasterizedCanvas = (contents, width, height) => {
return new Promise((resolve) => { return new Promise((resolve) => {
@ -30,10 +29,10 @@ const getRasterizedCanvas = (contents, width, height) => {
} }
// Attempt to match font kerning with the DOM. // Attempt to match font kerning with the DOM.
contents = '<style>svg{font-kerning:normal}</style>' + contents; const kerningAndPadding = '<style>svg{font-kerning:normal}body{padding:0;margin:0}</style>';
const svgContents = `<svg xmlns="http://www.w3.org/2000/svg" width="${width * 2}" height="${height * 2}"> const svgContents = `<svg xmlns="http://www.w3.org/2000/svg" width="${width * 2}" height="${height * 2}">
<foreignObject x="0" y="0" width="${width * 2}" height="${height * 2}" externalResourcesRequired="true"> <foreignObject x="0" y="0" width="${width * 2}" height="${height * 2}" externalResourcesRequired="true">
<html xmlns="http://www.w3.org/1999/xhtml"><body>${contents}</body></html> <html xmlns="http://www.w3.org/1999/xhtml"><head>${kerningAndPadding}</head><body>${contents}</body></html>
</foreignObject></svg>`; </foreignObject></svg>`;
const pixelRatio = 2; const pixelRatio = 2;
@ -153,13 +152,22 @@ export default class Creatify extends Component {
state, state,
} = this; } = this;
// TODO: Abstract into separate package & use CSS Modules.
const spacerCss = { width: '.3em' };
return ( return (
<div style={{ position: 'relative', flex: props.flex === true ? 1 : props.flex, display: props.flex ? 'flex' : 'block' }}> <div style={{ position: 'relative', flex: props.flex === true ? 1 : props.flex, display: props.flex ? 'flex' : 'block' }}>
<div style={{ position: 'absolute', top: 0, left: 0, right: 0, background: '#333', zIndex: 2 }}> <div className={props.toolbarClassName} style={{ alignItems: 'center', color: '#fff', display: 'flex', padding: '.3em', position: 'absolute', top: 0, left: 0, right: 0, background: '#333', flexDirection: 'row', zIndex: 2 }}>
{/* <FontAwesomeIcon icon={faPlusCircle} size="2x" />
<button onClick={() => this.renderContents()}>Rasterize</button> <div style={spacerCss} />
<Select isSearchable={false} options={state.fontOptions} onChange={(option) => this.setFont(option.fontName)} /> <FontAwesomeIcon icon={faMinusCircle} size="2x" />
*/} <div style={spacerCss} />
<div style={{ flex: 1 }}>
<Select style={{ flex: 1 }} isSearchable={false} options={state.fontOptions} onChange={(option) => this.setFont(option.fontName)} />
</div>
<div style={spacerCss} />
<div onClick={() => this.renderContents()} style={{ alignItems: 'center', alignSelf: 'stretch', color: '#fff', border: '1px solid #fff', display: 'flex', padding: '.4em' }}>
<span>Finish</span>
</div>
</div> </div>
<div ref={me.contents} style={{ fontSize: '22px', overflow: 'hidden', transform: 'translateZ(0)', flex: 1 }}> <div ref={me.contents} style={{ fontSize: '22px', overflow: 'hidden', transform: 'translateZ(0)', flex: 1 }}>
<RichDraggable bounds={state.bounds}> <RichDraggable bounds={state.bounds}>

View file

@ -154,7 +154,7 @@ class Dropzone extends React.Component {
}; };
const memeifyContent = memeify && file && filePreview ? ( const memeifyContent = memeify && file && filePreview ? (
<Creatify flex> <Creatify flex toolbarClassName={'dropzone-memeify-toolbar'}>
<div style={{ background: '#fff', flex: 1 }}> <div style={{ background: '#fff', flex: 1 }}>
<img style={{ width: '100%' }} src={filePreview} /> <img style={{ width: '100%' }} src={filePreview} />
</div> </div>
@ -168,7 +168,12 @@ class Dropzone extends React.Component {
{isUpdate && fileExt === 'mp4' ? ( {isUpdate && fileExt === 'mp4' ? (
<p>Video updates are currently disabled. This feature will be available soon. You can edit metadata.</p> <p>Video updates are currently disabled. This feature will be available soon. You can edit metadata.</p>
) : ( ) : (
<div className='dropzone-wrapper'> <div className={'dropzone-wrapper'}>
{ hasContent && !memeify && (
<div className={'dropzone-memeify-button'} onClick={() => this.setState({ memeify: !memeify })}>
<FontAwesomeIcon icon={faEdit} /> Memeify
</div>
)}
<form> <form>
<input <input
className='input-file' className='input-file'
@ -182,7 +187,7 @@ class Dropzone extends React.Component {
</form> </form>
<div className={dropZoneClassName} {...dropZoneHooks}> <div className={dropZoneClassName} {...dropZoneHooks}>
{hasContent ? ( {hasContent ? (
<div className={'dropzone-preview-wrapper'}> <div className={'dropzone-preview-wrapper' + (memeifyContent ? ' dropzone-preview-memeify' : '')}>
<DropzonePreviewImage {...dropZonePreviewProps} /> <DropzonePreviewImage {...dropZonePreviewProps} />
<div className={'dropzone-preview-overlay'}> <div className={'dropzone-preview-overlay'}>
{ dragOver ? <DropzoneDropItDisplay /> : null } { dragOver ? <DropzoneDropItDisplay /> : null }
@ -192,11 +197,6 @@ class Dropzone extends React.Component {
message={fileExt === 'mp4' ? 'Drag & drop new thumbnail' : null} message={fileExt === 'mp4' ? 'Drag & drop new thumbnail' : null}
/> />
) : null } ) : null }
{ !memeify && (
<div className={'dropzone-memeify-button'} onClick={() => this.setState({ memeify: !memeify })}>
<FontAwesomeIcon icon={faEdit} /> Memeify
</div>
)}
{memeifyContent} {memeifyContent}
</div> </div>
</div> </div>