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