From e9d72b07af0f8a5c71ed21294235dd9f0091ab23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Tue, 12 Jul 2016 17:03:22 -0300 Subject: [PATCH] AllType card line splitting and scaling --- example/index.html | 27 ++++++++-- src/components/Cards/AlltypeCard.js | 80 ++++++++++++++++++++++++++--- src/components/Cards/ScaledLine.js | 45 ++++++++++++++++ 3 files changed, 143 insertions(+), 9 deletions(-) create mode 100644 src/components/Cards/ScaledLine.js diff --git a/example/index.html b/example/index.html index 1fa10126..368e0f91 100644 --- a/example/index.html +++ b/example/index.html @@ -4,7 +4,7 @@ This is an example - + diff --git a/src/components/Cards/AlltypeCard.js b/src/components/Cards/AlltypeCard.js index 03cc520a..40cfbdcf 100644 --- a/src/components/Cards/AlltypeCard.js +++ b/src/components/Cards/AlltypeCard.js @@ -1,14 +1,82 @@ import React, { PropTypes } from 'react'; import { Card } from '../UI'; +import ScaledLine from './ScaledLine'; -export default function AlltypeCard({ onClick, text }) { - return ( - -

{text}

-
- ); + +export default class AlltypeCard extends React.Component { + + // Based on the Slabtype Algorithm by Erik Loyer + // http://erikloyer.com/index.php/blog/the_slabtype_algorithm_part_1_background/ + renderInscription(inscription) { + + var idealCharPerLine = 20; + + // segment the text into lines + var words = inscription.split(' '); + var preText, postText, finalText; + var preDiff, postDiff; + var wordIndex = 0; + var lineText = []; + + // while we still have words left, build the next line + while (wordIndex < words.length) { + postText = ''; + + // build two strings (preText and postText) word by word, with one + // string always one word behind the other, until + // the length of one string is less than the ideal number of characters + // per line, while the length of the other is greater than that ideal + while (postText.length < idealCharPerLine) { + preText = postText; + postText += words[wordIndex] + ' '; + wordIndex++; + if (wordIndex >= words.length) { + break; + } + } + + // calculate the character difference between the two strings and the + // ideal number of characters per line + preDiff = idealCharPerLine - preText.length; + postDiff = postText.length - idealCharPerLine; + + // if the smaller string is closer to the length of the ideal than + // the longer string, and doesn’t contain just a single space, then + // use that one for the line + if ((preDiff < postDiff) && (preText.length > 2)) { + finalText = preText; + wordIndex--; + + // otherwise, use the longer string for the line + } else { + finalText = postText; + } + + lineText.push(finalText.substr(0, finalText.length - 1)); + } + return lineText.map(text => ( + + {text} + + )); + } + + render() { + const { onClick, text } = this.props; + return ( + +
{this.renderInscription(text)}
+
+ ); + } } + AlltypeCard.propTypes = { + onClick: PropTypes.func, text: PropTypes.string.isRequired }; + +AlltypeCard.defaultProps = { + onClick: function() {}, +}; diff --git a/src/components/Cards/ScaledLine.js b/src/components/Cards/ScaledLine.js new file mode 100644 index 00000000..5712fa0e --- /dev/null +++ b/src/components/Cards/ScaledLine.js @@ -0,0 +1,45 @@ +import React, { PropTypes } from 'react'; + +export default class ScaledLine extends React.Component { + constructor(props) { + super(props); + this._content = null; + this.state = { + contentWidth: 0, + ratio: 1, + }; + } + + componentDidMount() { + const actualContent = this._content.children[0]; + + this.setState({ + contentWidth: actualContent.offsetWidth, + ratio: this.props.toWidth / actualContent.offsetWidth, + }); + } + + render() { + const { ratio } = this.state; + const { children } = this.props; + + var baseFontSize = 15; + + var styles = { + whiteSpace: 'nowrap', + textAlign: 'center' + }; + styles.fontSize = Math.round((baseFontSize * ratio)*1000)/1000 + + return ( +
this._content = c} style={styles}> + {children} +
+ ) + } +}; + +ScaledLine.propTypes = { + toWidth: PropTypes.number.isRequired, + children: PropTypes.node.isRequired +};