PluginProbe
Elementor Website Builder – more than just a page builder / 4.0.9
Elementor Website Builder – more than just a page builder v4.0.9
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 4.0.9, at modules/shapes/widgets/text-path.php

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