From b98f329fdd625d9a46d913fa52bb40f80e281bac Mon Sep 17 00:00:00 2001 From: "michael.danielczok" <michael@pcsg.de> Date: Mon, 23 May 2022 15:23:22 +0200 Subject: [PATCH] feat: Show animation added [FloatedNav] --- bin/Controls/FloatedNav.js | 169 ++++++++++++++++++++++++++ src/QUI/Menu/Controls/FloatedNav.css | 26 ++-- src/QUI/Menu/Controls/FloatedNav.html | 51 ++++---- src/QUI/Menu/Controls/FloatedNav.php | 107 ++++++++++++++-- 4 files changed, 308 insertions(+), 45 deletions(-) create mode 100644 bin/Controls/FloatedNav.js diff --git a/bin/Controls/FloatedNav.js b/bin/Controls/FloatedNav.js new file mode 100644 index 0000000..f3dcfcf --- /dev/null +++ b/bin/Controls/FloatedNav.js @@ -0,0 +1,169 @@ +/** + * @module package/quiqqer/menu/bin/Controls/FloatedNav + * @author www.pcsg.de (Michael Danielczok) + * + * @require qui/QUI + * @require qui/controls/Control + */ +define('package/quiqqer/menu/bin/Controls/FloatedNav', [ + + 'qui/QUI', + 'qui/controls/Control', + URL_OPT_DIR + 'bin/quiqqer-asset/animejs/animejs/lib/anime.min.js', + +], function (QUI, QUIControl, anime) { + 'use strict'; + + return new Class({ + + Extends: QUIControl, + Type : 'package/quiqqer/menu/bin/Controls/FloatedNav', + + Binds: [ + '$onImport' + ], + + options: { + pos : 'right', // right, left + animationtype : 'showAll', // showAll (show entire control), showOneByOne (show each entry one by one) + animationeasing : 'easeOutExpo', // see easing names on https://easings.net/ + animationduration: 500, // number + }, + + initialize: function (options) { + this.parent(options); + + this.addEvents({ + onImport: this.$onImport + }); + + this.$Nav = null; + this.$entries = null; + this.$pos = 'right'; + this.$animationType = 'showAll'; + this.$animationEasing = 'easeOutExpo'; + }, + + /** + * event: on import + */ + $onImport: function () { + this.$Nav = this.getElm(); + + if (this.$Nav.get('data-qui-options-animationtype')) { + this.$animationType = this.$Nav.get('data-qui-options-animationtype'); + } + + if (this.$Nav.get('data-qui-options-animationeasing')) { + this.$animationEasing = this.$getAnimationName(this.$Nav.get('data-qui-options-animationeasing')); + } + + // animation type + switch (this.$animationType) { + case 'showAll': + this.$Nav.setStyles({ + visibility: 'visible', + right : -this.$Nav.getSize().x - 50 + }) + + this.$show(this.$Nav); + break; + + case 'showOneByOne': + this.$entries = this.$Nav.querySelectorAll('.quiqqer-floatedNav-entry'); + + this.$entries.forEach(($Entry) => { + $Entry.setStyles({ + visibility: 'visible', + transform : 'translateX(100px)' + }); + }) + + this.$showOneByOne(this.$entries); + break; + } + }, + + /** + * Show nav entries one by one + * + * @param entries {HTMLCollection} + */ + $showOneByOne: function (entries) { + anime({ + targets : entries, + translateX: 0, + duration : 500, + easing : this.$animationEasing, + delay : anime.stagger(100, {start: 750}) + }); + }, + + /** + * Show nav + * + * @param Elm {HTMLElement} + */ + $show: function (Elm) { + anime({ + targets : Elm, + right : 0, + delay : 750, + duration: 500, + easing : this.$animationEasing + }); + }, + + /** + * Get correct easing name for animation + * https://easings.net/ + * + * @param easingName {string} + * @return {string} + */ + $getAnimationName: function (easingName) { + switch (easingName) { + case 'easeInQuad': + case 'easeInCubic': + case 'easeInQuart': + case 'easeInQuint': + case 'easeInSine': + case 'easeInExpo': + case 'easeInCirc': + case 'easeInBack': + case 'easeOutQuad': + case 'easeOutCubic': + case 'easeOutQuart': + case 'easeOutQuint': + case 'easeOutSine': + case 'easeOutExpo': + case 'easeOutCirc': + case 'easeOutBack': + case 'easeInBounce': + case 'easeInOutQuad': + case 'easeInOutCubic': + case 'easeInOutQuart': + case 'easeInOutQuint': + case 'easeInOutSine': + case 'easeInOutExpo': + case 'easeInOutCirc': + case 'easeInOutBack': + case 'easeInOutBounce': + case 'easeOutBounce': + case 'easeOutInQuad': + case 'easeOutInCubic': + case 'easeOutInQuart': + case 'easeOutInQuint': + case 'easeOutInSine': + case 'easeOutInExpo': + case 'easeOutInCirc': + case 'easeOutInBack': + case 'easeOutInBounce': + return easingName; + + default: + return 'easeOutExpo'; + } + } + }); +}); \ No newline at end of file diff --git a/src/QUI/Menu/Controls/FloatedNav.css b/src/QUI/Menu/Controls/FloatedNav.css index 40b20b6..a414672 100644 --- a/src/QUI/Menu/Controls/FloatedNav.css +++ b/src/QUI/Menu/Controls/FloatedNav.css @@ -23,7 +23,6 @@ /* control */ /***********/ .quiqqer-floatedNav { - background: #fff; position: fixed; top: 50%; transform: translateY(-50%); @@ -39,7 +38,7 @@ } .quiqqer-floatedNav-entry { - transition: 0.2s all ease; + /*transition: 0.2s all ease;*/ } .quiqqer-floatedNav-entry-inner { @@ -94,28 +93,41 @@ filter: brightness(90%); } + /***********/ /* Designs */ /***********/ /* Design: Bar with icons */ -.quiqqer-floatedNav__iconsBar { +.quiqqer-floatedNav__design-iconsBar { + background: #fff; border-bottom-left-radius: 0.75rem; border-top-left-radius: 0.75rem; box-shadow: -3px 3px 8px rgb(0 0 0 / 30%); padding: var(--quiqqer-floatedNav-spacing); } -.quiqqer-floatedNav__iconsBar .quiqqer-floatedNav-entry-inner, -.quiqqer-floatedNav__iconsBar .quiqqer-bricks-languageswitch-flag { +.quiqqer-floatedNav__design-iconsBar .quiqqer-floatedNav-entry-inner, +.quiqqer-floatedNav__design-iconsBar .quiqqer-bricks-languageswitch-flag { border-radius: var(--qui-btn-border-radius, 5px); } -.quiqqer-floatedNav__iconsBar .quiqqer-floatedNav-entry:not(:last-child) .quiqqer-floatedNav-entry-inner { +.quiqqer-floatedNav__design-iconsBar .quiqqer-floatedNav-entry:not(:last-child) .quiqqer-floatedNav-entry-inner { margin-bottom: var(--quiqqer-floatedNav-spacing); } /* Design: flat */ -.quiqqer-floatedNav__flat .quiqqer-floatedNav-entry:not(:last-child) { +.quiqqer-floatedNav__design-flat .quiqqer-floatedNav-entry:not(:last-child) { margin-bottom: 2px; } + +/*************/ +/* Animation */ +/*************/ +.quiqqer-floatedNav__animation-showAll { + visibility: hidden; +} + +.quiqqer-floatedNav__animation-showOneByOne .quiqqer-floatedNav-entry { + visibility: hidden; +} \ No newline at end of file diff --git a/src/QUI/Menu/Controls/FloatedNav.html b/src/QUI/Menu/Controls/FloatedNav.html index aea686f..1bd3c3d 100644 --- a/src/QUI/Menu/Controls/FloatedNav.html +++ b/src/QUI/Menu/Controls/FloatedNav.html @@ -1,28 +1,27 @@ -<nav class="quiqqer-floatedNav {$design} {$size} {$posX}"> - {foreach $children as $Child} - {assign var=hasUrl value=1} - {if !$Child->getUrl()} - {assign var=hasUrl value=0} - {/if} - {if $Child->getIcon() && $Child->getIcon()|strpos:'image.php' !== 0} - <div class="quiqqer-floatedNav-entry quiqqer-floatedNav-entry__id-{$Child->getIdentifier()} {if !$hasUrl}quiqqer-floatedNav-entry__noUrl{/if}"> - {if $Child->getUrl()} - <a href="{$Child->getUrl()}" - class="quiqqer-floatedNav-entry-inner" - title="{$Child->getTitleAttribute()|escape:'html'}" - {if $Child->getTarget()}target="{$Child->getTarget()}"{/if} - > - {image src=$Child->getIcon() onlyicon=1} - </a> - {else} - <span class="quiqqer-floatedNav-entry-inner" title="{$Child->getTitleAttribute()|escape:'html'}"> +{foreach $children as $Child} + {assign var=hasUrl value=1} + {if !$Child->getUrl()} + {assign var=hasUrl value=0} + {/if} + {if $Child->getIcon() && $Child->getIcon()|strpos:'image.php' !== 0} + <div class="quiqqer-floatedNav-entry quiqqer-floatedNav-entry__id-{$Child->getIdentifier()} {if !$hasUrl}quiqqer-floatedNav-entry__noUrl{/if}"> + {if $Child->getUrl()} + <a href="{$Child->getUrl()}" + class="quiqqer-floatedNav-entry-inner" + title="{$Child->getTitleAttribute()|escape:'html'}" + {if $Child->getTarget()}target="{$Child->getTarget()}"{/if} + > {image src=$Child->getIcon() onlyicon=1} - </span> - {/if} - </div> - {/if} - {/foreach} - {if $LangSwitch} - {$LangSwitch->create()} + </a> + {else} + <span class="quiqqer-floatedNav-entry-inner" title="{$Child->getTitleAttribute()|escape:'html'}"> + {image src=$Child->getIcon() onlyicon=1} + </span> + {/if} + </div> {/if} -</nav> \ No newline at end of file +{/foreach} + +{if $LangSwitch} + {$LangSwitch->create()} +{/if} \ No newline at end of file diff --git a/src/QUI/Menu/Controls/FloatedNav.php b/src/QUI/Menu/Controls/FloatedNav.php index 72fec77..517383a 100644 --- a/src/QUI/Menu/Controls/FloatedNav.php +++ b/src/QUI/Menu/Controls/FloatedNav.php @@ -25,11 +25,15 @@ public function __construct($attributes = []) { // default options $this->setAttributes([ - 'menuId' => false, - 'posX' => 'right', // right, left - 'size' => 'medium', // small, medium, large - 'design' => 'iconBar', // iconBar, flat - 'showLangSwitch' => false + 'class' => 'quiqqer-floatedNav', + 'nodeName' => 'nav', + 'menuId' => false, + 'posX' => 'right', // right, left + 'size' => 'medium', // small, medium, large + 'design' => 'iconBar', // iconBar, flat + 'animationType' => false, // false, showOneByOne (show entire control), showSingle (show each entry one by one) + 'animationEasing' => 'easeOutExpo', // see easing names on https://easings.net/ + 'showLangSwitch' => false ]); parent::__construct($attributes); @@ -46,9 +50,16 @@ public function __construct($attributes = []) */ public function getBody() { - $Engine = QUI::getTemplateManager()->getEngine(); - $IndependentMenu = Independent\Handler::getMenu($this->getAttribute('menuId')); - $LangSwitch = null; + $Engine = QUI::getTemplateManager()->getEngine(); + $LangSwitch = null; + + try { + $IndependentMenu = Independent\Handler::getMenu($this->getAttribute('menuId')); + } catch (QUI\Exception $Exception) { + QUI\System\Log::writeException($Exception); + + return ''; + } if (!$IndependentMenu) { return ''; @@ -66,13 +77,13 @@ public function getBody() } switch ($this->getAttribute('design')) { - case 'iconBar': case 'flat': - $design = 'quiqqer-floatedNav__'.$this->getAttribute('design'); + $design = 'quiqqer-floatedNav__design-'.$this->getAttribute('design'); break; + case 'iconBar': default: - $design = 'quiqqer-floatedNav__iconsBar'; + $design = 'quiqqer-floatedNav__design-iconsBar'; } switch ($this->getAttribute('posX')) { @@ -89,13 +100,33 @@ public function getBody() if ($this->getAttribute('showLangSwitch')) { try { $LangSwitch = new QUI\Bricks\Controls\LanguageSwitches\Flags([ - 'showFlags' => 0 + 'showFlags' => 0, + 'class' => 'quiqqer-floatedNav-entry' ]); } catch (QUI\Exception $Exception) { QUI\System\Log::writeException($Exception); } } + $animation = ''; + if ($this->getAttribute('animationType')) { + switch ($this->getAttribute('animationType')) { + case 'showAll': + case 'showOneByOne': + $this->setJavaScriptControlOption('position', 'right'); + $this->setJavaScriptControlOption('animationtype', $this->getAttribute('animationType')); + $this->setJavaScriptControlOption('animationeasing', $this->getAnimationEasingName()); + $this->setJavaScriptControl('package/quiqqer/menu/bin/Controls/FloatedNav'); + $animation = 'quiqqer-floatedNav__animation-'.$this->getAttribute('animationType'); + break; + } + } + + $this->addCSSClass($size); + $this->addCSSClass($design); + $this->addCSSClass($posX); + $this->addCSSClass($animation); + $children = $IndependentMenu->getChildren(); $Engine->assign([ @@ -109,4 +140,56 @@ public function getBody() return $Engine->fetch(dirname(__FILE__).'/FloatedNav.html'); } + + /** + * Get correct easing name for animation + * https://easings.net/ + * + * @return false|mixed|string + */ + public function getAnimationEasingName() + { + switch ($this->getAttribute('animationEasing')) { + case 'easeInQuad': + case 'easeInCubic': + case 'easeInQuart': + case 'easeInQuint': + case 'easeInSine': + case 'easeInExpo': + case 'easeInCirc': + case 'easeInBack': + case 'easeOutQuad': + case 'easeOutCubic': + case 'easeOutQuart': + case 'easeOutQuint': + case 'easeOutSine': + case 'easeOutExpo': + case 'easeOutCirc': + case 'easeOutBack': + case 'easeInBounce': + case 'easeInOutQuad': + case 'easeInOutCubic': + case 'easeInOutQuart': + case 'easeInOutQuint': + case 'easeInOutSine': + case 'easeInOutExpo': + case 'easeInOutCirc': + case 'easeInOutBack': + case 'easeInOutBounce': + case 'easeOutBounce': + case 'easeOutInQuad': + case 'easeOutInCubic': + case 'easeOutInQuart': + case 'easeOutInQuint': + case 'easeOutInSine': + case 'easeOutInExpo': + case 'easeOutInCirc': + case 'easeOutInBack': + case 'easeOutInBounce': + return $this->getAttribute('animationEasing'); + + default: + return 'easeOutExpo'; + } + } } -- GitLab