feat(image): enhance image handling with focal points and responsive support
- Added support for extracting focal points and alt text from CMS image fields. - Introduced responsive image handling in TopBanner component, allowing for AVIF/WebP sources and LQIP placeholders. - Updated image transformation functions to accommodate focal point parameters for better cropping. - Refactored image URL resolution logic across various components and routes to utilize new image field structure.
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
import type { PageServerLoad } from './$types';
|
||||
import { getPageBySlug } from '$lib/cms';
|
||||
import { resolveContentImages, resolveImageUrls } from '$lib/rusty-image';
|
||||
import {
|
||||
extractCmsImageField,
|
||||
resolveContentImages,
|
||||
resolveImageUrls,
|
||||
} from '$lib/rusty-image';
|
||||
import { buildResponsiveImage, type ResponsiveImage } from '$lib/rusty-image.server';
|
||||
import {
|
||||
resolvePostOverviewBlocks,
|
||||
resolveSearchableTextBlocks,
|
||||
@@ -9,6 +14,13 @@ import {
|
||||
import { PAGE_RESOLVE } from '$lib/constants';
|
||||
import { error } from '@sveltejs/kit';
|
||||
|
||||
const BANNER_WIDTHS = [640, 960, 1280, 1600, 1920, 2400];
|
||||
|
||||
function focalToCss(focal: { x: number; y: number } | undefined): string | null {
|
||||
if (!focal) return null;
|
||||
return `${(focal.x * 100).toFixed(2)}% ${(focal.y * 100).toFixed(2)}%`;
|
||||
}
|
||||
|
||||
export const load: PageServerLoad = async ({ params, locals }) => {
|
||||
const { slug } = params;
|
||||
const translations = locals.translations ?? {};
|
||||
@@ -29,6 +41,8 @@ export const load: PageServerLoad = async ({ params, locals }) => {
|
||||
|
||||
// Resolve top banner if present
|
||||
let topBannerResolvedImages: string[] = [];
|
||||
let topBannerResponsive: ResponsiveImage | null = null;
|
||||
let topBannerFocalCss: string | null = null;
|
||||
const bannerRaw = (page as { topFullwidthBanner?: unknown }).topFullwidthBanner;
|
||||
if (bannerRaw && typeof bannerRaw === 'object' && 'image' in bannerRaw) {
|
||||
const bannerImages = Array.isArray((bannerRaw as { image?: unknown }).image)
|
||||
@@ -37,6 +51,17 @@ export const load: PageServerLoad = async ({ params, locals }) => {
|
||||
? [(bannerRaw as { image?: unknown }).image]
|
||||
: [];
|
||||
if (bannerImages.length > 0) {
|
||||
const primary = extractCmsImageField(bannerImages[0]);
|
||||
if (primary?.url) {
|
||||
topBannerFocalCss = focalToCss(primary.focal);
|
||||
topBannerResponsive = await buildResponsiveImage(primary.url, {
|
||||
widths: BANNER_WIDTHS,
|
||||
fit: 'contain',
|
||||
formats: ['avif', 'webp', 'jpeg'],
|
||||
quality: 78,
|
||||
focal: primary.focal,
|
||||
});
|
||||
}
|
||||
topBannerResolvedImages = await resolveImageUrls(bannerImages as string[], {
|
||||
width: 2000,
|
||||
height: 750,
|
||||
@@ -59,6 +84,8 @@ export const load: PageServerLoad = async ({ params, locals }) => {
|
||||
? {
|
||||
banner: bannerRaw as import('$lib/cms').FullwidthBannerEntry | null,
|
||||
resolvedImages: topBannerResolvedImages,
|
||||
responsive: topBannerResponsive,
|
||||
focalCss: topBannerFocalCss,
|
||||
headline: page.headline ?? undefined,
|
||||
subheadline: page.subheadline ?? undefined,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user