Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZigZag Entrance Animation [TMZ-216] #153

Merged
merged 23 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions assets/dev/scss/variables/values.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
$transition: all .3s;

$corners-shape-default: 8px;
$corners-shape-sharp: 0;
$corners-shape-rounded: 12px;
Expand Down
116 changes: 116 additions & 0 deletions modules/content/assets/js/frontend/handlers/hello-plus-zigzag.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
export default class ZigZagHandler extends elementorModules.frontend.handlers.Base {
getDefaultSettings() {
return {
selectors: {
main: '.ehp-zigzag',
itemWrapper: '.ehp-zigzag__item-wrapper',
},
constants: {
entranceAnimation: 'zigzag_animation',
entranceAnimationAlternate: 'zigzag_animation_alternate',
hasEntranceAnimation: 'has-entrance-animation',
hasAlternateAnimation: 'has-alternate-animation',
none: 'none',
visible: 'visible',
hidden: 'hidden',
},
};
}

getDefaultElements() {
const selectors = this.getSettings( 'selectors' );

return {
main: this.$element[ 0 ].querySelector( selectors.main ),
itemWrappers: this.$element[ 0 ].querySelectorAll( selectors.itemWrapper ),
};
}

bindEvents() {
if ( this.elements.itemWrappers.length > 0 ) {
this.elements.itemWrappers.forEach( ( itemWrapper ) => {
itemWrapper.addEventListener( 'animationend', this.removeAnimationClasses.bind( this ) );
} );
}
}

getResponsiveSetting( controlName ) {
const currentDevice = elementorFrontend.getCurrentDeviceMode();
return elementorFrontend.utils.controls.getResponsiveControlValue( this.getElementSettings(), controlName, '', currentDevice );
}

initEntranceAnimation() {
const { entranceAnimation, entranceAnimationAlternate, none, visible, hidden } = this.getSettings( 'constants' );
const entranceAnimationClass = this.getResponsiveSetting( entranceAnimation );

if ( ! entranceAnimationClass || none === entranceAnimationClass ) {
return;
}
const alternateAnimationClass = this.getResponsiveSetting( entranceAnimationAlternate );

const observerCallback = ( entries ) => {
const sortedEntries = [ ...entries ].sort( ( a, b ) => {
const indexA = a.target.dataset.index;
const indexB = b.target.dataset.index;
return indexA - indexB;
} );

sortedEntries.forEach( ( entry, index ) => {
if ( entry.isIntersecting && ! entry.target.classList.contains( visible ) ) {
setTimeout( () => {
entry.target.classList.remove( hidden );
const entryIndex = parseInt( entry.target.dataset.index, 10 );
const animation = this.hasAlternateAnimation( entryIndex ) ? alternateAnimationClass : entranceAnimationClass;
entry.target.classList.add( animation );
}, index * 200 );
}
} );
};

const observerOptions = {
root: null,
rootMargin: '0px',
threshold: 0.5,
};
const observer = new IntersectionObserver( observerCallback, observerOptions );

this.elements.itemWrappers.forEach( ( element, index ) => {
element.dataset.index = index;
observer.observe( element );
} );
}

removeAnimationClasses( event ) {
const { entranceAnimation, entranceAnimationAlternate, visible, hidden } = this.getSettings( 'constants' );
const element = event.target;
const entranceAnimationClass = this.getResponsiveSetting( entranceAnimation );
const alternateAnimationClass = this.getResponsiveSetting( entranceAnimationAlternate );
const entryIndex = parseInt( element.dataset.index, 10 );

const animation = this.hasAlternateAnimation( entryIndex ) ? alternateAnimationClass : entranceAnimationClass;
element.classList.remove( animation );

element.classList.remove( hidden );
element.classList.add( visible );
}

hasAlternateAnimation( index ) {
const { hasAlternateAnimation } = this.getSettings( 'constants' );
const isEven = 0 === ( index + 1 ) % 2;
return this.elements.main.classList.contains( hasAlternateAnimation ) && isEven;
}

getAlternateAnimationClass( entranceAnimationClass ) {
return entranceAnimationClass.replace( /Right|Left/g, ( match ) => ( 'Right' === match ? 'Left' : 'Right' ) );
}

onInit( ...args ) {
const { hasEntranceAnimation } = this.getSettings( 'constants' );

super.onInit( ...args );

if ( this.elements.main && this.elements.main.classList.contains( hasEntranceAnimation ) ) {
this.initEntranceAnimation();
}
}
}
13 changes: 13 additions & 0 deletions modules/content/assets/js/frontend/hello-plus-zigzag-fe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export default class HelloPlusZigzagFe extends elementorModules.Module {
constructor() {
super();

elementorFrontend.elementsHandler.attachHandler( 'zigzag', [
() => import( /* webpackChunkName: 'js/content' */ './handlers/hello-plus-zigzag' ),
] );
}
}

window.addEventListener( 'elementor/frontend/init', () => {
new HelloPlusZigzagFe();
} );
23 changes: 23 additions & 0 deletions modules/content/assets/scss/hello-plus-zigzag.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
--zigzag-box-padding-inline-start: 0;
--zigzag-box-padding-inline-end: 0;

--zigzag-animation-delay: 0;
--zigzag-animation-duration: 1s;

align-items: center;
background-color: transparent;
display: flex;
Expand Down Expand Up @@ -235,6 +238,16 @@
}
}

&.has-entrance-animation {

& .ehp-zigzag__item-wrapper {
animation-delay: var(--zigzag-animation-delay);
animation-duration: var(--zigzag-animation-duration);
animation-fill-mode: both;
animation-timing-function: ease;
}
}

&__item-wrapper {
display: flex;
justify-content: center;
Expand All @@ -253,6 +266,16 @@
padding-block-end: var(--zigzag-box-padding-block-end);
}
}

&.hidden {
opacity: 0;
visibility: hidden;
}

&.visible {
opacity: 1;
visibility: visible;
}
}

@media screen and (max-width: $screen-tablet-max) {
Expand Down
39 changes: 39 additions & 0 deletions modules/content/classes/control-zig-zag-animation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php
namespace HelloPlus\Modules\Content\Classes;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

use Elementor\Control_Animation;

class Control_Zig_Zag_Animation extends Control_Animation {

const CONTROL_TYPE = 'ehp-zigzag-animation';

public function get_type(): string {
return static::CONTROL_TYPE;
}

public static function get_default_animations(): array {
return [
'Fading' => [
'fadeIn' => 'Fade In',
'fadeInLeft' => 'Fade In Left',
'fadeInRight' => 'Fade In Right',
'fadeInUp' => 'Fade In Up',
],
'Bouncing' => [
'bounceIn' => 'Bounce In',
'bounceInLeft' => 'Bounce In Left',
'bounceInRight' => 'Bounce In Right',
'bounceInUp' => 'Bounce In Up',
],
'Sliding' => [
'slideInLeft' => 'Slide In Left',
'slideInRight' => 'Slide In Right',
'slideInUp' => 'Slide In Up',
],
];
}
}
25 changes: 24 additions & 1 deletion modules/content/classes/render/widget-zig-zag-render.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ public function __construct( Zig_Zag $widget ) {
public function render(): void {
$first_zigzag_direction = $this->settings['first_zigzag_direction'];
$has_alternate_icon_color = $this->settings['has_alternate_icon_color'];
$entrance_animation = $this->settings['zigzag_animation'] ?? '';
$has_entrance_animation = ! empty( $entrance_animation ) && 'none' !== $entrance_animation;
$has_alternate_animation = 'yes' === $this->settings['animation_alternate'];

$layout_classnames = [
self::LAYOUT_CLASSNAME,
Expand All @@ -39,6 +42,14 @@ public function render(): void {
$layout_classnames[] = 'has-alternate-icon-color';
}

if ( $has_entrance_animation ) {
$layout_classnames[] = 'has-entrance-animation';
}

if ( $has_alternate_animation ) {
$layout_classnames[] = 'has-alternate-animation';
}

$this->widget->add_render_attribute( 'layout', [
'class' => $layout_classnames,
] );
Expand All @@ -49,12 +60,24 @@ public function render(): void {
$graphic_element = $this->settings['graphic_element'];
$repeater = 'image' === $graphic_element ? $this->settings['image_zigzag_items'] : $this->settings['icon_zigzag_items'];

$wrapper_classnames = [
'ehp-zigzag__item-wrapper',
];

if ( $has_entrance_animation ) {
$wrapper_classnames[] = 'hidden';
}

foreach ( $repeater as $key => $item ) {
$this->widget->add_render_attribute( 'zigzag-item-wrapper-' . $key, [
'class' => $wrapper_classnames,
nuritsha marked this conversation as resolved.
Show resolved Hide resolved
] );

$this->widget->add_render_attribute( 'zigzag-item-' . $key, [
'class' => self::ITEM_CLASSNAME,
] );
?>
<div class="ehp-zigzag__item-wrapper">
<div <?php $this->widget->print_render_attribute_string( 'zigzag-item-wrapper-' . $key ); ?>>
<div <?php $this->widget->print_render_attribute_string( 'zigzag-item-' . $key ); ?>>
<?php
$this->render_graphic_element_container( $item, $key );
Expand Down
21 changes: 21 additions & 0 deletions modules/content/module.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
exit; // Exit if accessed directly.
}

use Elementor\Controls_Manager;
use HelloPlus\Includes\Module_Base;
use HelloPlus\Includes\Utils;
use HelloPlus\Modules\Content\Classes\Control_Zig_Zag_Animation;

/**
* class Module
Expand Down Expand Up @@ -40,6 +42,19 @@ protected function get_widget_ids(): array {
];
}

/**
* @return void
*/
public function register_scripts() {
wp_register_script(
'helloplus-zigzag-fe',
HELLOPLUS_SCRIPTS_URL . 'helloplus-zigzag-fe.js',
[ 'elementor-frontend' ],
HELLOPLUS_VERSION,
true
);
}

public function register_styles(): void {
wp_register_style(
'helloplus-zigzag',
Expand Down Expand Up @@ -79,8 +94,14 @@ public static function is_active(): bool {
return Utils::is_elementor_active();
}

public function register_controls( Controls_Manager $controls_manager ) {
$controls_manager->register( new Control_Zig_Zag_Animation() );
}

protected function register_hooks(): void {
parent::register_hooks();
add_action( 'elementor/frontend/after_register_scripts', [ $this, 'register_scripts' ] );
add_action( 'elementor/frontend/after_register_styles', [ $this, 'register_styles' ] );
add_action( 'elementor/controls/register', [ $this, 'register_controls' ] );
}
}
Loading
Loading