PluginProbe
Elementor Website Builder – more than just a page builder / 3.27.0-dev2
Elementor Website Builder – more than just a page builder v3.27.0-dev2
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / modules / shapes / widgets / text-path.php

text-path.php in Elementor Website Builder – more than just a page builder 3.27.0-dev2, at modules/shapes/widgets/text-path.php

712 lines 14.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Elementor\Modules\Shapes\Widgets;
4
5 use Elementor\Controls_Manager;
6 use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
7 use Elementor\Group_Control_Typography;
8 use Elementor\Modules\Shapes\Module as Shapes_Module;
9 use Elementor\Group_Control_Text_Stroke;
10 use Elementor\Plugin;
11 use Elementor\Widget_Base;
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit; // Exit if accessed directly.
15 }
16
17 /**
18 * Elementor WordArt widget.
19 *
20 * Elementor widget that displays text along SVG path.
21 *
22 */
23 class TextPath extends Widget_Base {
24
25 const DEFAULT_PATH_FILL = '#E8178A';
26
27 /**
28 * Get widget name.
29 *
30 * Retrieve Text Path widget name.
31 *
32 * @return string Widget name.
33 * @access public
34 *
35 */
36 public function get_name() {
37 return 'text-path';
38 }
39
40 public function get_group_name() {
41 return 'shapes';
42 }
43
44 /**
45 * Get widget title.
46 *
47 * Retrieve Text Path widget title.
48 *
49 * @return string Widget title.
50 * @access public
51 *
52 */
53 public function get_title() {
54 return esc_html__( 'Text Path', 'elementor' );
55 }
56
57 /**
58 * Get widget icon.
59 *
60 * Retrieve Text Path widget icon.
61 *
62 * @return string Widget icon.
63 * @access public
64 *
65 */
66 public function get_icon() {
67 return 'eicon-wordart';
68 }
69
70 /**
71 * Get widget keywords.
72 *
73 * Retrieve the list of keywords the widget belongs to.
74 *
75 * @return array Widget keywords.
76 * @access public
77 *
78 */
79 public function get_keywords() {
80 return [ 'text path', 'word path', 'text on path', 'wordart', 'word art' ];
81 }
82
83 /**
84 * Get style dependencies.
85 *
86 * Retrieve the list of style dependencies the widget requires.
87 *
88 * @since 3.24.0
89 * @access public
90 *
91 * @return array Widget style dependencies.
92 */
93 public function get_style_depends(): array {
94 return [ 'widget-text-path' ];
95 }
96
97 public function has_widget_inner_wrapper(): bool {
98 return ! Plugin::$instance->experiments->is_feature_active( 'e_optimized_markup' );
99 }
100
101 /**
102 * Register content controls under content tab.
103 */
104 protected function register_content_tab() {
105 $this->start_controls_section(
106 'section_content_text_path',
107 [
108 'label' => esc_html__( 'Text Path', 'elementor' ),
109 'tab' => Controls_Manager::TAB_CONTENT,
110 ]
111 );
112
113 $this->add_control(
114 'text',
115 [
116 'label' => esc_html__( 'Text', 'elementor' ),
117 'type' => Controls_Manager::TEXT,
118 'label_block' => true,
119 'default' => esc_html__( 'Add Your Curvy Text Here', 'elementor' ),
120 'frontend_available' => true,
121 'render_type' => 'none',
122 'dynamic' => [
123 'active' => true,
124 ],
125 ]
126 );
127
128 $this->add_control(
129 'path',
130 [
131 'label' => esc_html__( 'Path Type', 'elementor' ),
132 'type' => Controls_Manager::SELECT,
133 'options' => Shapes_Module::get_paths(),
134 'default' => 'wave',
135 ]
136 );
137
138 $this->add_control(
139 'custom_path',
140 [
141 'label' => esc_html__( 'SVG', 'elementor' ),
142 'type' => Controls_Manager::MEDIA,
143 'media_types' => [
144 'svg',
145 ],
146 'condition' => [
147 'path' => 'custom',
148 ],
149 'dynamic' => [
150 'active' => true,
151 ],
152 'description' => sprintf(
153 '%1$s <a target="_blank" href="https://go.elementor.com/text-path-create-paths/">%2$s</a>',
154 esc_html__( 'Want to create custom text paths with SVG?', 'elementor' ),
155 esc_html__( 'Learn more', 'elementor' )
156 ),
157 ]
158 );
159
160 $this->add_control(
161 'link',
162 [
163 'label' => esc_html__( 'Link', 'elementor' ),
164 'type' => Controls_Manager::URL,
165 'label_block' => true,
166 'dynamic' => [
167 'active' => true,
168 ],
169 'placeholder' => esc_html__( 'Paste URL or type', 'elementor' ),
170 'frontend_available' => true,
171 ]
172 );
173
174 $this->add_responsive_control(
175 'align',
176 [
177 'label' => esc_html__( 'Alignment', 'elementor' ),
178 'type' => Controls_Manager::CHOOSE,
179 'default' => '',
180 'options' => [
181 'left' => [
182 'title' => esc_html__( 'Left', 'elementor' ),
183 'icon' => 'eicon-text-align-left',
184 ],
185 'center' => [
186 'title' => esc_html__( 'Center', 'elementor' ),
187 'icon' => 'eicon-text-align-center',
188 ],
189 'right' => [
190 'title' => esc_html__( 'Right', 'elementor' ),
191 'icon' => 'eicon-text-align-right',
192 ],
193 ],
194 'selectors' => [
195 '{{WRAPPER}}' => '--alignment: {{VALUE}}',
196 ],
197 'frontend_available' => true,
198 ]
199 );
200
201 $this->add_control(
202 'text_path_direction',
203 [
204 'label' => esc_html__( 'Text Direction', 'elementor' ),
205 'type' => Controls_Manager::SELECT,
206 'default' => '',
207 'options' => [
208 '' => esc_html__( 'Default', 'elementor' ),
209 'rtl' => esc_html__( 'RTL', 'elementor' ),
210 'ltr' => esc_html__( 'LTR', 'elementor' ),
211 ],
212 'selectors' => [
213 '{{WRAPPER}}' => '--direction: {{VALUE}}',
214 ],
215 'frontend_available' => true,
216 ]
217 );
218
219 $this->add_control(
220 'show_path',
221 [
222 'label' => esc_html__( 'Show Path', 'elementor' ),
223 'type' => Controls_Manager::SWITCHER,
224 'label_on' => esc_html__( 'On', 'elementor' ),
225 'label_off' => esc_html__( 'Off', 'elementor' ),
226 'return_value' => self::DEFAULT_PATH_FILL,
227 'separator' => 'before',
228 'default' => '',
229 'selectors' => [
230 '{{WRAPPER}}' => '--path-stroke: {{VALUE}}; --path-fill: transparent;',
231 ],
232 ]
233 );
234
235 $this->end_controls_section();
236 }
237
238 /**
239 * Register style controls under style tab.
240 */
241 protected function register_style_tab() {
242 /**
243 * Text Path styling section.
244 */
245 $this->start_controls_section(
246 'section_style_text_path',
247 [
248 'label' => esc_html__( 'Text Path', 'elementor' ),
249 'tab' => Controls_Manager::TAB_STYLE,
250 ]
251 );
252
253 $this->add_responsive_control(
254 'size',
255 [
256 'label' => esc_html__( 'Size', 'elementor' ),
257 'type' => Controls_Manager::SLIDER,
258 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
259 'range' => [
260 '%' => [
261 'min' => 0,
262 'max' => 100,
263 'step' => 10,
264 ],
265 'px' => [
266 'max' => 800,
267 'step' => 50,
268 ],
269 ],
270 'default' => [
271 'size' => 500,
272 ],
273 'tablet_default' => [
274 'size' => 500,
275 ],
276 'mobile_default' => [
277 'size' => 500,
278 ],
279 'selectors' => [
280 '{{WRAPPER}}' => '--width: {{SIZE}}{{UNIT}};',
281 ],
282 ]
283 );
284
285 $this->add_responsive_control(
286 'rotation',
287 [
288 'label' => esc_html__( 'Rotate', 'elementor' ),
289 'type' => Controls_Manager::SLIDER,
290 'size_units' => [ 'deg', 'grad', 'rad', 'turn', 'custom' ],
291 'default' => [
292 'unit' => 'deg',
293 ],
294 'tablet_default' => [
295 'unit' => 'deg',
296 ],
297 'mobile_default' => [
298 'unit' => 'deg',
299 ],
300 'selectors' => [
301 '{{WRAPPER}}' => '--rotate: {{SIZE}}{{UNIT}};',
302 ],
303 ]
304 );
305
306 $this->add_control(
307 'text_heading',
308 [
309 'label' => esc_html__( 'Text', 'elementor' ),
310 'type' => Controls_Manager::HEADING,
311 ]
312 );
313
314 $this->add_group_control(
315 Group_Control_Typography::get_type(),
316 [
317 'name' => 'text_typography',
318 'selector' => '{{WRAPPER}}',
319 'global' => [
320 'default' => Global_Typography::TYPOGRAPHY_TEXT,
321 ],
322 'fields_options' => [
323 'font_size' => [
324 'default' => [
325 'size' => '20',
326 'unit' => 'px',
327 ],
328 'size_units' => [ 'px' ],
329 ],
330 // Text decoration isn't an inherited property, so it's required to explicitly
331 // target the specific `textPath` element.
332 'text_decoration' => [
333 'selectors' => [
334 '{{WRAPPER}} textPath' => 'text-decoration: {{VALUE}};',
335 ],
336 ],
337 ],
338 ]
339 );
340
341 $this->add_group_control(
342 Group_Control_Text_Stroke::get_type(),
343 [
344 'name' => 'text_stroke',
345 'selector' => '{{WRAPPER}} textPath',
346 ]
347 );
348
349 $this->add_responsive_control(
350 'word_spacing',
351 [
352 'label' => esc_html__( 'Word Spacing', 'elementor' ),
353 'type' => Controls_Manager::SLIDER,
354 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
355 'range' => [
356 'px' => [
357 'min' => -20,
358 'max' => 20,
359 ],
360 'em' => [
361 'min' => -1,
362 'max' => 1,
363 ],
364 'rem' => [
365 'min' => -1,
366 'max' => 1,
367 ],
368 ],
369 'default' => [
370 'size' => '',
371 ],
372 'tablet_default' => [
373 'size' => '',
374 ],
375 'mobile_default' => [
376 'size' => '',
377 ],
378 'selectors' => [
379 '{{WRAPPER}}' => '--word-spacing: {{SIZE}}{{UNIT}};',
380 ],
381 ]
382 );
383
384 $this->add_control(
385 'start_point',
386 [
387 'label' => esc_html__( 'Starting Point', 'elementor' ) . ' (%)',
388 'type' => Controls_Manager::SLIDER,
389 'size_units' => [ '%' ],
390 'range' => [
391 'px' => [
392 'min' => -100,
393 'max' => 100,
394 'step' => 1,
395 ],
396 ],
397 'default' => [
398 'unit' => '%',
399 'size' => 0,
400 ],
401 'frontend_available' => true,
402 'render_type' => 'none',
403 ]
404 );
405
406 $this->start_controls_tabs( 'text_style' );
407
408 /**
409 * Normal tab.
410 */
411 $this->start_controls_tab(
412 'text_normal',
413 [
414 'label' => esc_html__( 'Normal', 'elementor' ),
415 ]
416 );
417
418 $this->add_control(
419 'text_color_normal',
420 [
421 'label' => esc_html__( 'Color', 'elementor' ),
422 'type' => Controls_Manager::COLOR,
423 'default' => '',
424 'selectors' => [
425 '{{WRAPPER}}' => '--text-color: {{VALUE}};',
426 ],
427 ]
428 );
429
430 $this->end_controls_tab();
431
432 /**
433 * Hover tab.
434 */
435 $this->start_controls_tab(
436 'text_hover',
437 [
438 'label' => esc_html__( 'Hover', 'elementor' ),
439 ]
440 );
441
442 $this->add_control(
443 'text_color_hover',
444 [
445 'label' => esc_html__( 'Color', 'elementor' ),
446 'type' => Controls_Manager::COLOR,
447 'default' => '',
448 'selectors' => [
449 '{{WRAPPER}}' => '--text-color-hover: {{VALUE}};',
450 ],
451 ]
452 );
453
454 $this->add_control(
455 'hover_animation',
456 [
457 'label' => esc_html__( 'Hover Animation', 'elementor' ),
458 'type' => Controls_Manager::HOVER_ANIMATION,
459 ]
460 );
461
462 $this->add_control(
463 'hover_transition',
464 [
465 'label' => esc_html__( 'Transition Duration', 'elementor' ),
466 'type' => Controls_Manager::SLIDER,
467 'size_units' => [ 's', 'ms', 'custom' ],
468 'default' => [
469 'unit' => 's',
470 'size' => 0.3,
471 ],
472 'selectors' => [
473 '{{WRAPPER}}' => '--transition: {{SIZE}}{{UNIT}}',
474 ],
475 ]
476 );
477
478 $this->end_controls_tab();
479
480 $this->end_controls_tabs();
481
482 $this->end_controls_section();
483
484 /**
485 * Path styling section.
486 */
487 $this->start_controls_section(
488 'section_style_path',
489 [
490 'label' => esc_html__( 'Path', 'elementor' ),
491 'tab' => Controls_Manager::TAB_STYLE,
492 'condition' => [
493 'show_path!' => '',
494 ],
495 ]
496 );
497
498 $this->start_controls_tabs( 'path_style' );
499
500 /**
501 * Normal tab.
502 */
503 $this->start_controls_tab(
504 'path_normal',
505 [
506 'label' => esc_html__( 'Normal', 'elementor' ),
507 ]
508 );
509
510 $this->add_control(
511 'path_fill_normal',
512 [
513 'label' => esc_html__( 'Color', 'elementor' ),
514 'type' => Controls_Manager::COLOR,
515 'default' => '',
516 'selectors' => [
517 '{{WRAPPER}}' => '--path-fill: {{VALUE}};',
518 ],
519 ]
520 );
521
522 $this->add_control(
523 'stroke_heading_normal',
524 [
525 'label' => esc_html__( 'Stroke', 'elementor' ),
526 'type' => Controls_Manager::HEADING,
527 ]
528 );
529
530 $this->add_control(
531 'stroke_color_normal',
532 [
533 'label' => esc_html__( 'Color', 'elementor' ),
534 'type' => Controls_Manager::COLOR,
535 'default' => self::DEFAULT_PATH_FILL,
536 'selectors' => [
537 '{{WRAPPER}}' => '--stroke-color: {{VALUE}};',
538 ],
539 ]
540 );
541
542 $this->add_control(
543 'stroke_width_normal',
544 [
545 'label' => esc_html__( 'Width', 'elementor' ),
546 'type' => Controls_Manager::SLIDER,
547 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
548 'default' => [
549 'size' => 1,
550 ],
551 'range' => [
552 'px' => [
553 'min' => 1,
554 'max' => 20,
555 ],
556 'em' => [
557 'max' => 2,
558 ],
559 'rem' => [
560 'max' => 2,
561 ],
562 ],
563 'selectors' => [
564 '{{WRAPPER}}' => '--stroke-width: {{SIZE}}{{UNIT}}',
565 ],
566 ]
567 );
568
569 $this->end_controls_tab();
570
571 /**
572 * Hover tab.
573 */
574 $this->start_controls_tab(
575 'path_hover',
576 [
577 'label' => esc_html__( 'Hover', 'elementor' ),
578 ]
579 );
580
581 $this->add_control(
582 'path_fill_hover',
583 [
584 'label' => esc_html__( 'Color', 'elementor' ),
585 'type' => Controls_Manager::COLOR,
586 'default' => '',
587 'selectors' => [
588 '{{WRAPPER}}' => '--path-fill-hover: {{VALUE}};',
589 ],
590 ]
591 );
592
593 $this->add_control(
594 'stroke_heading_hover',
595 [
596 'label' => esc_html__( 'Stroke', 'elementor' ),
597 'type' => Controls_Manager::HEADING,
598 ]
599 );
600
601 $this->add_control(
602 'stroke_color_hover',
603 [
604 'label' => esc_html__( 'Color', 'elementor' ),
605 'type' => Controls_Manager::COLOR,
606 'default' => '',
607 'selectors' => [
608 '{{WRAPPER}}' => '--stroke-color-hover: {{VALUE}};',
609 ],
610 ]
611 );
612
613 $this->add_control(
614 'stroke_width_hover',
615 [
616 'label' => esc_html__( 'Width', 'elementor' ),
617 'type' => Controls_Manager::SLIDER,
618 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
619 'default' => [
620 'size' => '',
621 ],
622 'range' => [
623 'px' => [
624 'min' => 1,
625 'max' => 20,
626 ],
627 'em' => [
628 'max' => 2,
629 ],
630 'rem' => [
631 'max' => 2,
632 ],
633 ],
634 'selectors' => [
635 '{{WRAPPER}}' => '--stroke-width-hover: {{SIZE}}{{UNIT}}',
636 ],
637 ]
638 );
639
640 $this->add_control(
641 'stroke_transition',
642 [
643 'label' => esc_html__( 'Transition Duration', 'elementor' ),
644 'type' => Controls_Manager::SLIDER,
645 'size_units' => [ 's', 'ms', 'custom' ],
646 'default' => [
647 'unit' => 's',
648 'size' => 0.3,
649 ],
650 'selectors' => [
651 '{{WRAPPER}}' => '--stroke-transition: {{SIZE}}{{UNIT}}',
652 ],
653 ]
654 );
655
656 $this->end_controls_tab();
657
658 $this->end_controls_tabs();
659
660 $this->end_controls_section();
661 }
662
663 /**
664 * Register Text Path widget controls.
665 *
666 * Adds different input fields to allow the user to change and customize the widget settings.
667 *
668 * @access protected
669 */
670 protected function register_controls() {
671 $this->register_content_tab();
672 $this->register_style_tab();
673 }
674
675 /**
676 * Render Text Path widget output on the frontend.
677 *
678 * Written in PHP and used to generate the final HTML.
679 *
680 * @access protected
681 */
682 protected function render() {
683 $settings = $this->get_settings_for_display();
684
685 // Get the path URL.
686 $path_url = ( 'custom' === $settings['path'] )
687 ? wp_get_attachment_url( $settings['custom_path']['id'] )
688 : Shapes_Module::get_path_url( $settings['path'] );
689
690 // Remove the HTTP protocol to prevent Mixed Content error.
691 $path_url = preg_replace( '/^https?:/i', '', $path_url );
692
693 // Add Text Path attributes.
694 $this->add_render_attribute( 'text_path', [
695 'class' => 'e-text-path',
696 'data-text' => htmlentities( esc_attr( $settings['text'] ) ),
697 'data-url' => esc_url( $path_url ),
698 'data-link-url' => esc_url( $settings['link']['url'] ?? '' ),
699 ] );
700
701 // Add hover animation.
702 if ( ! empty( $settings['hover_animation'] ) ) {
703 $this->add_render_attribute( 'text_path', 'class', 'elementor-animation-' . $settings['hover_animation'] );
704 }
705
706 // Render.
707 ?>
708 <div <?php $this->print_render_attribute_string( 'text_path' ); ?>></div>
709 <?php
710 }
711 }
712