Skip to content

Commit

Permalink
feat: implement blurred and background colour placeholders for gatsby…
Browse files Browse the repository at this point in the history
…ImageData
  • Loading branch information
frederickfogerty committed Mar 8, 2021
1 parent e7c1264 commit d51935c
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 31 deletions.
37 changes: 36 additions & 1 deletion src/api/fetchBase64Image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const buildBase64URL = (contentType: string, base64: string): string =>
export const fetchImgixBase64Image = (cache: GatsbyCache) => (
url: string,
): TE.TaskEither<Error, string> =>
withCache(`gatsby-plugin-imgix-base64-url-${url}`, cache, () =>
withCache(`imgix-gatsby-base64-url-${url}`, cache, () =>
pipe(
url,
fetch,
Expand All @@ -27,3 +27,38 @@ export const fetchImgixBase64Image = (cache: GatsbyCache) => (
),
),
);

export type HexString = string;
type ImgixPaletteResponse = {
dominant_colors: {
vibrant: {
/**
* In format '#xxxxxx'
*/
hex: string;
};
};
};

export const fetchImgixDominantColor = (cache: GatsbyCache) => (
buildURL: (params: Record<string, unknown>) => string,
): TE.TaskEither<Error, HexString> =>
pipe(buildURL({ palette: 'json' }), (url) =>
withCache(`imgix-gatsby-dominant-color-${url}`, cache, () =>
pipe(
url,
fetch,
TE.chain((res) =>
TE.tryCatch<Error, ImgixPaletteResponse>(
() => res.json(),
(err) =>
new Error(
'Something went wrong while decoding the dominant color for the placeholder image: ' +
String(err),
),
),
),
TE.map((data) => data.dominant_colors.vibrant.hex),
),
),
);
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import { GatsbyCache } from 'gatsby';
import { FluidObject } from 'gatsby-image';
import {
generateImageData,
getLowResolutionImageURL,
IGatsbyImageData,
IGatsbyImageHelperArgs,
ImageFormat,
} from 'gatsby-plugin-image';
import { getGatsbyImageFieldConfig } from 'gatsby-plugin-image/graphql-utils';
import {
Expand All @@ -20,25 +22,20 @@ import {
} from 'gatsby/graphql';
import ImgixClient from 'imgix-core-js';
import R from 'ramda';
import {
fetchImgixBase64Image,
fetchImgixDominantColor,
} from '../../api/fetchBase64Image';
import { TaskOptionFromTE } from '../../common/fpTsUtils';
import {
ImgixSourceDataResolver,
resolveUrlFromSourceData,
taskEitherFromSourceDataResolver,
} from '../../common/utils';
import { IImgixParams } from '../../publicTypes';
import { ImgixParamsInputType } from './graphqlTypes';
import { ImgixParamsInputType, ImgixPlaceholderType } from './graphqlTypes';
import { resolveDimensions } from './resolveDimensions';

/* const fitMap = {
cover: ,
contain: ,
fill: ,
inside: ,
outside: ,
} */

const generateImageSource = (
client: ImgixClient,
): IGatsbyImageHelperArgs['generateImageSource'] => (
Expand Down Expand Up @@ -99,27 +96,58 @@ const resolveGatsbyImageData = <TSource>({
client: imgixClient,
}),
)
.return(({ url, dimensions: { width, height } }) =>
generateImageData({
...args,
pluginName: `@imgix/gatsby`,
filename: url,
sourceMetadata: { width, height, format: 'auto' },
// placeholderURL: await getBase64Image({ baseUrl }),
// TODO: not a public API, need to replace with public API when implemented
breakpoints:
args.breakpoints ??
(imgixClient as any)._generateTargetWidths(
args.widthTolerance,
args.srcSetMinWidth,
args.srcSetMaxWidth,
.letL(
'baseImageDataArgs',
({ url, dimensions: { width, height } }) =>
({
...args,
pluginName: `@imgix/gatsby`,
filename: url,
sourceMetadata: { width, height, format: 'auto' as ImageFormat },
// TODO: not a public API, need to replace with public API when implemented
breakpoints:
args.breakpoints ??
(imgixClient as any)._generateTargetWidths(
args.widthTolerance,
args.srcSetMinWidth,
args.srcSetMaxWidth,
),
formats: ['auto'] as ImageFormat[],
generateImageSource: generateImageSource(imgixClient),
// TODO: check if this should be set to imgixParams
options: args,
} as const),
)
.bindL('placeholderData', ({ url, baseImageDataArgs }) => {
console.log('args.placeholder', args.placeholder);
if (args.placeholder === 'blurred') {
return pipe(
getLowResolutionImageURL(baseImageDataArgs),
fetchImgixBase64Image(cache),
TE.map((base64Data) => ({
placeholder: { fallback: base64Data },
})),
);
}
if (args.placeholder === 'dominantColor') {
return pipe(
// TODO: add imgix params
fetchImgixDominantColor(cache)((params) =>
imgixClient.buildURL(url, params),
),
// breakpoints
formats: ['auto'],
generateImageSource: generateImageSource(imgixClient),
options: args,
TE.map((dominantColor) => ({
backgroundColor: dominantColor,
})),
);
}
return TE.right({});
})
.return(({ baseImageDataArgs, placeholderData }) => ({
...generateImageData({
...baseImageDataArgs,
}),
),
...placeholderData,
})),
TE.getOrElseW(() => T.of(undefined)),
)();
};
Expand Down Expand Up @@ -167,6 +195,14 @@ export const createImgixGatsbyImageFieldConfig = <TSource, TContext = {}>({
All of imgix's parameters can be found here: https://docs.imgix.com/apis/rendering
`,
},
placeholder: {
type: ImgixPlaceholderType,
description: stripIndent`
Format of generated placeholder image, displayed while the main image loads.
BLURRED: a blurred, low resolution image, encoded as a base64 data URI (default)
DOMINANT_COLOR: a solid color, calculated from the dominant color of the image.
NONE: no placeholder. Set "backgroundColor" to use a fixed background color.`,
},
widthTolerance: {
type: GraphQLFloat,
description: stripIndent`
Expand All @@ -189,7 +225,6 @@ export const createImgixGatsbyImageFieldConfig = <TSource, TContext = {}>({
`,
defaultValue: 8192,
},
// TODO: add placeholder
},
};

Expand Down
9 changes: 9 additions & 0 deletions src/modules/gatsby-source-url/graphqlTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,12 @@ export const unTransformParams = <T>(

export type IGatsbySourceImgixUrlField = string;
export const gatsbySourceImgixUrlFieldType = GraphQLString;

export const ImgixPlaceholderType = new GraphQLEnumType({
name: `ImgixPlaceholder`,
values: {
DOMINANT_COLOR: { value: `dominantColor` },
BLURRED: { value: `blurred` },
NONE: { value: `none` },
},
});

0 comments on commit d51935c

Please sign in to comment.