Skip to content

Commit

Permalink
Quick and dirty way to support different aspectratios per breakpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisRAoW committed Nov 3, 2024
1 parent 488dd8b commit c7c573f
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 19 deletions.
49 changes: 32 additions & 17 deletions src/Helpers/ImageHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ final class ImageHelper

/**
* @param int|int[] $attachmentIds
* @param array{url?: string, class?: string, loading?: string, alt?: string, sizes?: string[], aspectRatio?: string, lightbox?: bool, containedMaxWidth?: string|int|float} $args
* @param array{url?: string, class?: string, loading?: string, alt?: string, sizes?: string[], aspectRatio?: string|array, lightbox?: bool, containedMaxWidth?: string|int|float} $args
*/
public function generateResponsiveImage(int|array $attachmentIds, array $args = []): string
{
Expand Down Expand Up @@ -59,7 +59,7 @@ public function generateResponsiveImage(int|array $attachmentIds, array $args =
}

// Generate image tags
$breakpoints = $this->generateBreakpoints($attachmentIds, $sizes, $containedMaxWidth);
$breakpoints = $this->generateBreakpoints($attachmentIds, $sizes, $containedMaxWidth, !is_array($aspectRatio) ? [0 => $aspectRatio] : $aspectRatio);

$sources = $this->generateSources($breakpoints, $aspectRatio);

Expand All @@ -85,18 +85,19 @@ private function cleanSizes(iterable $array): array
* @param array<int, string> $imageSizes
* @return array<int, BreakPoint> An array of strings with pixel values. EG: '42px'
*/
protected function generateBreakpoints(array $attachmentIds, array $imageSizes, string|int $containedMaxWidth): array
protected function generateBreakpoints(array $attachmentIds, array $imageSizes, string|int $containedMaxWidth, array $aspectRatios): array
{
// Combine breakpoints of attachmentIds and imageSizes
/** @var int[] $breakpointWidths */
$breakpointWidths = array_unique([...array_keys($imageSizes), ...array_keys($attachmentIds)]);
$breakpointWidths = array_unique([...array_keys($imageSizes), ...array_keys($attachmentIds), ...array_keys($aspectRatios)]);

// Sort sizes by key (breakpoints)
sort($breakpointWidths);

$breakpoints = [];
$imageSize = '100%';
$imageId = 0;
$aspectRatio = null;

foreach ($breakpointWidths as $breakpointWidth) {
if (array_key_exists($breakpointWidth, $imageSizes)) {
Expand All @@ -107,6 +108,10 @@ protected function generateBreakpoints(array $attachmentIds, array $imageSizes,
$imageId = $attachmentIds[$breakpointWidth];
}

if (array_key_exists($breakpointWidth, $aspectRatios)) {
$aspectRatio = $aspectRatios[$breakpointWidth];
}

$nextBreakpointWidth = $this->getNextKey($imageSizes, $breakpointWidth);

// Check if the size needs to be calculate based on a percentage
Expand Down Expand Up @@ -135,7 +140,7 @@ protected function generateBreakpoints(array $attachmentIds, array $imageSizes,
}

if ($imageWidth) {
$breakpoints[$breakpointWidth] = new BreakPoint($imageId, $imageWidth);
$breakpoints[$breakpointWidth] = new BreakPoint($imageId, $imageWidth, $aspectRatio);
}

// in two cases we add an extra size:
Expand All @@ -149,7 +154,7 @@ protected function generateBreakpoints(array $attachmentIds, array $imageSizes,
(!$nextBreakpointWidth && $breakpointWidth < $containedMaxWidth)
)
) {
$breakpoints[$containedMaxWidth] = new BreakPoint($imageId, ceil($containedMaxWidth * ($percentage / 100)) . 'px');
$breakpoints[$containedMaxWidth] = new BreakPoint($imageId, ceil($containedMaxWidth * ($percentage / 100)) . 'px', $aspectRatio);
}
}

Expand Down Expand Up @@ -288,9 +293,10 @@ public function generateSrcSet(int $attachmentId, array $sizes, string|float|int

/**
* @param array<int, BreakPoint> $breakpoints
* @param ?string|array $aspectRatio
* @return array{sizes: string[]|null[], media_query: string, srcset?: string[]}[]
*/
protected function generateSources(array $breakpoints, ?string $aspectRatio): array
protected function generateSources(array $breakpoints, $aspectRatio): array
{
$sources = [];
$sourceSizes = [];
Expand All @@ -305,9 +311,9 @@ protected function generateSources(array $breakpoints, ?string $aspectRatio): ar

// We are going to group the relative sources in source. So if current and next is
// a relative width, we're going to skip it.
if ($breakpoint->getAttachmentId() === $nextBreakpoint?->getAttachmentId() && $breakpoint->getUnit() === 'vw' && $nextBreakpoint->getUnit() === 'vw') {
continue;
}
// if ($breakpoint->getAttachmentId() === $nextBreakpoint?->getAttachmentId() && $breakpoint->getUnit() === 'vw' && $nextBreakpoint->getUnit() === 'vw') {
// continue;
// }

// If there is a next breakpoint use that as max-width, otherwise use min-width
if ($nextBreakpointWidth) {
Expand All @@ -318,22 +324,25 @@ protected function generateSources(array $breakpoints, ?string $aspectRatio): ar

// If current width is relative, and the next one is absolute (or there is no next)
// we going to define the source.
if ($breakpoint->getUnit() === 'vw' && (!$nextBreakpoint || $nextBreakpoint->getUnit() === 'px' || $breakpoint->getAttachmentId() !== $nextBreakpoint->getAttachmentId())) {

$srcsetAspectRatio = $breakpoint->getAspectRatio() ?? (is_array($aspectRatio) ? end($aspectRatio) : $aspectRatio);

if ($breakpoint->getUnit() === 'vw' && (!$nextBreakpoint || $nextBreakpoint->getUnit() === 'px' || $breakpoint->getAttachmentId() !== $nextBreakpoint->getAttachmentId() || $breakpoint->getAspectRatio() !== $nextBreakpoint->getAspectRatio())) {
if ($nextBreakpointWidth) {
$sourceSizes[$nextBreakpointWidth] = null;
}

$source['sizes'] = $sourceSizes;
$source['srcset'] = $this->generateSrcSet($breakpoint->getAttachmentId(), $sourceSizes, $aspectRatio);
$source['srcset'] = $this->generateSrcSet($breakpoint->getAttachmentId(), $sourceSizes, $srcsetAspectRatio);

$sources[] = $source;

continue;
}

// Absolute definitions will width a more strict srcset (defining pixel density images)
if ($breakpoint->getUnit() === 'px' || $breakpoint->getAttachmentId() !== $nextBreakpoint->getAttachmentId()) {
$source['srcset'] = $this->generateSrcSet($breakpoint->getAttachmentId(), [$breakpoint->getWidth()], $aspectRatio, true);
if ($breakpoint->getUnit() === 'px' || $breakpoint->getAttachmentId() !== $nextBreakpoint->getAttachmentId() || $breakpoint->getAspectRatio() !== $nextBreakpoint->getAspectRatio()) {
$source['srcset'] = $this->generateSrcSet($breakpoint->getAttachmentId(), [$breakpoint->getWidth()], $srcsetAspectRatio, true);

$sources[] = $source;
}
Expand All @@ -342,6 +351,12 @@ protected function generateSources(array $breakpoints, ?string $aspectRatio): ar
return $sources;
}

public function getAspectRatioByBreakpoint(array $aspectRatio, $breakpointWidth) {
var_dump("PINO", $breakpointWidth);

return current($aspectRatio);
}

/**
* @pure
* @param array<int, string|null> $sizes
Expand Down Expand Up @@ -400,9 +415,9 @@ protected function generateResponsiveImageTag(int $fallbackAttachmentId, array $
$styles[] = 'object-fit: ' . $objectFit;
}

if ($aspectRatio) {
$styles[] = 'aspect-ratio: ' . $aspectRatio;
}
// if ($aspectRatio) {
// $styles[] = 'aspect-ratio: ' . $aspectRatio;
// }

$fallbackImage = offbeat('images')->getMaxImage($fallbackAttachmentId, $aspectRatio);

Expand Down
8 changes: 7 additions & 1 deletion src/Objects/BreakPoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ final class BreakPoint
private int $attachmentId;
private string $width;
private string $unit;
private $aspectRatio;

public function __construct(int $attachmentId, string $width)
public function __construct(int $attachmentId, string $width, $aspectRatio = null)
{
$this->attachmentId = $attachmentId;
$this->width = $width;
$this->unit = str_ends_with($this->width, 'vw') ? 'vw' : 'px';
$this->aspectRatio = $aspectRatio;
}

public function getAttachmentId(): int
Expand All @@ -30,4 +32,8 @@ public function getUnit(): string
{
return $this->unit;
}
public function getAspectRatio(): ?string
{
return $this->aspectRatio;
}
}
9 changes: 8 additions & 1 deletion src/Repositories/ImagesRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,14 @@ public function getMaxImage(int $attachmentId, $aspectRatio = null): ?array
$maxImageHeight = $this->getOriginalImageHeight($attachmentId);

if ($aspectRatio) {
$maxImageHeight = floor($fullImageMeta['width'] / ImageHelper::calculateAspectRatio($aspectRatio, $attachmentId));
$aspectRatioForCalculation = $aspectRatio;

if (is_array($aspectRatio)) {
ksort($aspectRatio);
$aspectRatioForCalculation = end($aspectRatio);
}

$maxImageHeight = floor($fullImageMeta['width'] / ImageHelper::calculateAspectRatio($aspectRatioForCalculation, $attachmentId));

if ($maxImageHeight > $fullImageMeta['height']) {
$maxImageWidth = floor($fullImageMeta['width'] * ($fullImageMeta['height'] / $maxImageHeight));
Expand Down

0 comments on commit c7c573f

Please sign in to comment.