Last active
March 1, 2021 04:18
-
-
Save pryley/277b4ab275cd538168fb759471ab7e2c to your computer and use it in GitHub Desktop.
ImageKit job for the Responsive Images Statamic addon (https://statamic.com/addons/spatie/responsive-images)
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
<?php | |
namespace App\Jobs; | |
use Illuminate\Support\Arr; | |
use Illuminate\Support\Collection; | |
use Spatie\ResponsiveImages\Jobs\GenerateImageJob; | |
class GenerateImageKitJob extends GenerateImageJob | |
{ | |
protected $image; | |
protected $height; | |
protected $width; | |
protected $transforms; | |
protected function crop(): void | |
{ | |
$this->transforms['crop'] = [ | |
'cm' => 'extract', | |
'h' => $this->resizedHeight(), | |
'w' => $this->resizedWidth(), | |
'x' => $this->resizedX() - $this->zoomedX(), | |
'y' => $this->resizedY() - $this->zoomedY(), | |
]; | |
} | |
protected function cropResized(): void | |
{ | |
$height = $this->resizedHeight(); | |
$width = $this->resizedWidth(); | |
$cx = ($this->image->get('width') * ($this->image->get('cx_percent') / 100)) - $this->zoomedX(); | |
$cy = ($this->image->get('height') * ($this->image->get('cy_percent') / 100)) - $this->zoomedY(); | |
$x = $cx - ($width / 2); | |
$y = $cy - ($height / 2); | |
$this->transforms['crop_resized'] = [ | |
'cm' => 'extract', | |
'h' => $height, | |
'w' => $width, | |
'x' => $x, | |
'y' => $y, | |
]; | |
} | |
protected function cropZoomed(): void | |
{ | |
$this->transforms['crop_zoomed'] = [ | |
'cm' => 'extract', | |
'h' => $this->zoomedHeight(), | |
'w' => $this->zoomedWidth(), | |
'x' => $this->zoomedX(), | |
'y' => $this->zoomedY(), | |
]; | |
} | |
protected function generateUrl(): string | |
{ | |
$parts = [ | |
'domain' => config('imagekit.domain'), | |
'id' => config('imagekit.id'), | |
'identifier' => config('imagekit.identifier'), | |
'transformation' => $this->generateTransformation(), | |
'path' => trim(str_replace('assets/', 'photos/', $this->asset->url()), '/'), | |
]; | |
return 'https://'.implode('/', array_filter($parts)); | |
} | |
protected function generateTransformation(): string | |
{ | |
$transforms = []; | |
foreach ($this->transforms as $params) { | |
array_walk($params, function (&$value, $key) { | |
if (is_numeric($value)) { | |
$value = intval(floor($value)); // round down | |
} | |
$value = $key.'-'.$value; | |
}); | |
$transforms[] = 'tr:'.implode(',', $params); | |
} | |
return implode(':', $transforms); | |
} | |
protected function image(): Collection | |
{ | |
$focus = explode('-', $this->asset->data()->get('focus', '50-50-1')); | |
$height = $this->asset->meta()['height']; | |
$width = $this->asset->meta()['width']; | |
$cx = Arr::get($focus, 0, 50); | |
$cy = Arr::get($focus, 1, 50); | |
$zoom = Arr::get($focus, 2, 1); | |
return collect([ | |
'cx' => $cx, | |
'cy' => $cy, | |
'height' => $height, | |
'width' => $width, | |
'x' => $width * ($cx / 100), | |
'y' => $height * ($cy / 100), | |
'zoom' => $zoom, | |
]); | |
} | |
protected function imageUrl(): string | |
{ | |
$this->image = $this->image(); | |
$this->height = collect($this->params)->get('height'); | |
$this->width = collect($this->params)->get('width'); | |
if ($this->isZoomed()) { | |
$this->cropZoomed(); | |
} | |
if ($this->isOversized()) { | |
$this->cropResized(); | |
} else { | |
$this->crop(); | |
} | |
$this->resize(); | |
return $this->generateUrl(); | |
} | |
protected function isHeightOversized(): bool | |
{ | |
return $this->height > $this->image->get('height'); | |
} | |
protected function isOversized(): bool | |
{ | |
return $this->isHeightOversized() || $this->isWidthOversized(); | |
} | |
protected function isWidthOversized(): bool | |
{ | |
return $this->width > $this->image->get('width'); | |
} | |
protected function isZoomed(): bool | |
{ | |
return $this->image->get('zoom') > 1; | |
} | |
protected function ratio(int $number, int $a, int $b): int | |
{ | |
return $number * ($a / $b); | |
} | |
protected function resize(): void | |
{ | |
$this->transforms['resize'] = [ | |
'h' => $this->height, | |
'w' => $this->width, | |
]; | |
} | |
protected function resizedHeight(): int | |
{ | |
$height = $this->zoomedHeight(); | |
$width = $this->zoomedWidth(); | |
$percentOfHeight = $height / $this->height; | |
$percentOfWidth = $width / $this->width; | |
return $percentOfHeight > $percentOfWidth | |
? $this->ratio($width, $this->height, $this->width) | |
: $height; | |
} | |
protected function resizedWidth(): int | |
{ | |
$height = $this->zoomedHeight(); | |
$width = $this->zoomedWidth(); | |
$percentOfHeight = $height / $this->height; | |
$percentOfWidth = $width / $this->width; | |
return $percentOfWidth > $percentOfHeight | |
? $this->ratio($height, $this->width, $this->height) | |
: $width; | |
} | |
protected function resizedX(): int | |
{ | |
$width = $this->resizedWidth(); | |
$x = $this->image->get('x') - ($width / 2); | |
$adjustment = max(0, ($width - ($this->image->get('width') - $x))); | |
return intval($x - $adjustment); | |
} | |
protected function resizedY(): int | |
{ | |
$height = $this->resizedHeight(); | |
$y = $this->image->get('y') - ($height / 2); | |
$adjustment = max(0, ($height - ($this->image->get('height') - $y))); | |
return intval($y - $adjustment); | |
} | |
protected function zoomedHeight(): int | |
{ | |
return $this->image->get('height') / $this->image->get('zoom'); | |
} | |
protected function zoomedWidth(): int | |
{ | |
return $this->image->get('width') / $this->image->get('zoom'); | |
} | |
protected function zoomedX(): int | |
{ | |
$width = $this->zoomedWidth(); | |
$x = $this->image->get('x') - ($width / 2); | |
$adjustment = max(0, ($width - ($this->image->get('width') - $x))); | |
return intval($x - $adjustment); | |
} | |
protected function zoomedY(): int | |
{ | |
$height = $this->zoomedHeight(); | |
$y = $this->image->get('y') - ($height / 2); | |
$adjustment = max(0, ($height - ($this->image->get('height') - $y))); | |
return intval($y - $adjustment); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment