Created
August 14, 2017 12:15
-
-
Save phloe/f1b70ce07a89867fbe49923f292c1288 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import URL from "url-parse"; | |
import ratioHelper from "./ratioHelper"; | |
import { quantize, interpolate, normalize, clamp } from "./math"; | |
var dprMin = 1; // min dpr to get highest quality | |
var dprMax = 2; // max dpr to get lowest quality | |
var dprRanges = [ | |
/*{ | |
min: 3, | |
quality: getQuality(3) | |
},*/ | |
{ | |
min: 2, | |
//max: 3, | |
quality: getQuality(2) | |
}, | |
// default dpr (below 2) setting | |
{ | |
quality: qualityMax | |
} | |
]; | |
export const defaultWidths = [120, 240, 360, 720, 1080, 1440, 1800, 2160, 2520]; | |
export const ratios = ratioHelper(["16-9", "4-3", "3-2", "2-1", "1-1", "3-4"]); | |
function prefixMediaDpr (media) { | |
var result = [media]; | |
var mdprReg = /(\()(min|max)-resolution(: \d+(?:\.\d*)?)dppx/g; | |
["$1-webkit-$2-device-pixel-ratio$3", "$1$2-device-pixel-ratio$3"].forEach( | |
(pattern) => { | |
var prefixed = media.replace(mdprReg, pattern); | |
if (prefixed !== media) { | |
result.unshift(prefixed); | |
} | |
} | |
); | |
return result.join(", "); | |
} | |
function mediaDpr (media, dprMin, dprMax) { | |
var result = []; | |
if (media) { | |
result.push(media); | |
} | |
if (dprMin) { | |
result.push(`(min-resolution: ${dprMin}dppx)`); | |
} | |
if (dprMax) { | |
result.push(`(max-resolution: ${dprMax}dppx)`); | |
} | |
return prefixMediaDpr(result.join(" and ")); | |
} | |
function expandDprRanges (result, media, params, sizes, widths) { | |
dprRanges.forEach( | |
({min, max, quality}, index) => { | |
const srcSet = prescaleSrcSet(params, min, quality, widths); | |
result.push({ | |
media: mediaDpr(media, min, max), | |
sizes, | |
srcSet | |
}); | |
} | |
); | |
} | |
export function sourcePropsFromMediaSizes (params, mediaSizes = { default: "" }, widths) { | |
var propSet = []; | |
Object.entries(mediaSizes).reduce( | |
(result, [media, sizes]) => { | |
if (media !== "default") { | |
expandDprRanges(result, media, params, sizes, widths); | |
} | |
return result; | |
}, | |
propSet | |
); | |
expandDprRanges(propSet, null, params, mediaSizes.default, widths); | |
return propSet; | |
} | |
export function responsiveSources (url, w, h, ratioLabel, mediaSizes, widths = defaultWidths) { | |
if (/\.(png|gif)$/.test(url)) { | |
return { | |
src: url, | |
sources: [] | |
}; | |
} | |
var params = getParams(url, w, h, ratioLabel); | |
return { | |
src: scalerUrl({...params, w: 640, h: null}), | |
sources: sourcePropsFromMediaSizes(params, mediaSizes, widths) | |
}; | |
} | |
export function getParams (url, w, h, ratioLabel) { | |
ratioLabel = ratioLabel || (w && h ? ratios.getLabelFromSize(w, h) : null); | |
return { url, w, h, ratio: ratioLabel }; | |
} | |
export function prescaleSrcSet (params, dpr, quality, widths) { | |
return widths.reduce( | |
(result, size, index) => { | |
var _size = (dpr > 1) ? Math.round(size * dpr) : size; | |
// always output first width | |
// always output if no width was provided | |
// else only output if needed size is smaller than/equal source | |
if (!index || !params.w || _size <= params.w ) { | |
var _params = { | |
...params, | |
quality, | |
w: _size, | |
h: (params.h) ? Math.round(params.h * (_size / params.w)) : null | |
}; | |
result.push(`${scalerUrl(_params)} ${_size}w`); | |
} | |
return result; | |
}, | |
[] | |
).join(", "); | |
} | |
/* | |
{ | |
"(min-width: 640px)": { | |
"1x": "image.jpg 240w, image_640.jpg 640w", | |
"2x": "image_480.jpg 480w, image_1280.jpg 1280w" | |
}, | |
"default": { | |
"1x": "image.jpg 240w, image_640.jpg 640w" | |
} | |
} | |
*/ | |
export default function (data) { | |
if (typeof data === "string") { | |
return [{ | |
srcSet: data | |
}]; | |
} | |
return Object.entries(data).reduce( | |
(result, [media, mediaData]) => { | |
var source = {}; | |
if (typeof mediaData === "string") { | |
if (media !== "default") { | |
source.media = media; | |
} | |
source.srcSet = mediaData; | |
result.push(source); | |
} | |
else { | |
var dprs = Object.keys(mediaData).map( | |
(dpr) => parseFloat(dpr, 10) | |
).sort().reverse(); | |
} | |
return result; | |
}, | |
[] | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment