1.0.4 • Published 3 years ago

drapeau v1.0.4

Weekly downloads
7
License
MIT
Repository
github
Last release
3 years ago

drapeau

Take care of your ragged lines

Given a text and a width, drapeau will find the font-size that creates the most balanced and visually pleasing composition. It is agnostic of any rendering context, so that you can use it to create beautiful paragraphs in any project (canvas, svg, TTY…).

This is like FitText.js, except that the best font-size for a given composition is not always the biggest.

See the demo.

How it works

Built on top of mattdesl's word-wrapper which takes care of the line wrapping algorithm, this module will give a score to all possible font-sizes for a given text and width.

This score starts at maximum, and is reduced by different penalties, defined arbitrarly to produce what is considered a good visual composition (no widows, well balanced ragged lines, etc…).

I am open to discussion on what should define a plausible penalty.

Installation

npm install --save drapeau

Usage

See example/ for a complete canvas implementation.

Basic usage

import drapeau from 'drapeau'

const { fontSize } = drapeau('lorem ipsum…', {
  step: 1,
  minFontSize: 12,
  maxFontSize: 72,
  width: 600,

  // This function will be used to measure the glyphs during word-wrapping and
  // penalties evaluation: default is monospace.
  // See example/ for a more complete implementation.
  measure: function (glyph, fontSize) {
    return { width: 1, height: 1 }
  },

  // See « hacking penalties » below.
  penalties: function (penalties) {
    return penalties
  }
})

Note: all dimensions related properties (step, minFOntSize, maxFontSize, width…) are expressed in user defined unit. The core of the module is agnostic of any render context, only your implementation will use specific units.

Hacking penalties

The goal of this module is to provide good enough defaults to not have to deal with penalties in most of the cases. However, some implementations may need to add, modify or even delete some penaltes.

To personnalize the way the score is computed, the options object therefore accepts a penalties property. This property is expectec to be a function which takes a deep cloned object of the default penalties as a parameter, and returns a mutated version of it:

import drapeau from 'drapeau'

const { fontSize } = drapeau('lorem ipsum…', {
  penalties: function (penalties) {
     // See what penalties are applied by default
    console.log(Object.keys(penalties))

    // Delete a default penalty
    // Note that the penalties object is cloned, so that you can mutate it however you like
    delete penalties.AVOID_WIDOWS

    // Mutate a default penalty
    penalties.WIDOWS.weight = 0.1

    // Add a custom penalty
    penalties.customPenality = {
      // Define the weight of this penalty compared to the others.
      // Should be in [0~1] range, default is 1.
      weight: 0.5,

      // If true, the penalty is ignored and does not impact the final score
      ignore: context => context.lines.length < 2,

      // If true, set the score to 0
      illegal: context => context.lines.length > 10,

      // Should return a value in the [0~1] range, which will be applied to the score,
      // 1 being the best score possible, 0 the worst
      value: context => …
    }

    return penalties
  }
})

See DEFAULT_PENALTIES in index.js.

Development

$ npm install             # install all npm dependencies
$ npm run example:serve   # start the dev server with livereload on the example folder
$ npm run example:deploy  # deploy your example folder on a gh-page branch
$ npm run test            # lint your js inside the lib folder

Dependencies

License

MIT.