Skip to main content
June 17, 2019
Answered

Fit Layer To Canvas Keeping Aspect Ratio

  • June 17, 2019
  • 2 replies
  • 6225 views

Hello

I'm currently using the below script to resize a layer to fit the canvas, however I would like to adjust it so it keeps in ratio. It currently stretches the whole layer to fit the canvas which isn't quite what I'm after. I would like it to fit specifically to the width or the height of the canvas depending if the layer content is wider than it is tall or vice-versa. Unfortunately I have zero scripting skills and am at a complete loss on what to adjust. Any help would be fantastic.

var maintainAspectRatio;// set to true to keep aspect ratio 

    if(app.documents.length>0){ 

        app.activeDocument.suspendHistory ('Fit Layer to Canvas', 'FitLayerToCanvas('+maintainAspectRatio+')'); 

    } 

    function FitLayerToCanvas( keepAspect ){// keepAspect:Boolean - optional. Default to false 

        var doc = app.activeDocument; 

        var layer = doc.activeLayer; 

        // do nothing if layer is background or locked 

        if(layer.isBackgroundLayer || layer.allLocked || layer.pixelsLocked 

                                || layer.positionLocked || layer.transparentPixelsLocked ) return; 

        // do nothing if layer is not normal artLayer or Smart Object 

        if( layer.kind != LayerKind.NORMAL && layer.kind != LayerKind.SMARTOBJECT) return; 

        // store the ruler 

        var defaultRulerUnits = app.preferences.rulerUnits; 

        app.preferences.rulerUnits = Units.PIXELS; 

         

        var width = doc.width.as('px'); 

        var height =doc.height.as('px'); 

        var bounds = app.activeDocument.activeLayer.bounds; 

        var layerWidth = bounds[2].as('px')-bounds[0].as('px'); 

        var layerHeight = bounds[3].as('px')-bounds[1].as('px'); 

             

        // move the layer so top left corner matches canvas top left corner 

        layer.translate(new UnitValue(0-layer.bounds[0].as('px'),'px'), new UnitValue(0-layer.bounds[1].as('px'),'px')); 

        if( !keepAspect ){ 

            // scale the layer to match canvas 

            layer.resize( (width/layerWidth)*100,(height/layerHeight)*100,AnchorPosition.TOPLEFT); 

        }else{ 

            var layerRatio = layerWidth / layerHeight; 

            var newWidth = width; 

            var newHeight = ((1.0 * width) / layerRatio); 

            if (newHeight >= height) { 

                newWidth = layerRatio * height; 

                newHeight = height; 

            } 

            var resizePercent = newWidth/layerWidth*100; 

            app.activeDocument.activeLayer.resize(resizePercent,resizePercent,AnchorPosition.TOPLEFT); 

        } 

        // restore the ruler 

        app.preferences.rulerUnits = defaultRulerUnits; 

    } 

This topic has been closed for replies.
Correct answer Stephen Marsh

I just posted this in another topic thread (this code is the opposite, it maintains proportion, the other script code stretches):

 

// FIT LAYER TO CANVAS 
// via https://forums.adobe.com/message/5413957#5413957 
// https://gist.githubusercontent.com/jawinn/ab4df1c33d0743e41fd3/raw/72ff297ae42ed029c86be7644bd021ef4... 
var maintainAspectRatio = true; // set to true to keep aspect ratio, false to stretch/distort to fit   
if (app.documents.length > 0) {
    app.activeDocument.suspendHistory('Fit Layer to Canvas', 'FitLayerToCanvas(' + maintainAspectRatio + ')');
}

function FitLayerToCanvas(keepAspect) { // keepAspect:Boolean - optional. Default to false   
    var doc = app.activeDocument;
    var layer = doc.activeLayer;
    // do nothing if layer is background or locked   
    if (layer.isBackgroundLayer || layer.allLocked || layer.pixelsLocked ||
        layer.positionLocked || layer.transparentPixelsLocked) return;
    // do nothing if layer is not normal artLayer or Smart Object   
    if (layer.kind != LayerKind.NORMAL && layer.kind != LayerKind.SMARTOBJECT) return;
    // store the ruler   
    var defaultRulerUnits = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.PIXELS;

    var width = doc.width.as('px');
    var height = doc.height.as('px');
    var bounds = app.activeDocument.activeLayer.bounds;
    var layerWidth = bounds[2].as('px') - bounds[0].as('px');
    var layerHeight = bounds[3].as('px') - bounds[1].as('px');

    // move the layer so top left corner matches canvas top left corner   
    layer.translate(new UnitValue(0 - layer.bounds[0].as('px'), 'px'), new UnitValue(0 - layer.bounds[1].as('px'), 'px'));
    if (!keepAspect) {
        // scale the layer to match canvas   
        layer.resize((width / layerWidth) * 100, (height / layerHeight) * 100, AnchorPosition.TOPLEFT);
    } else {
        var layerRatio = layerWidth / layerHeight;
        var newWidth = width;
        var newHeight = ((1.0 * width) / layerRatio);
        if (newHeight >= height) {
            newWidth = layerRatio * height;
            newHeight = height;
        }
        var resizePercent = newWidth / layerWidth * 100;
        app.activeDocument.activeLayer.resize(resizePercent, resizePercent, AnchorPosition.TOPLEFT);
    }
    // restore the ruler   
    app.preferences.rulerUnits = defaultRulerUnits;
}

2 replies

schroef
Inspiring
February 1, 2020

Does anyone know how i can reset scale to 100%. Im trying make simple script, but the resize function works with percentage, so simply using 100 doesnt do anything. I cant find the reference for this in the scripting documents. Neither does there exist a simple function "reset scale" or "reset transformation". At least not that i know of

Stephen Marsh
Community Expert
Community Expert
December 17, 2022
quote

Does anyone know how i can reset scale to 100%.


By @schroef

 

@schroef – I know that this is an old post, however, your activity has now brought it to my attention... If you were referring to resetting a smart object transformation:

 

// Reset the SO transform
var idplacedLayerResetTransforms = stringIDToTypeID("placedLayerResetTransforms");
executeAction(idplacedLayerResetTransforms, undefined, DialogModes.NO);
Stephen Marsh
Community Expert
Stephen MarshCommunity ExpertCorrect answer
Community Expert
June 17, 2019

I just posted this in another topic thread (this code is the opposite, it maintains proportion, the other script code stretches):

 

// FIT LAYER TO CANVAS 
// via https://forums.adobe.com/message/5413957#5413957 
// https://gist.githubusercontent.com/jawinn/ab4df1c33d0743e41fd3/raw/72ff297ae42ed029c86be7644bd021ef4... 
var maintainAspectRatio = true; // set to true to keep aspect ratio, false to stretch/distort to fit   
if (app.documents.length > 0) {
    app.activeDocument.suspendHistory('Fit Layer to Canvas', 'FitLayerToCanvas(' + maintainAspectRatio + ')');
}

