responsive-image-utils
Version:
Utility functions to make it easier to work with auto generated responsive images for better performance optimised images.
161 lines (151 loc) • 6.46 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = global || self, factory(global.responsiveImageUtils = {}));
}(this, function (exports) { 'use strict';
/** Default media query values */
var MediaQueriesDefault = {
s: 640,
m: 1024,
l: 1280,
xl: 1920,
xxl: 2560,
};
/**
* Use this to auto calculate various image sizes based on your media query breakpoints and fluid image sizes using VW
*
* @param sizes - key/value pair of media query and image size {s: '50vw', l: '25vw', xl: '500px'}
* @param mediaQueries - Optional. key/value pair of media query breakpoints. Defaults to MediaQueriesDefault
* @returns Number array of generated image sizes
*
*/
function getSrcsetSizes(sizes, mediaQueries) {
if (mediaQueries === void 0) { mediaQueries = MediaQueriesDefault; }
var prevSize = '100vw';
var getSizePerMediaQuery = Object.keys(mediaQueries).map(function (key) {
var _a;
var currentSize = sizes[key] ? sizes[key] : prevSize;
prevSize = currentSize;
return _a = {},
_a[key] = currentSize,
_a;
});
var srcSets = getSizePerMediaQuery.map(function (sizeObj) {
var key = Object.keys(sizeObj)[0];
var sizeValue = sizeObj[key];
var unit = sizeValue.slice(-2);
var mediaQuery = parseInt(sizeValue.replace(unit, ''), 10);
if (unit !== 'px' && unit !== 'vw') {
throw new Error(unit + " unit is not supported. Only supports px & vw");
}
return unit === 'px' ? mediaQuery : Math.round((mediaQueries[key] * mediaQuery) / 100);
});
return Array.from(new Set(srcSets)).sort(function (a, b) { return a - b; });
}
/**
* Use this to generate retina sizes for your sizes
*
* @param sizesArr - array of numbers [320, 640, 1024, 2048]
* @param [multiplier] - number to multiply the images by, you can provide multiples getRetinaSizes(array, 2, 3, 4)
* @returns Number array of generated image sizes
*
*/
function getRetinaSizes(sizesArr) {
var multiplier = [];
for (var _i = 1; _i < arguments.length; _i++) {
multiplier[_i - 1] = arguments[_i];
}
var newSizes = multiplier
.map(function (n) { return sizesArr.slice(0).map(function (size) { return size * n; }); })
.reduce(function (prev, curr) { return prev.concat(curr); }, sizesArr);
return Array.from(new Set(newSizes));
}
/**
* Use this to limit the number of image sizes provided to the browser.
* This will automatically choose every Nth image to ensure image sizes are not so close to each other
*
* @param max - the maximum number of sizes
* @param sizesArr - array of numbers [320, 640, 1024, 2048]
* @returns Number array of generated image sizes
*
*/
function getMaxNumOfSizes(sizesArr, max) {
if (max > sizesArr.length) {
throw new Error('Max is greater than sizes length!');
}
var ascSizes = sizesArr.sort(function (a, b) { return a - b; });
return Array(max)
.fill(0)
.map(function (n, i) {
var index = ascSizes.length - i * Math.ceil(ascSizes.length / max);
if (index < 1) {
return i * Math.ceil(ascSizes.length / max) - ascSizes.length + 1;
}
return index;
})
.map(function (n) { return ascSizes[n - 1]; })
.sort(function (a, b) { return a - b; });
}
/**
* Use this to combine your media queries and sizes to generate a string to populate your image tag
*
* @param sizes - key/value pair of media query and image size {s: '50vw', l: '25vw', xl: '500px'}
* @param mediaQueries - Optional. key/value pair of media query breakpoints. Defaults to MediaQueriesDefault
* @returns String array of generated string sizes
*
*/
function getImgSizeStrings(sizes, mediaQueries) {
if (mediaQueries === void 0) { mediaQueries = MediaQueriesDefault; }
var mediaQueriesMinWidth = function () {
var prevKey = '';
return Object.keys(mediaQueries)
.map(function (key) {
var _a;
var currentMinWidth = mediaQueries[prevKey] ? mediaQueries[prevKey] + 1 : 0;
prevKey = key;
return _a = {},
_a[key] = currentMinWidth,
_a;
})
.reduce(function (prev, curr) { return Object.assign(prev, curr); }, {});
};
return Object.keys(sizes)
.map(function (sizeKey) {
if (mediaQueriesMinWidth()[sizeKey] === 0) {
return sizes[sizeKey];
}
return "(min-width:" + mediaQueriesMinWidth()[sizeKey] + "px) " + sizes[sizeKey];
})
.reverse();
}
/**
* You can use *getSizesWithInterval* which will take N results from the set
* without the sizes being too close to each other.
* For example, if you have the following sizes `[300, 320, 460, 480, 1024]`,
* you might want to remove `300` & `460` since the 20px difference with the
* next size up has marginal benefit over page weight
*
* @param sizesArr - array of numbers [320, 640, 1024, 2048]
* @param interval - how much interval should each size have from each other
* @returns Number array of generated image sizes
*
*/
function getSizesWithInterval(sizesArr, interval) {
return sizesArr
.sort(function (a, b) { return b - a; })
.reduce(function (accumulator, current) {
if (accumulator[accumulator.length - 1] - current < interval) {
return accumulator;
}
return accumulator.concat([current]);
}, [])
.sort(function (a, b) { return a - b; });
}
exports.getMaxNumOfSizes = getMaxNumOfSizes;
exports.getRetinaSizes = getRetinaSizes;
exports.getImgSizeStrings = getImgSizeStrings;
exports.getSrcsetSizes = getSrcsetSizes;
exports.getSizesWithInterval = getSizesWithInterval;
Object.defineProperty(exports, '__esModule', { value: true });
}));
//# sourceMappingURL=responsive-image-utils.umd.js.map