feat: Add aspect ratio support to imgproxy loader and apply 16:9 aspect ratio to featured images across blog posts and recent posts.
This commit is contained in:
@@ -76,7 +76,7 @@ export default async function BlogPost({ params }: BlogPostProps) {
|
|||||||
<div className="relative w-full h-[70vh] min-h-[500px] overflow-hidden group">
|
<div className="relative w-full h-[70vh] min-h-[500px] overflow-hidden group">
|
||||||
<div className="absolute inset-0 transition-transform duration-[3s] ease-out scale-110 group-hover:scale-100">
|
<div className="absolute inset-0 transition-transform duration-[3s] ease-out scale-110 group-hover:scale-100">
|
||||||
<Image
|
<Image
|
||||||
src={post.frontmatter.featuredImage}
|
src={`${post.frontmatter.featuredImage}?ar=16:9`}
|
||||||
alt={post.frontmatter.title}
|
alt={post.frontmatter.title}
|
||||||
fill
|
fill
|
||||||
priority
|
priority
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export default function PostNavigation({
|
|||||||
{prev.frontmatter.featuredImage ? (
|
{prev.frontmatter.featuredImage ? (
|
||||||
<div
|
<div
|
||||||
className="absolute inset-0 bg-cover bg-center transition-transform duration-700 group-hover:scale-110"
|
className="absolute inset-0 bg-cover bg-center transition-transform duration-700 group-hover:scale-110"
|
||||||
style={{ backgroundImage: `url(${prev.frontmatter.featuredImage})` }}
|
style={{ backgroundImage: `url(${prev.frontmatter.featuredImage}?ar=16:9)` }}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="absolute inset-0 bg-neutral-100" />
|
<div className="absolute inset-0 bg-neutral-100" />
|
||||||
@@ -82,7 +82,7 @@ export default function PostNavigation({
|
|||||||
{next.frontmatter.featuredImage ? (
|
{next.frontmatter.featuredImage ? (
|
||||||
<div
|
<div
|
||||||
className="absolute inset-0 bg-cover bg-center transition-transform duration-700 group-hover:scale-110"
|
className="absolute inset-0 bg-cover bg-center transition-transform duration-700 group-hover:scale-110"
|
||||||
style={{ backgroundImage: `url(${next.frontmatter.featuredImage})` }}
|
style={{ backgroundImage: `url(${next.frontmatter.featuredImage}?ar=16:9)` }}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="absolute inset-0 bg-neutral-100" />
|
<div className="absolute inset-0 bg-neutral-100" />
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export default async function RecentPosts({ locale }: RecentPostsProps) {
|
|||||||
{post.frontmatter.featuredImage && (
|
{post.frontmatter.featuredImage && (
|
||||||
<div className="relative h-64 overflow-hidden">
|
<div className="relative h-64 overflow-hidden">
|
||||||
<Image
|
<Image
|
||||||
src={post.frontmatter.featuredImage}
|
src={`${post.frontmatter.featuredImage}?ar=16:9`}
|
||||||
alt={post.frontmatter.title}
|
alt={post.frontmatter.title}
|
||||||
fill
|
fill
|
||||||
className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110"
|
className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110"
|
||||||
|
|||||||
@@ -23,17 +23,37 @@ export default function imgproxyLoader({
|
|||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if src contains custom gravity query parameter
|
// Check if src contains custom gravity or aspect ratio query parameters
|
||||||
let gravity = 'sm'; // Use smart gravity (content-aware) by default
|
let gravity = 'sm'; // Use smart gravity (content-aware) by default
|
||||||
let cleanSrc = src;
|
let cleanSrc = src;
|
||||||
|
let calculatedHeight = 0;
|
||||||
|
let resizingType: 'fit' | 'fill' = 'fit';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Dummy base needed for relative URLs
|
// Dummy base needed for relative URLs
|
||||||
const url = new URL(src, 'http://localhost');
|
const url = new URL(src, 'http://localhost');
|
||||||
const customGravity = url.searchParams.get('gravity');
|
const customGravity = url.searchParams.get('gravity');
|
||||||
|
const aspectRatio = url.searchParams.get('ar'); // e.g. "16:9"
|
||||||
|
|
||||||
if (customGravity) {
|
if (customGravity) {
|
||||||
gravity = customGravity;
|
gravity = customGravity;
|
||||||
url.searchParams.delete('gravity');
|
url.searchParams.delete('gravity');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aspectRatio) {
|
||||||
|
const parts = aspectRatio.split(':');
|
||||||
|
if (parts.length === 2) {
|
||||||
|
const arW = parseFloat(parts[0]);
|
||||||
|
const arH = parseFloat(parts[1]);
|
||||||
|
if (!isNaN(arW) && !isNaN(arH) && arW > 0) {
|
||||||
|
calculatedHeight = Math.round(width * (arH / arW));
|
||||||
|
resizingType = 'fill'; // Must use fill to allow imgproxy to crop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
url.searchParams.delete('ar');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (customGravity || aspectRatio) {
|
||||||
cleanSrc = src.startsWith('http') ? url.href : url.pathname + url.search;
|
cleanSrc = src.startsWith('http') ? url.href : url.pathname + url.search;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -41,10 +61,11 @@ export default function imgproxyLoader({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We use the width provided by Next.js for responsive images
|
// We use the width provided by Next.js for responsive images
|
||||||
// Height is set to 0 to maintain aspect ratio
|
// Height is calculated from aspect ratio if provided, otherwise 0 to maintain aspect ratio
|
||||||
return getImgproxyUrl(cleanSrc, {
|
return getImgproxyUrl(cleanSrc, {
|
||||||
width,
|
width,
|
||||||
resizing_type: 'fit',
|
height: calculatedHeight,
|
||||||
|
resizing_type: resizingType,
|
||||||
gravity,
|
gravity,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user