function FitLayerToCanvas(keepAspect) { // keepAspect:Boolean - optional. Default to false   
    var doc = app.activeDocument;
    var layer = doc.activeLayer;
    // do nothing if layer is background or locked   
    if (layer.isBackgroundLayer || layer.allLocked || layer.pixelsLocked ||
        layer.positionLocked || layer.transparentPixelsLocked) return;
    // do nothing if layer is not normal artLayer or Smart Object   
    if (layer.kind != LayerKind.NORMAL && layer.kind != LayerKind.SMARTOBJECT) return;
    // store the ruler   
    var defaultRulerUnits = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.PIXELS;

    var width = doc.width.as('px');
    var height = doc.height.as('px');
    var bounds = app.activeDocument.activeLayer.bounds;
    var layerWidth = bounds[2].as('px') - bounds[0].as('px');
    var layerHeight = bounds[3].as('px') - bounds[1].as('px');

    // move the layer so top left corner matches canvas top left corner   
    layer.translate(new UnitValue(0 - layer.bounds[0].as('px'), 'px'), new UnitValue(0 - layer.bounds[1].as('px'), 'px'));
    if (!keepAspect) {
        // scale the layer to match canvas   
        layer.resize((width / layerWidth) * 100, (height / layerHeight) * 100, AnchorPosition.TOPLEFT);
    } else {
        var layerRatio = layerWidth / layerHeight;
        var newWidth = width;
        var newHeight = ((1.0 * width) / layerRatio);
        if (newHeight >= height) {
            newWidth = layerRatio * height;
            newHeight = height;
        }
        var resizePercent = newWidth / layerWidth * 100;
        app.activeDocument.activeLayer.resize(resizePercent, resizePercent, AnchorPosition.TOPLEFT);
    }
    // restore the ruler   
    app.preferences.rulerUnits = defaultRulerUnits;
}
June 17, 2019

This is perfect, thank you so much!

schroef
Inspiring
December 17, 2022

Perhaps something like this?

 

#target photoshop

function fitLayer() {

    if (documents.length > 0) {

        // Save the original dialog display
        var originalDialogMode = app.displayDialogs;
        app.displayDialogs = DialogModes.ERROR;
        // Save the original ruler units
        var originalRulerUnits = app.preferences.rulerUnits;
        // Set the working units
        app.preferences.rulerUnits = Units.PIXELS;
        // Save the original resolution
        var originalRes = app.activeDocument.resolution;

        try {

            app.preferences.rulerUnits = Units.PIXELS;

            // Conditional resize layer by portrait or landscape orientation
            if (app.activeDocument.height > app.activeDocument.width) {
                scaleP();
            } else {
                scaleL();
            }

            // Reset the original settings
            app.preferences.rulerUnits = originalRulerUnits;
            app.displayDialogs = originalDialogMode;
            app.activeDocument.resolution = originalRes;

            function scaleP() {
                var iLayer = app.activeDocument.activeLayer;
                app.activeDocument.activeLayer = iLayer;
                var scale = Math.min(app.activeDocument.width / (iLayer.bounds[2] - iLayer.bounds[0]), app.activeDocument.width / (iLayer.bounds[3] - iLayer.bounds[1]));
                // Scale to 90% of canvas
                iLayer.resize(scale * 100, scale * 100);
                // Centre the text layer on canvas
                iLayer.translate(app.activeDocument.width / 2 - (iLayer.bounds[0] + iLayer.bounds[2]) / 2, app.activeDocument.height / 2 - (iLayer.bounds[1] + iLayer.bounds[3]) / 2);
            }

            function scaleL() {
                var iLayer = app.activeDocument.activeLayer;
                app.activeDocument.activeLayer = iLayer;
                var scale = Math.min(app.activeDocument.width / (iLayer.bounds[2] - iLayer.bounds[0]), app.activeDocument.height / (iLayer.bounds[3] - iLayer.bounds[1]));
                // Scale to 90% of canvas
                iLayer.resize(scale * 100, scale * 100);
                // Centre the text layer on canvas
                iLayer.translate(app.activeDocument.width / 2 - (iLayer.bounds[0] + iLayer.bounds[2]) / 2, app.activeDocument.height / 2 - (iLayer.bounds[1] + iLayer.bounds[3]) / 2);
            }

        } catch (e) {
            // Reset the original settings
            app.preferences.rulerUnits = originalRulerUnits;
            app.displayDialogs = originalDialogMode;
            app.activeDocument.resolution = originalRes;

            return;
        }
    }
}

// Create a single history step
app.activeDocument.suspendHistory("Fit Layer Proportionally", "fitLayer()");

Won't the last step cause an error on older illustrator versions? I work with 2018cc at work due to old computer. But it doesn't have the history panel. I think you should then add of statement app.version, not 100% what the exact code is, but i know we can get the app version somehow