154 lines
5.7 KiB
PHP
154 lines
5.7 KiB
PHP
<?php
|
|
namespace YTKNS\Effects;
|
|
|
|
use Exception;
|
|
use YTKNS\HtmlTag;
|
|
use YTKNS\HtmlText;
|
|
use YTKNS\PageBuilder;
|
|
use YTKNS\PageEffectInterface;
|
|
use YTKNS\Upload;
|
|
use YTKNS\UploadNotFoundException;
|
|
|
|
class ForegroundImageEffect implements PageEffectInterface {
|
|
private const IMG_MIME = [
|
|
'image/png',
|
|
'image/jpeg',
|
|
'image/gif',
|
|
];
|
|
private const SPIN_DIRS = [
|
|
'cw' => 'Clockwise',
|
|
'ccw' => 'Counterclockwise',
|
|
];
|
|
private const SPIN_MIN = 0.01;
|
|
private const SPIN_MAX = 1000;
|
|
|
|
private $imageUpload = null;
|
|
private $spin = false;
|
|
private $spinSpeed = 1;
|
|
private $spinDirection = 'cw';
|
|
private $syncWithAudio = false;
|
|
|
|
public function getEffectName(): string {
|
|
return 'Foreground Image';
|
|
}
|
|
|
|
public function getEffectProperties(): array {
|
|
return [
|
|
[
|
|
'name' => 'img',
|
|
'title' => 'Image',
|
|
'type' => [
|
|
'name' => 'upload',
|
|
'allowed' => self::IMG_MIME,
|
|
],
|
|
],
|
|
[
|
|
'name' => 'spin',
|
|
'title' => 'Spin Animation',
|
|
'default' => false,
|
|
'type' => [
|
|
'name' => 'bool',
|
|
],
|
|
],
|
|
[
|
|
'name' => 'spnspd',
|
|
'title' => 'Spin Animation Period',
|
|
'default' => 1,
|
|
'type' => [
|
|
'name' => 'float',
|
|
'min' => self::SPIN_MIN,
|
|
'max' => self::SPIN_MAX,
|
|
],
|
|
],
|
|
[
|
|
'name' => 'spndir',
|
|
'title' => 'Spin Animation Direction',
|
|
'default' => 'br',
|
|
'type' => [
|
|
'name' => 'select',
|
|
'options' => self::SPIN_DIRS,
|
|
],
|
|
],
|
|
[
|
|
'name' => 'sync',
|
|
'title' => 'Synchronise with Background Audio',
|
|
'default' => false,
|
|
'type' => [
|
|
'name' => 'bool',
|
|
],
|
|
],
|
|
];
|
|
}
|
|
|
|
public function setEffectParams(array $vars, bool $quiet = false): void {
|
|
try {
|
|
if(isset($vars['img']) && is_string($vars['img'])) {
|
|
try {
|
|
$this->imageUpload = Upload::byId($vars['img']);
|
|
} catch(Exception $ex) {
|
|
if(!$quiet)
|
|
throw $ex;
|
|
}
|
|
|
|
if(!$quiet && !in_array($this->imageUpload->getType(), self::IMG_MIME))
|
|
throw new PageEffectException('Image upload was of invalid type.');
|
|
}
|
|
} catch(UploadNotFoundException $ex) {
|
|
$this->imageUpload = null;
|
|
}
|
|
|
|
if(isset($vars['spin']))
|
|
$this->spin = is_bool($vars['spin']) ? $vars['spin'] : (is_string($vars['spin']) ? boolval($vars['spin']) : false);
|
|
if(isset($vars['sync']))
|
|
$this->syncWithAudio = is_bool($vars['sync']) ? $vars['sync'] : (is_string($vars['sync']) ? boolval($vars['sync']) : false);
|
|
|
|
if(isset($vars['spnspd'])) {
|
|
$this->spinSpeed = is_int($vars['spnspd']) || is_float($vars['spnspd']) ? $vars['spnspd'] : (is_string($vars['spnspd']) ? floatval($vars['spnspd']) : 1);
|
|
|
|
if(!$quiet && ($this->spinSpeed < self::SPIN_MIN || $this->spinSpeed > self::SPIN_MAX))
|
|
throw new PageEffectException(sprintf('Spin speed may not be less than %d or more than %d', self::SPIN_MIN, self::SPIN_MAX));
|
|
}
|
|
|
|
if(isset($vars['spndir']) && is_string($vars['spndir']) && array_key_exists($vars['spndir'], self::SPIN_DIRS))
|
|
$this->spinDirection = $vars['spndir'];
|
|
}
|
|
|
|
public function getEffectParams(): array {
|
|
return [
|
|
'img' => empty($this->imageUpload) ? null : $this->imageUpload->getId(),
|
|
'spin' => $this->spin,
|
|
'spnspd' => $this->spinSpeed,
|
|
'spndir' => $this->spinDirection,
|
|
'sync' => $this->syncWithAudio,
|
|
];
|
|
}
|
|
|
|
public function applyEffect(PageBuilder $builder): void {
|
|
$element = $builder->getContainer()->appendChild(new HtmlTag('div', ['class' => 'ForegroundImage']));
|
|
$imageTarget = $element->appendChild(new HtmlTag('div', ['class' => 'ForegroundImage_Image', 'id' => 'ForegroundImage']));
|
|
|
|
if(!empty($this->imageUpload)) {
|
|
$imageSize = getimagesize($this->imageUpload->getPath());
|
|
|
|
if($imageSize !== false) {
|
|
$styleText = sprintf('width: %dpx; height: %dpx', $imageSize[0], $imageSize[1]);
|
|
|
|
if(!empty($_GET['preview']) || !$this->syncWithAudio)
|
|
$styleText .= sprintf(';background-image:url(\'%s\')', $this->imageUpload->getUrl());
|
|
|
|
if(empty($_GET['preview']) && $this->spin)
|
|
$styleText .= sprintf(';animation: SharedAnimation_Spin360 infinite linear %s %Fs', $this->spinDirection === 'cw' ? 'normal' : 'reverse', $this->spinSpeed);
|
|
|
|
$imageTarget->setAttribute('style', $styleText);
|
|
|
|
$scriptText = 'window.addEventListener(\'DOMContentLoaded\', function() {';
|
|
$scriptText .= 'synchroniseBackgroundWithAudio(\'' . $this->imageUpload->getUrl() . '\', \'ForegroundImage\');';
|
|
$scriptText .= '});';
|
|
$scriptTag = new HtmlTag('script', ['type' => 'text/javascript']);
|
|
$scriptTag->setTextContent($scriptText);
|
|
$builder->getHead()->appendChild($scriptTag);
|
|
}
|
|
}
|
|
}
|
|
}
|