PluginProbe ʕ •ᴥ•ʔ
Essential Addons for Elementor – Popular Elementor Templates & Widgets / 6.6.9
Essential Addons for Elementor – Popular Elementor Templates & Widgets v6.6.9
6.6.9 6.6.8 6.6.7 6.6.6 6.6.5 6.6.4 6.6.3 5.7.3 5.7.4 5.8.0 5.8.1 5.8.10 5.8.11 5.8.12 5.8.13 5.8.14 5.8.15 5.8.16 5.8.18 5.8.2 5.8.3 5.8.4 5.8.5 5.8.6 5.8.7 5.8.8 5.8.9 5.9.0 5.9.1 5.9.10 5.9.11 5.9.12 5.9.13 5.9.14 5.9.15 5.9.16 5.9.17 5.9.18 5.9.19 5.9.2 5.9.20 5.9.21 5.9.22 5.9.23 5.9.24 5.9.25 5.9.26 5.9.27 5.9.3 5.9.4 5.9.5 5.9.6 5.9.7 5.9.8 5.9.9 6.0.0 6.0.1 6.0.10 6.0.11 6.0.12 6.0.13 6.0.14 6.0.15 6.0.2 6.0.3 6.0.4 6.0.5 6.0.6 6.0.7 6.0.8 6.0.9 6.1.0 6.1.1 6.1.10 6.1.11 trunk 6.1.12 1.0.0 6.1.13 1.0.1 6.1.14 1.1.0 6.1.15 2.0 6.1.17 2.1 6.1.18 2.10.0 6.1.19 2.10.1 6.1.2 2.10.2 6.1.20 2.10.3 6.1.3 2.10.4 6.1.4 2.10.5 6.1.5 2.2.0 6.1.6 2.2.1 6.1.7 2.2.2 6.1.8 2.2.3 6.1.9 2.2.4 6.2.0 2.2.5 6.2.1 2.3.0 6.2.2 2.3.1 6.2.3 2.4.0 6.2.4 2.4.1 6.3.0 2.4.2 6.3.1 2.4.3 6.3.2 2.5.0 6.3.3 2.6.0 6.4.0 2.7.0 6.5.0 2.7.1 6.5.1 2.7.10 6.5.10 2.7.11 6.5.11 2.7.2 6.5.12 2.7.3 6.5.13 2.7.4 6.5.2 2.7.5 6.5.3 2.7.6 6.5.4 2.7.7 6.5.5 2.7.8 6.5.6 2.7.9 6.5.7 2.8.0 6.5.8 2.8.1 6.5.9 2.8.2 6.6.0 2.8.3 6.6.1 2.8.4 6.6.2 2.8.5 2.8.6 2.8.7 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 2.9.8 2.9.9 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.4.1 3.1.5 3.2.0 3.3.0 3.3.1 3.3.2 3.3.3 3.4.0 3.5.0 3.5.1 3.5.2 3.6.0 3.6.1 3.6.2 3.7.0 3.7.1 3.7.2 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.2.0 4.2.1 4.2.2 4.2.3 4.2.4 4.3.0 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.3.8 4.3.9 4.4.0 4.4.1 4.5.0 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.6.6 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.7.5 4.8.0 4.8.1 4.8.2 4.8.3 4.8.4 4.9.0 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 4.9.6 4.9.7 5.0.0 5.0.1 5.0.10 5.0.11 5.0.12 5.0.13 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.0.9 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.2.0 5.2.1 5.2.2 5.2.3 5.2.4 5.3.0 5.3.1 5.3.2 5.4.6 5.5.5 5.6.5 5.7.2
essential-addons-for-elementor-lite / includes / Extensions / Image_Masking.php
essential-addons-for-elementor-lite / includes / Extensions Last commit date
Custom_JS.php 1 year ago Hover_Effect.php 1 year ago Image_Masking.php 2 months ago Liquid_Glass_Effect.php 5 months ago Post_Duplicator.php 2 months ago Promotion.php 9 months ago Reading_Progress.php 5 months ago Scroll_to_Top.php 5 months ago Table_of_Content.php 2 weeks ago Vertical_Text_Orientation.php 7 months ago Wrapper_Link.php 2 months ago index.php 3 years ago
Image_Masking.php
640 lines
1 <?php
2
3 namespace Essential_Addons_Elementor\Extensions;
4
5 use Elementor\Controls_Manager;
6
7 if ( ! defined( 'ABSPATH' ) ) {
8 exit;
9 }
10
11 class Image_Masking {
12
13 private static $svg_dir_url = EAEL_PLUGIN_URL . 'assets/front-end/img/image-masking/svg-shapes/';
14 /**
15 * Initialize hooks
16 */
17 public function __construct() {
18 add_action( 'elementor/element/column/section_advanced/after_section_end', [ $this, 'register_controls' ] );
19 add_action( 'elementor/element/section/section_advanced/after_section_end', [ $this, 'register_controls' ] );
20 add_action( 'elementor/element/container/section_layout/after_section_end', [ $this, 'register_controls' ] );
21 add_action( 'elementor/element/common/_section_style/after_section_end', [ $this, 'register_controls' ] );
22 add_action( 'elementor/frontend/before_render', [ $this, 'before_render' ], 100 );
23 add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
24 add_filter( 'elementor/document/element/replace_id', [ $this, 'cleanup_settings_data' ] );
25 add_filter( 'elementor/document/save/data', [ $this, 'cleanup_settings_data' ] );
26 }
27
28 public function cleanup_settings_data( $element_data ) {
29
30 $prefixes = [
31 'eael_image_masking_',
32 'eael_clip_',
33 'eael_svg_paths_',
34 'eael_image_morphing_'
35 ];
36
37 $clean_settings = function ( &$settings ) use ( $prefixes ) {
38 if ( empty( $settings[ 'eael_enable_image_masking' ] ) || 'yes' !== $settings[ 'eael_enable_image_masking' ] ) {
39 foreach ( array_keys( $settings ) as $key ) {
40 foreach ( $prefixes as $prefix ) {
41 if ( strncmp( $key, $prefix, \strlen( $prefix ) ) === 0 ) {
42 unset( $settings[ $key ] );
43 }
44 }
45 }
46 }
47
48 // TODO: Remove this block after several versions once existing sites have re-saved and eael_svg_path is no longer present in the DB.
49 // Strip legacy eael_svg_path key from repeater items (replaced by eael_svg_code)
50 if ( ! empty( $settings['eael_svg_paths_custom'] ) && \is_array( $settings['eael_svg_paths_custom'] ) ) {
51 foreach ( $settings['eael_svg_paths_custom'] as &$item ) {
52 unset( $item['eael_svg_path'] );
53 }
54 unset( $item );
55 }
56 };
57
58 $walk = function ( &$element ) use ( &$walk, $clean_settings ) {
59
60 if ( isset( $element['settings'] ) ) {
61 $clean_settings( $element['settings'] );
62 }
63
64 if ( isset( $element['page_settings'] ) ) {
65 $clean_settings( $element['page_settings'] );
66 }
67
68 if ( ! empty( $element['elements'] ) ) {
69 foreach ( $element['elements'] as &$child ) {
70 $walk( $child );
71 }
72 }
73 };
74
75 $walk( $element_data );
76
77 return $element_data;
78 }
79
80 public function enqueue_scripts() {
81 $data = [ 'svg_dir_url' => self::$svg_dir_url ];
82 wp_localize_script( 'elementor-frontend', 'EAELImageMaskingConfig', $data );
83 }
84
85 private function clip_paths( $shape ){
86 $shapes = [
87 'bavel' => 'polygon(20% 0%, 80% 0%, 100% 20%, 100% 80%, 80% 100%, 20% 100%, 0% 80%, 0% 20%)',
88 'rabbet' => 'polygon(0% 15%, 15% 15%, 15% 0%, 85% 0%, 85% 15%, 100% 15%, 100% 85%, 85% 85%, 85% 100%, 15% 100%, 15% 85%, 0% 85%)',
89 'chevron-left' => 'polygon(100% 0%, 75% 50%, 100% 100%, 25% 100%, 0% 50%, 25% 0%)',
90 'chevron-right' => 'polygon(75% 0%, 100% 50%, 75% 100%, 0% 100%, 25% 50%, 0% 0%)',
91 'star' => 'polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%)',
92 ];
93 return $shapes[$shape] ?? '';
94 }
95 private function masking_controllers( $element, $tab = '' ) {
96
97 $condition = [];
98 if( '_hover' === $tab ) {
99 $element->add_control(
100 'eael_image_masking_hover_effect',
101 [
102 'label' => esc_html__( 'Enable', 'essential-addons-for-elementor-lite' ),
103 'type' => Controls_Manager::SWITCHER,
104 'return_value' => 'yes',
105 ]
106 );
107 $condition = [
108 'eael_image_masking_hover_effect' => 'yes',
109 ];
110 }
111
112 $condition['eael_image_masking_type'] = 'clip';
113 $image_dir_url = EAEL_PLUGIN_URL . 'assets/front-end/img/image-masking/clip-paths/';
114 $element->add_control(
115 'eael_image_masking_clip_path' . $tab,
116 [
117 'label' => esc_html__( 'Select Clip Path', 'essential-addons-for-elementor-lite' ),
118 'label_block' => true,
119 'type' => Controls_Manager::CHOOSE,
120 'options' => [
121 'bavel' => [
122 'title' => esc_html__( 'Bavel', 'essential-addons-for-elementor-lite' ),
123 'image' => $image_dir_url . 'bavel.svg',
124 ],
125 'rabbet' => [
126 'title' => esc_html__( 'Rabbet', 'essential-addons-for-elementor-lite' ),
127 'image' => $image_dir_url . 'rabbet.svg',
128 ],
129 'chevron-left' => [
130 'title' => esc_html__( 'Chevron Left', 'essential-addons-for-elementor-lite' ),
131 'image' => $image_dir_url . 'chevron-left.svg',
132 ],
133 'chevron-right' => [
134 'title' => esc_html__( 'Chevron Right', 'essential-addons-for-elementor-lite' ),
135 'image' => $image_dir_url . 'chevron-right.svg',
136 ],
137 'star' => [
138 'title' => esc_html__( 'Start', 'essential-addons-for-elementor-lite' ),
139 'image' => $image_dir_url . 'star.svg',
140 ],
141 ],
142 'default' => 'bavel',
143 'toggle' => false,
144 'image_choose' => true,
145 'css_class' => 'eael-image-masking-choose',
146 'condition' => array_merge( $condition, [ 'eael_image_masking_enable_custom_clip_path' . $tab . '!' => 'yes' ] )
147 ]
148 );
149
150 $element->add_control(
151 'eael_image_masking_enable_custom_clip_path' . $tab,
152 [
153 'label' => esc_html__( 'Use Custom Clip Path', 'essential-addons-for-elementor-lite' ),
154 'type' => Controls_Manager::SWITCHER,
155 'return_value' => 'yes',
156 'condition' => $condition,
157 ]
158 );
159
160 $element->add_control(
161 'eael_image_masking_custom_clip_path' . $tab,
162 [
163 'label' => '',
164 'type' => Controls_Manager::TEXTAREA,
165 'rows' => 10,
166 'label_block' => true,
167 'dynamic' => [
168 'active' => false,
169 ],
170 'ai' => [
171 'active' => false,
172 ],
173 'default' => 'clip-path: polygon(50% 0%, 80% 10%, 100% 35%, 100% 70%, 80% 90%, 50% 100%, 20% 90%, 0% 70%, 0% 35%, 20% 10%);',
174 'placeholder' => 'clip-path: polygon(50% 0%, 0% 100%, 100% 100%);',
175 'description' => __( 'Enter your custom clip path value. You can use <a href = "https://bennettfeely.com/clippy/" target = "_blank">Clippy</a> to generate your custom clip path.', 'essential-addons-for-elementor-lite' ),
176 'condition' => array_merge( $condition, [ 'eael_image_masking_enable_custom_clip_path' . $tab => 'yes' ] ),
177 ]
178 );
179
180 $condition = [ 'eael_image_masking_type' => 'image' ];
181 if( '_hover' === $tab ){
182 $condition['eael_image_masking_hover_effect'] = 'yes';
183 }
184
185 $svg_url = EAEL_PLUGIN_URL . 'assets/front-end/img/image-masking/svg-shapes/';
186 $element->add_control(
187 'eael_image_masking_svg' . $tab,
188 [
189 'label' => esc_html__( 'Choose Shape', 'essential-addons-for-elementor-lite' ),
190 'label_block' => true,
191 'type' => Controls_Manager::CHOOSE,
192 'options' => [
193 'polygon' => [
194 'title' => esc_html__( 'Polygon', 'essential-addons-for-elementor-lite' ),
195 'image' => $svg_url . 'polygon.svg',
196 ],
197 'rounded' => [
198 'title' => esc_html__( 'Rounded', 'essential-addons-for-elementor-lite' ),
199 'image' => $svg_url . 'rounded.svg',
200 ],
201 'arch-down' => [
202 'title' => esc_html__( 'Arch Down', 'essential-addons-for-elementor-lite' ),
203 'image' => $svg_url . 'arch-down.svg',
204 ],
205 'arch-group' => [
206 'title' => esc_html__( 'Arch Group', 'essential-addons-for-elementor-lite' ),
207 'image' => $svg_url . 'arch-group.svg',
208 ],
209 'arch-up' => [
210 'title' => esc_html__( 'Arch Up', 'essential-addons-for-elementor-lite' ),
211 'image' => $svg_url . 'arch-up.svg',
212 ],
213 'asterisk' => [
214 'title' => esc_html__( 'Asterisk', 'essential-addons-for-elementor-lite' ),
215 'image' => $svg_url . 'asterisk.svg',
216 ],
217 'blob' => [
218 'title' => esc_html__( 'Blob', 'essential-addons-for-elementor-lite' ),
219 'image' => $svg_url . 'blob.svg',
220 ],
221 'blocks' => [
222 'title' => esc_html__( 'Blocks', 'essential-addons-for-elementor-lite' ),
223 'image' => $svg_url . 'blocks.svg',
224 ],
225 'brash-1' => [
226 'title' => esc_html__( 'Brash 1', 'essential-addons-for-elementor-lite' ),
227 'image' => $svg_url . 'brash-1.svg',
228 ],
229 'brash-2' => [
230 'title' => esc_html__( 'Brash 2', 'essential-addons-for-elementor-lite' ),
231 'image' => $svg_url . 'brash-2.svg',
232 ],
233 'brash-3' => [
234 'title' => esc_html__( 'Brash 3', 'essential-addons-for-elementor-lite' ),
235 'image' => $svg_url . 'brash-3.svg',
236 ],
237 'burst' => [
238 'title' => esc_html__( 'Burst', 'essential-addons-for-elementor-lite' ),
239 'image' => $svg_url . 'burst.svg',
240 ],
241 'chat' => [
242 'title' => esc_html__( 'Chat', 'essential-addons-for-elementor-lite' ),
243 'image' => $svg_url . 'chat.svg',
244 ],
245 'hex-tile' => [
246 'title' => esc_html__( 'Hex Tile', 'essential-addons-for-elementor-lite' ),
247 'image' => $svg_url . 'hex-tile.svg',
248 ],
249 'leaf' => [
250 'title' => esc_html__( 'Leaf', 'essential-addons-for-elementor-lite' ),
251 'image' => $svg_url . 'leaf.svg',
252 ],
253 'oval' => [
254 'title' => esc_html__( 'Oval', 'essential-addons-for-elementor-lite' ),
255 'image' => $svg_url . 'oval.svg',
256 ],
257 'pixel-cross' => [
258 'title' => esc_html__( 'Pixel Cross', 'essential-addons-for-elementor-lite' ),
259 'image' => $svg_url . 'pixel-cross.svg',
260 ],
261 'quote' => [
262 'title' => esc_html__( 'Quote', 'essential-addons-for-elementor-lite' ),
263 'image' => $svg_url . 'quote.svg',
264 ],
265 'star-dimond' => [
266 'title' => esc_html__( 'Star Diamond', 'essential-addons-for-elementor-lite' ),
267 'image' => $svg_url . 'star-dimond.svg',
268 ],
269 'upload' => [
270 'title' => esc_html__( 'Upload', 'essential-addons-for-elementor-lite' ),
271 'image' => $svg_url . 'upload.svg',
272 'fullwidth' => true,
273 ],
274 ],
275 'toggle' => false,
276 'image_choose' => true,
277 'css_class' => 'eael-image-masking-choose col-5',
278 'default' => 'polygon',
279 'condition' => $condition
280 ]
281 );
282
283 if ( !apply_filters('eael/pro_enabled', false ) ) {
284 $element->add_control(
285 'eael_image_masking_upload_pro_message' . $tab,
286 [
287 'label' => '',
288 'type' => Controls_Manager::RAW_HTML,
289 'raw' => '<div class="ea-nerd-box">
290 <div class="ea-nerd-box-message">' . __('This feature is available in the pro version.', 'essential-addons-for-elementor-lite') . '</div>
291 <a class="ea-nerd-box-link elementor-button elementor-button-default" href="https://wpdeveloper.com/upgrade/ea-pro" target="_blank">
292 ' . __('Upgrade to EA PRO', 'essential-addons-for-elementor-lite') . '
293 </a>
294 </div>',
295 'content_classes' => 'eael-pro-notice',
296 'condition' => array_merge( $condition, [ 'eael_image_masking_svg' . $tab => 'upload' ] )
297 ]
298 );
299 } else {
300 do_action( 'eael/image-masking/image_control', $element, array_merge( $condition, [ 'eael_image_masking_svg' . $tab => 'upload' ] ), $tab );
301 }
302
303 if( '_hover' === $tab ){
304 $element->add_control(
305 'eael_image_masking_hover_selector',
306 [
307 'label' => esc_html__( 'Hover Selector', 'essential-addons-for-elementor-lite' ),
308 'type' => Controls_Manager::TEXT,
309 'label_block' => true,
310 'dynamic' => [
311 'active' => false,
312 ],
313 'ai' => [
314 'active' => true,
315 ],
316 'placeholder' => '.not-masked-element, #not-masked-element',
317 'description' => __( 'Enter the selector for the element you want to apply the hover effect on. If you leave this field empty, the hover effect will be applied on hover for full section.', 'essential-addons-for-elementor-lite' ),
318 'condition' => [
319 'eael_image_masking_hover_effect' => 'yes',
320 ]
321 ]
322 );
323 }
324 }
325
326 public function register_controls( $element ) {
327 $element->start_controls_section(
328 'eael_image_masking_section',
329 [
330 'label' => __( '<i class="eaicon-logo"></i> Image Masking', 'essential-addons-for-elementor-lite' ),
331 'tab' => Controls_Manager::TAB_ADVANCED
332 ]
333 );
334
335 $element->add_control(
336 'eael_enable_image_masking',
337 [
338 'label' => __( 'Enable Image Masking', 'essential-addons-for-elementor-lite' ),
339 'type' => Controls_Manager::SWITCHER
340 ]
341 );
342
343 $element->add_control(
344 'eael_image_masking_type',
345 [
346 'label' => esc_html__( 'Type', 'essential-addons-for-elementor-lite' ),
347 'type' => Controls_Manager::CHOOSE,
348 'options' => [
349 'image' => [
350 'title' => esc_html__( 'Image/SVG Masking', 'essential-addons-for-elementor-lite' ),
351 'icon' => 'eicon-image',
352 ],
353 'clip' => [
354 'title' => esc_html__( 'Clip Path', 'essential-addons-for-elementor-lite' ),
355 'icon' => 'eicon-integration',
356 ],
357 'morphing' => [
358 'title' => esc_html__( 'Morphing', 'essential-addons-for-elementor-lite' ),
359 'icon' => 'eicon-animation',
360 ]
361 ],
362 'condition' => [
363 'eael_enable_image_masking' => 'yes'
364 ],
365 'default' => 'clip',
366 'toggle' => false,
367 ]
368 );
369
370 $element->start_controls_tabs( 'eael_image_masking_tabs', [
371 'condition' => [
372 'eael_enable_image_masking' => 'yes',
373 'eael_image_masking_type!' => 'morphing'
374 ]
375 ] );
376
377 $element->start_controls_tab(
378 'eael_image_masking_normal_tab',
379 [
380 'label' => esc_html__( 'Normal', 'essential-addons-for-elementor-lite' ),
381 ]
382 );
383
384 $this->masking_controllers( $element );
385
386 $element->end_controls_tab();
387
388 $element->start_controls_tab(
389 'eael_image_masking_hover_tab',
390 [
391 'label' => esc_html__( 'Hover', 'essential-addons-for-elementor-lite' ),
392 ]
393 );
394
395 $this->masking_controllers( $element, '_hover' );
396
397 $element->end_controls_tab();
398
399 $element->end_controls_tabs();
400
401 $element->add_control(
402 'eael_image_masking_image_size',
403 [
404 'label' => esc_html__( 'Size', 'essential-addons-for-elementor-lite' ),
405 'type' => Controls_Manager::SELECT,
406 'default' => 'contain',
407 'options' => [
408 '' => esc_html__( 'Default', 'essential-addons-for-elementor-lite' ),
409 'auto' => esc_html__( 'Auto', 'essential-addons-for-elementor-lite' ),
410 'cover' => esc_html__( 'Cover', 'essential-addons-for-elementor-lite' ),
411 'contain' => esc_html__( 'Contain', 'essential-addons-for-elementor-lite' ),
412 'custom' => esc_html__( 'Custom', 'essential-addons-for-elementor-lite' ),
413 ],
414 'condition' => [
415 'eael_enable_image_masking' => 'yes',
416 'eael_image_masking_type' => 'image'
417 ],
418 'selectors' => [
419 '{{WRAPPER}} img' => 'mask-size: {{VALUE}}; -webkit-mask-size: {{VALUE}};',
420 ],
421 ]
422 );
423
424 $element->add_control(
425 'eael_image_masking_image_custom_size_custom',
426 [
427 'label' => '',
428 'type' => Controls_Manager::SLIDER,
429 'size_units' => [ 'px', '%' ],
430 'range' => [
431 'px' => [
432 'min' => 0,
433 'max' => 1000,
434 'step' => 5,
435 ],
436 '%' => [
437 'min' => 0,
438 'max' => 100,
439 ],
440 ],
441 'selectors' => [
442 '{{WRAPPER}} img' => 'mask-size: {{SIZE}}{{UNIT}}; -webkit-mask-size: {{SIZE}}{{UNIT}};',
443 ],
444 'condition' => [
445 'eael_enable_image_masking' => 'yes',
446 'eael_image_masking_type' => 'image',
447 'eael_image_masking_image_size' => 'custom'
448 ],
449 ]
450 );
451
452 $element->add_control(
453 'eael_image_masking_image_position',
454 [
455 'label' => esc_html__( 'Position', 'essential-addons-for-elementor-lite' ),
456 'type' => Controls_Manager::SELECT,
457 'default' => 'center center',
458 'options' => [
459 '' => esc_html__( 'Default', 'essential-addons-for-elementor-lite' ),
460 'left top' => esc_html__( 'Left Top', 'essential-addons-for-elementor-lite' ),
461 'left center' => esc_html__( 'Left Center', 'essential-addons-for-elementor-lite' ),
462 'left bottom' => esc_html__( 'Left Bottom', 'essential-addons-for-elementor-lite' ),
463 'center top' => esc_html__( 'Center Top', 'essential-addons-for-elementor-lite' ),
464 'center center' => esc_html__( 'Center Center', 'essential-addons-for-elementor-lite' ),
465 'center bottom' => esc_html__( 'Center Bottom', 'essential-addons-for-elementor-lite' ),
466 'right top' => esc_html__( 'Right Top', 'essential-addons-for-elementor-lite' ),
467 'right center' => esc_html__( 'Right Center', 'essential-addons-for-elementor-lite' ),
468 'right bottom' => esc_html__( 'Right Bottom', 'essential-addons-for-elementor-lite' )
469 ],
470 'condition' => [
471 'eael_enable_image_masking' => 'yes',
472 'eael_image_masking_type' => 'image'
473 ],
474 'selectors' => [
475 '{{WRAPPER}} img' => 'mask-position: {{VALUE}}; -webkit-mask-position: {{VALUE}};',
476 ],
477 ]
478 );
479
480 $element->add_control(
481 'eael_image_masking_image_repeat',
482 [
483 'label' => esc_html__( 'Repeat', 'essential-addons-for-elementor-lite' ),
484 'type' => Controls_Manager::SELECT,
485 'default' => 'no-repeat',
486 'options' => [
487 'no-repeat' => esc_html__( 'No-repeat', 'essential-addons-for-elementor-lite' ),
488 'repeat' => esc_html__( 'Repeat', 'essential-addons-for-elementor-lite' ),
489 'repeat-x' => esc_html__( 'Repeat-x', 'essential-addons-for-elementor-lite' ),
490 'repeat-y' => esc_html__( 'Repeat-y', 'essential-addons-for-elementor-lite' ),
491 ],
492 'condition' => [
493 'eael_enable_image_masking' => 'yes',
494 'eael_image_masking_type' => 'image'
495 ],
496 'selectors' => [
497 '{{WRAPPER}} img' => 'mask-repeat: {{VALUE}}; -webkit-mask-repeat: {{VALUE}};',
498 ],
499 ]
500 );
501
502 if ( !apply_filters('eael/pro_enabled', false ) ) {
503 $element->add_control(
504 'eael_image_masking_pro_message',
505 [
506 'label' => '',
507 'type' => Controls_Manager::RAW_HTML,
508 'raw' => '<div class="ea-nerd-box">
509 <div class="ea-nerd-box-message">' . __('This feature is available in the pro version.', 'essential-addons-for-elementor-lite') . '</div>
510 <a class="ea-nerd-box-link elementor-button elementor-button-default" href="https://wpdeveloper.com/upgrade/ea-pro" target="_blank">
511 ' . __('Upgrade to EA PRO', 'essential-addons-for-elementor-lite') . '
512 </a>
513 </div>',
514 'content_classes' => 'eael-pro-notice',
515 'condition' => [
516 'eael_enable_image_masking' => 'yes',
517 'eael_image_masking_type' => 'morphing'
518 ]
519 ]
520 );
521 } else {
522 do_action( 'eael/image_masking/morphing_controls', $element );
523 }
524
525 $element->end_controls_section();
526 }
527
528 private function extract_first_path_d($svg) {
529 // Try DOM first
530 libxml_use_internal_errors(true);
531 $dom = new \DOMDocument();
532 if (@$dom->loadXML($svg)) {
533 $path = $dom->getElementsByTagName('path')->item(0);
534 if ($path) {
535 return $path->getAttribute('d');
536 }
537 }
538
539 // Regex fallback
540 if (preg_match('/<path[^>]+d="([^"]+)"/i', $svg, $match)) {
541 return $match[1];
542 }
543
544 return null; // not found
545 }
546 public function before_render( $element ) {
547 $is_enabled = $element->get_settings_for_display( 'eael_enable_image_masking' );
548 $settings = $element->get_settings_for_display();
549
550 if ( 'yes' === $is_enabled ) {
551 $type = $settings['eael_image_masking_type'];
552 $element_id = $element->get_id();
553 $style = '';
554 $element->add_render_attribute( '_wrapper', 'class', 'eael-image-masking-' . esc_attr( $element_id ) );
555 if( 'clip' === $type ){
556 $clip_path_value = '';
557 if( 'yes' === $settings['eael_image_masking_enable_custom_clip_path'] ){
558 $clip_path_value = $settings['eael_image_masking_custom_clip_path'];
559 $clip_path_value = str_replace( 'clip-path: ', '', $clip_path_value );
560 } else {
561 $clip_path = $settings['eael_image_masking_clip_path'];
562 $clip_path_value = $this->clip_paths( $clip_path );
563 }
564 if( $clip_path_value ) {
565 $style .= '.eael-image-masking-'. esc_html( $element_id ) .' img {clip-path: '.$clip_path_value.'}';
566 }
567
568 if( 'yes' === $settings['eael_image_masking_hover_effect'] ){
569 $hover_clip_path_value = '';
570 if( 'yes' === $settings['eael_image_masking_enable_custom_clip_path_hover'] ){
571 $hover_clip_path_value = $settings['eael_image_masking_custom_clip_path_hover'];
572 $hover_clip_path_value = str_replace( 'clip-path: ', '', $hover_clip_path_value );
573 } else {
574 $hover_clip_path = $settings['eael_image_masking_clip_path_hover'];
575 $hover_clip_path_value = $this->clip_paths( $hover_clip_path );
576 }
577 if( $hover_clip_path_value ) {
578 $hover_selector = $settings['eael_image_masking_hover_selector'];
579 if( $hover_selector ){
580 $hover_selector = ' ' . trim( $hover_selector );
581 }
582 $style .= '.eael-image-masking-'. esc_html( $element_id ) . $hover_selector . ':hover img {clip-path: '.$hover_clip_path_value.'}';
583 }
584 }
585 } else if( 'image' === $type ) {
586 $svg = $element->get_settings_for_display( 'eael_image_masking_svg' );
587 $mask_url = '';
588 if( 'upload' !== $svg ){
589 $svg_url = self::$svg_dir_url;
590 $mask_url = $svg_url . $svg . '.svg';
591 } else if( 'upload' === $svg ){
592 $image = $element->get_settings_for_display( 'eael_image_masking_image' );
593 $mask_url = isset( $image['url'] ) ? $image['url'] : '';
594 }
595
596 if( $mask_url ) {
597 $style .= '.eael-image-masking-'. esc_html( $element_id ) .' img {mask-image: url('.$mask_url.'); -webkit-mask-image: url('.$mask_url.');}';
598 }
599
600 if( 'yes' === $settings['eael_image_masking_hover_effect'] ){
601 $hover_image = $element->get_settings_for_display( 'eael_image_masking_svg_hover' );
602 $hover_mask_url = '';
603 if( 'upload' !== $hover_image ){
604 $svg = $element->get_settings_for_display( 'eael_image_masking_svg' );
605 $svg_url = self::$svg_dir_url;
606 $hover_mask_url = $svg_url . $hover_image . '.svg';
607 } else if( 'upload' === $hover_image ){
608 $hover_image = $element->get_settings_for_display( 'eael_image_masking_image_hover' );
609 $hover_mask_url = $hover_image['url'] ?? '';
610 }
611 if( $hover_mask_url ) {
612 $hover_selector = $element->get_settings_for_display( 'eael_image_masking_hover_selector' );
613 if( $hover_selector ){
614 $hover_selector = ' ' . trim( $hover_selector );
615 }
616 $style .= '.eael-image-masking-'. esc_html( $element_id ) . $hover_selector .':hover img {mask-image: url('.$hover_mask_url.'); -webkit-mask-image: url('.$hover_mask_url.');}';
617 }
618 }
619
620 } else if( 'morphing' === $type ) {
621 $morphing_options = apply_filters( 'eael/image_masking/morphing_options', [], $element, $element_id );
622 if( !empty( $morphing_options ) ){
623 if( !empty( $morphing_options['svg_html'] ) ){
624 //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
625 echo $morphing_options['svg_html'];
626 }
627 unset( $morphing_options['svg_html'] );
628 $element->add_render_attribute( '_wrapper', 'data-morphing-options', wp_json_encode( $morphing_options ) );
629 $element->add_render_attribute( '_wrapper', 'class', 'eael-morphing-enabled' );
630 }
631 }
632
633
634 if( $style ){
635 //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
636 echo '<style id="eael-image-masking-'. esc_attr( $element_id ) .'">'. $style .'</style>';
637 }
638 }
639 }
640 }