Skip to content

Instantly share code, notes, and snippets.

@clark-stevenson
Created October 2, 2018 15:00
Show Gist options
  • Save clark-stevenson/44e3d524b9fda229b308e2f81dcf27b7 to your computer and use it in GitHub Desktop.
Save clark-stevenson/44e3d524b9fda229b308e2f81dcf27b7 to your computer and use it in GitHub Desktop.

Revisions

  1. clark-stevenson created this gist Oct 2, 2018.
    65 changes: 65 additions & 0 deletions fit.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,65 @@
    /**
    * Copyright (C) 2014 Justin Windle, http://soulwire.co.uk
    *
    * Modified version of https://github.com/soulwire/fit.js/
    *
    * Fits a Rectangle into a Rectangle returning the transform
    */

    interface FitSettings {
    xAlign: 'center' | 'bottom' | 'right' | 'left' | 'top';
    yAlign: 'center' | 'bottom' | 'right' | 'left' | 'top';
    cover: boolean;
    }

    interface FitRectangle {
    x: number;
    y: number;
    width: number;
    height: number;
    }

    interface FitTransform extends FitRectangle {
    tx: number;
    ty: number;
    scale: number;
    }

    const defaultSettings: FitSettings = {
    xAlign: 'left',
    yAlign: 'top',
    cover: false
    };

    /**
    * Fit a rect into a area returning a transform
    * @param rect - the source rectangle is what we want to fit
    * @param area - the area rectangle is what the rect fits into
    * @param settings - any optional settings
    */
    export function fit(rect: FitRectangle, area: FitRectangle, settings = defaultSettings) {
    const sx = area.width / rect.width;
    const sy = area.height / rect.height;
    const ra = rect.width / rect.height;
    const rb = area.width / area.height;
    const sH = settings.cover ? sy : sx;
    const sV = settings.cover ? sx : sy;
    const scale = ra >= rb ? sH : sV;
    const w = rect.width * scale;
    const h = rect.height * scale;
    const tx = settings.xAlign === 'center' ? 0.5 * (w - area.width) : settings.xAlign === 'right' ? w - area.width : 0.0;
    const ty = settings.yAlign === 'center' ? 0.5 * (h - area.height) : settings.yAlign === 'bottom' ? h - area.height : 0.0;

    const transform: FitTransform = {
    tx: area.x - tx - rect.x,
    ty: area.y - ty - rect.y,
    x: area.x - tx - rect.x * scale,
    y: area.y - ty - rect.y * scale,
    height: rect.height * scale,
    width: rect.width * scale,

    scale: scale
    };

    return transform;
    }