420 lines
15 KiB
PHP
420 lines
15 KiB
PHP
<?php
|
|
|
|
|
|
namespace Nextend\SmartSlider3\Slider\Feature;
|
|
|
|
|
|
use Nextend\Framework\Image\ImageEdit;
|
|
use Nextend\Framework\Image\ImageManager;
|
|
use Nextend\Framework\Parser\Color;
|
|
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
|
|
use Nextend\Framework\View\Html;
|
|
use Nextend\SmartSlider3\Slider\Slide;
|
|
use Nextend\SmartSlider3\Slider\Slider;
|
|
|
|
class SlideBackground {
|
|
|
|
/**
|
|
* @var Slider
|
|
*/
|
|
private $slider;
|
|
|
|
public function __construct($slider) {
|
|
|
|
$this->slider = $slider;
|
|
}
|
|
|
|
public function makeJavaScriptProperties(&$properties) {
|
|
$enabled = intval($this->slider->params->get('slide-background-parallax', 0));
|
|
if ($enabled) {
|
|
$properties['backgroundParallax'] = array(
|
|
'strength' => intval($this->slider->params->get('slide-background-parallax-strength', 50)) / 100,
|
|
'tablet' => intval($this->slider->params->get('bg-parallax-tablet', 0)),
|
|
'mobile' => intval($this->slider->params->get('bg-parallax-mobile', 0))
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $slide Slide
|
|
*
|
|
* @return string
|
|
*/
|
|
|
|
public function make($slide) {
|
|
|
|
if ($slide->parameters->get('background-type') == '') {
|
|
$slide->parameters->set('background-type', 'color');
|
|
if ($slide->parameters->get('backgroundVideoMp4')) {
|
|
$slide->parameters->set('background-type', 'video');
|
|
} else if ($slide->parameters->get('backgroundImage')) {
|
|
$slide->parameters->set('background-type', 'image');
|
|
}
|
|
}
|
|
|
|
return $this->makeBackground($slide);
|
|
}
|
|
|
|
private function getBackgroundStyle($slide) {
|
|
|
|
$attributes = array();
|
|
|
|
$style = '';
|
|
$color = $slide->fill($slide->parameters->get('backgroundColor', ''));
|
|
if (empty($color)) {
|
|
$color = 'ffffff00';
|
|
}
|
|
if (strlen($color) > 0 && $color[0] == '#') {
|
|
$color = substr($color, 1);
|
|
if (strlen($color) == 6) {
|
|
$color .= 'ff';
|
|
}
|
|
}
|
|
$gradient = $slide->parameters->get('backgroundGradient', 'off');
|
|
|
|
if ($gradient != 'off') {
|
|
$colorEnd = $slide->fill($slide->parameters->get('backgroundColorEnd', 'ffffff00'));
|
|
if (empty($colorEnd)) {
|
|
$colorEnd = 'ffffff00';
|
|
}
|
|
|
|
if ($colorEnd[0] == '#') {
|
|
$colorEnd = substr($colorEnd, 1);
|
|
if (strlen($colorEnd) == 6) {
|
|
$colorEnd .= 'ff';
|
|
}
|
|
}
|
|
|
|
$startColor = Color::colorToRGBA($color);
|
|
$endColor = Color::colorToRGBA($colorEnd);
|
|
|
|
$attributes['data-gradient'] = $gradient;
|
|
$attributes['data-color-start'] = $startColor;
|
|
$attributes['data-color-end'] = $endColor;
|
|
|
|
switch ($gradient) {
|
|
case 'horizontal':
|
|
$style .= 'background:linear-gradient(to right, ' . $startColor . ' 0%,' . $endColor . ' 100%);';
|
|
break;
|
|
case 'vertical':
|
|
$style .= 'background:linear-gradient(to bottom, ' . $startColor . ' 0%,' . $endColor . ' 100%);';
|
|
break;
|
|
case 'diagonal1':
|
|
$style .= 'background:linear-gradient(45deg, ' . $startColor . ' 0%,' . $endColor . ' 100%);';
|
|
break;
|
|
case 'diagonal2':
|
|
$style .= 'background:linear-gradient(135deg, ' . $startColor . ' 0%,' . $endColor . ' 100%);';
|
|
break;
|
|
}
|
|
} else {
|
|
if (strlen($color) == 8) {
|
|
|
|
$colorRGBA = Color::colorToRGBA($color);
|
|
$style .= "background-color: " . Color::colorToRGBA($color) . ";";
|
|
|
|
$attributes['data-color'] = $colorRGBA;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
$attributes['style'] = $style;
|
|
|
|
return $attributes;
|
|
}
|
|
|
|
private function makeBackground($slide) {
|
|
|
|
$backgroundType = $slide->parameters->get('background-type');
|
|
|
|
if (empty($backgroundType)) {
|
|
$backgroundVideoMp4 = $slide->parameters->get('backgroundVideoMp4', '');
|
|
$backgroundImage = $slide->parameters->get('backgroundImage', '');
|
|
if (!empty($backgroundVideoMp4)) {
|
|
$backgroundType = 'video';
|
|
} else if (!empty($backgroundImage)) {
|
|
$backgroundType = 'image';
|
|
} else {
|
|
$backgroundType = 'color';
|
|
}
|
|
}
|
|
|
|
$fillMode = $slide->parameters->get('backgroundMode', 'default');
|
|
|
|
if ($fillMode == 'default') {
|
|
$fillMode = $this->slider->params->get('backgroundMode', 'fill');
|
|
|
|
}
|
|
|
|
$backgroundElements = array();
|
|
|
|
if ($backgroundType == 'color') {
|
|
$backgroundElements[] = $this->renderColor($slide);
|
|
|
|
} else if ($backgroundType == 'video') {
|
|
|
|
|
|
$backgroundElements[] = $this->renderBackgroundVideo($slide);
|
|
$backgroundElements[] = $this->renderImage($slide, $fillMode);
|
|
|
|
$backgroundElements[] = $this->renderColor($slide);
|
|
|
|
} else if ($backgroundType == 'image') {
|
|
|
|
|
|
$backgroundElements[] = $this->renderImage($slide, $fillMode);
|
|
|
|
$backgroundElements[] = $this->renderColor($slide);
|
|
}
|
|
|
|
$html = implode('', $backgroundElements);
|
|
|
|
/* @see https://bugs.chromium.org/p/chromium/issues/detail?id=1181291
|
|
* if (!$slide->getFrontendFirst()) {
|
|
* $html = '<template>' . $html . '</template>';
|
|
* }
|
|
*/
|
|
|
|
return Html::tag('div', array(
|
|
'class' => "n2-ss-slide-background",
|
|
'data-public-id' => $slide->publicID,
|
|
'data-mode' => $fillMode
|
|
), $html);
|
|
}
|
|
|
|
private function renderColor($slide) {
|
|
$backgroundAttributes = $this->getBackgroundStyle($slide);
|
|
|
|
if (!empty($backgroundAttributes['style'])) {
|
|
|
|
$backgroundAttributes['class'] = 'n2-ss-slide-background-color';
|
|
|
|
if ($slide->parameters->get('backgroundColorOverlay', 0)) {
|
|
$backgroundAttributes['data-overlay'] = 1;
|
|
}
|
|
|
|
return Html::tag('div', $backgroundAttributes, '');
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* @param $slide Slide
|
|
* @param $fillMode
|
|
*
|
|
* @return string
|
|
*/
|
|
private function renderImage($slide, $fillMode) {
|
|
|
|
$rawBackgroundImage = $slide->parameters->get('backgroundImage', '');
|
|
|
|
if (empty($rawBackgroundImage)) {
|
|
return '';
|
|
}
|
|
|
|
$backgroundImageBlur = max(0, $slide->parameters->get('backgroundImageBlur', 0));
|
|
|
|
$focusX = max(0, min(100, $slide->fill($slide->parameters->get('backgroundFocusX', 50))));
|
|
$focusY = max(0, min(100, $slide->fill($slide->parameters->get('backgroundFocusY', 50))));
|
|
|
|
$backgroundImageMobile = '';
|
|
$backgroundImageTablet = '';
|
|
$backgroundImageDesktopRetina = '';
|
|
$backgroundImage = $slide->fill($rawBackgroundImage);
|
|
|
|
if (!$slide->hasGenerator()) {
|
|
$imageData = ImageManager::getImageData($backgroundImage);
|
|
$backgroundImageDesktopRetina = $imageData['desktop-retina']['image'];
|
|
$backgroundImageMobile = $imageData['mobile']['image'];
|
|
$backgroundImageTablet = $imageData['tablet']['image'];
|
|
}
|
|
|
|
$alt = $slide->fill($slide->parameters->get('backgroundAlt', ''));
|
|
$title = $slide->fill($slide->parameters->get('backgroundTitle', ''));
|
|
|
|
|
|
$opacity = min(100, max(0, $slide->parameters->get('backgroundImageOpacity', 100)));
|
|
|
|
$style = array();
|
|
if ($opacity < 100) {
|
|
$style[] = 'opacity:' . ($opacity / 100);
|
|
}
|
|
|
|
if ($focusX != '50') {
|
|
$style[] = '--ss-o-pos-x:' . $focusX . '%';
|
|
}
|
|
|
|
if ($focusY != '50') {
|
|
$style[] = '--ss-o-pos-y:' . $focusY . '%';
|
|
}
|
|
|
|
$attributes = array(
|
|
"class" => 'n2-ss-slide-background-image',
|
|
"data-blur" => $backgroundImageBlur,
|
|
"data-opacity" => $opacity,
|
|
"data-x" => $focusX,
|
|
"data-y" => $focusY,
|
|
"data-alt" => $alt,
|
|
"data-title" => $title
|
|
);
|
|
|
|
if (!empty($style)) {
|
|
$attributes['style'] = implode(';', $style);
|
|
}
|
|
|
|
$sources = array();
|
|
|
|
if ($this->slider->isAdmin) {
|
|
$src = $backgroundImage;
|
|
|
|
$attributes['data-hash'] = md5($src);
|
|
$attributes['data-src-desktop'] = $src;
|
|
$attributes['data-src-desktop-retina'] = $backgroundImageDesktopRetina;
|
|
$attributes['data-src-tablet'] = $backgroundImageTablet;
|
|
$attributes['data-src-mobile'] = $backgroundImageMobile;
|
|
} else {
|
|
|
|
if (empty($backgroundImage)) {
|
|
/**
|
|
* @todo Does it really work as expected?
|
|
*/
|
|
$src = ImageEdit::base64Transparent();
|
|
} else {
|
|
/**
|
|
* @todo this resize might have a better place
|
|
*/
|
|
$src = $backgroundImage;
|
|
if ($this->slider->params->get('optimize-scale', 0)) {
|
|
$src = ResourceTranslator::urlToResource($this->slider->features->optimize->optimizeBackground($backgroundImage, $focusX, $focusY));
|
|
}
|
|
|
|
|
|
$slide->addImage(ResourceTranslator::toUrl($src));
|
|
}
|
|
|
|
$hasDeviceSpecificImage = false;
|
|
|
|
$mediaQueries = $this->slider->features->responsive->mediaQueries;
|
|
|
|
if (!empty($backgroundImageDesktopRetina)) {
|
|
|
|
$hasDeviceSpecificImage = true;
|
|
|
|
$backgroundImageDesktopRetina = ResourceTranslator::toUrl($backgroundImageDesktopRetina);
|
|
|
|
$mediaQueryMinPixelRatio = ' and (-webkit-min-device-pixel-ratio: 1.5)';
|
|
|
|
if (!empty($mediaQueries['desktopportrait'])) {
|
|
$sources[] = HTML::tag('source', Html::addExcludeLazyLoadAttributes(array(
|
|
'srcset' => $backgroundImageDesktopRetina,
|
|
'media' => implode($mediaQueryMinPixelRatio . ',', $mediaQueries['desktopportrait']) . $mediaQueryMinPixelRatio
|
|
)), false, false);
|
|
}
|
|
if (!empty($mediaQueries['desktoplandscape'])) {
|
|
$sources[] = HTML::tag('source', Html::addExcludeLazyLoadAttributes(array(
|
|
'srcset' => $backgroundImageDesktopRetina,
|
|
'media' => implode($mediaQueryMinPixelRatio . ',', $mediaQueries['desktoplandscape']) . $mediaQueryMinPixelRatio
|
|
)), false, false);
|
|
}
|
|
|
|
}
|
|
|
|
if (!empty($backgroundImageMobile)) {
|
|
|
|
$hasDeviceSpecificImage = true;
|
|
|
|
$backgroundImageMobileUrl = ResourceTranslator::toUrl($backgroundImageMobile);
|
|
|
|
if (!empty($mediaQueries['mobileportrait'])) {
|
|
$sources[] = HTML::tag('source', Html::addExcludeLazyLoadAttributes(array(
|
|
'srcset' => $backgroundImageMobileUrl,
|
|
'media' => implode(',', $mediaQueries['mobileportrait'])
|
|
)), false, false);
|
|
}
|
|
if (!empty($mediaQueries['mobilelandscape'])) {
|
|
$sources[] = HTML::tag('source', Html::addExcludeLazyLoadAttributes(array(
|
|
'srcset' => $backgroundImageMobileUrl,
|
|
'media' => implode(',', $mediaQueries['mobilelandscape'])
|
|
)), false, false);
|
|
}
|
|
}
|
|
|
|
if (!empty($backgroundImageTablet)) {
|
|
|
|
$hasDeviceSpecificImage = true;
|
|
|
|
$backgroundImageTabletUrl = ResourceTranslator::toUrl($backgroundImageTablet);
|
|
|
|
if (!empty($mediaQueries['tabletportrait'])) {
|
|
$sources[] = HTML::tag('source', Html::addExcludeLazyLoadAttributes(array(
|
|
'srcset' => $backgroundImageTabletUrl,
|
|
'media' => implode(',', $mediaQueries['tabletportrait'])
|
|
)), false, false);
|
|
}
|
|
if (!empty($mediaQueries['tabletlandscape'])) {
|
|
$sources[] = HTML::tag('source', Html::addExcludeLazyLoadAttributes(array(
|
|
'srcset' => $backgroundImageTabletUrl,
|
|
'media' => implode(',', $mediaQueries['tabletlandscape'])
|
|
)), false, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
$imageAttributes = array(
|
|
'src' => ResourceTranslator::toUrl($src),
|
|
'alt' => $alt,
|
|
'title' => $title,
|
|
'loading' => 'lazy',
|
|
'style' => ''
|
|
);
|
|
|
|
$imageAttributes = Html::addExcludeLazyLoadAttributes($imageAttributes);
|
|
|
|
$sources[] = Html::tag('img', $imageAttributes, '', false);
|
|
|
|
$picture = HTML::tag('picture', Html::addExcludeLazyLoadAttributes(), implode('', $sources));
|
|
|
|
$originalImage = Html::tag('div', $attributes, $picture);
|
|
|
|
if ($fillMode === 'blurfit') {
|
|
$slideOption = $slide->parameters->get('backgroundMode', 'default');
|
|
|
|
if ($slideOption === 'blurfit') {
|
|
$blurFit = $slide->parameters->get('backgroundBlurFit', 7);
|
|
} else {
|
|
$blurFit = $this->slider->params->get('backgroundBlurFit', 7);
|
|
$attributes['data-blurfitmode'] = 'default';
|
|
}
|
|
$picture = HTML::tag('picture', Html::addExcludeLazyLoadAttributes(array(
|
|
'style' => 'filter:blur(' . $blurFit . 'px)'
|
|
)), implode('', $sources));
|
|
$blurFitStyle = array(
|
|
'margin:-' . ($blurFit * 2) . 'px',
|
|
'padding:' . ($blurFit * 2) . 'px'
|
|
);
|
|
if (!isset($attributes['style'])) {
|
|
$attributes['style'] = '';
|
|
}
|
|
|
|
$attributes['data-globalblur'] = $this->slider->params->get('backgroundBlurFit', 7);
|
|
$attributes['data-bgblur'] = $slide->parameters->get('backgroundBlurFit', 7);
|
|
$attributes['style'] = implode(';', $blurFitStyle);
|
|
$ret = Html::tag('div', $attributes, $picture) . $originalImage;
|
|
} else {
|
|
$ret = $originalImage;
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* @param Slide $slide
|
|
*
|
|
* @return string
|
|
*/
|
|
private function renderBackgroundVideo($slide) {
|
|
|
|
return '';
|
|
}
|
|
} |