楼梯台阶文字效果 CSS

发布于 2025-01-17 15:05:23 字数 254 浏览 4 评论 0 原文

我正在尝试创建与 Adob​​e Illustrator 称为“楼梯台阶”文本效果相同的效果。

我还想在文本字段中键入内容时使用此文本效果,因此文本和效果对于键入的任何内容都应该是动态的。

彩虹与楼梯

我只找到了如何制作“彩虹”文字效果。

有谁知道如何编写这个代码?

太感谢了!

I'm trying to create the same effect Adobe Illustrator has called "Stair Step" text effect.

I also want to use this text effect while I'm typing in a text field, so both the text and the effect should be dynamic to whatever is being typed.

Rainbow vs. Stair Step

I have only found how to make the "Rainbow" text effect.

Does anyone know how to code this?

Thank you so much!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

晚雾 2025-01-24 15:05:23

使用 arctext.js 将节省您的时间和简单。

演示: 1 2 3

/**
 * Arctext.js
 * A jQuery plugin for curved text
 * http://www.codrops.com
 *
 * Copyright 2011, Pedro Botelho / Codrops
 * Free to use under the MIT license.
 *
 * Date: Mon Jan 23 2012
 */

(function( $, undefined ) {
    
    /*! 
    * FitText.js 1.0
    *
    * Copyright 2011, Dave Rupert http://daverupert.com
    * Released under the WTFPL license 
    * http://sam.zoy.org/wtfpl/
    *
    * Date: Thu May 05 14:23:00 2011 -0600
    */
    $.fn.fitText = function( kompressor, options ) {

        var settings = {
            'minFontSize' : Number.NEGATIVE_INFINITY,
            'maxFontSize' : Number.POSITIVE_INFINITY
        };

        return this.each(function() {
            var $this = $(this);              // store the object
            var compressor = kompressor || 1; // set the compressor
    
            if ( options ) { 
              $.extend( settings, options );
            }
    
            // Resizer() resizes items based on the object width divided by the compressor * 10
            var resizer = function () {
                $this.css('font-size', Math.max(Math.min($this.width() / (compressor*10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize)));
            };

            // Call once to set.
            resizer();

            // Call on resize. Opera debounces their resize by default. 
            $(window).resize(resizer);
        });

    };

    /*
     * Lettering plugin
     *
     * changed injector function:
     *   add   for empty chars.
     */
    function injector(t, splitter, klass, after) {
        var a = t.text().split(splitter), inject = '', emptyclass;
        if (a.length) {
            $(a).each(function(i, item) {
                emptyclass = '';
                if(item === ' ') {
                    emptyclass = ' empty';
                    item=' ';
                }   
                inject += '<span class="'+klass+(i+1)+emptyclass+'">'+item+'</span>'+after;
            }); 
            t.empty().append(inject);
        }
    }
    
    var methods             = {
        init : function() {

            return this.each(function() {
                injector($(this), '', 'char', '');
            });

        },

        words : function() {

            return this.each(function() {
                injector($(this), ' ', 'word', ' ');
            });

        },
        
        lines : function() {

            return this.each(function() {
                var r = "eefec303079ad17405c889e092e105b0";
                // Because it's hard to split a <br/> tag consistently across browsers,
                // (*ahem* IE *ahem*), we replaces all <br/> instances with an md5 hash 
                // (of the word "split").  If you're trying to use this plugin on that 
                // md5 hash string, it will fail because you're being ridiculous.
                injector($(this).children("br").replaceWith(r).end(), r, 'line', '');
            });

        }
    };

    $.fn.lettering          = function( method ) {
        // Method calling logic
        if ( method && methods[method] ) {
            return methods[ method ].apply( this, [].slice.call( arguments, 1 ));
        } else if ( method === 'letters' || ! method ) {
            return methods.init.apply( this, [].slice.call( arguments, 0 ) ); // always pass an array
        }
        $.error( 'Method ' +  method + ' does not exist on jQuery.lettering' );
        return this;
    };
    
    /*
     * Arctext object.
     */
    $.Arctext               = function( options, element ) {
    
        this.$el    = $( element );
        this._init( options );
        
    };
    
    $.Arctext.defaults      = {
        radius  : 0,    // the minimum value allowed is half of the word length. if set to -1, the word will be straight.
        dir     : 1,    // 1: curve is down, -1: curve is up.
        rotate  : true, // if true each letter will be rotated.
        fitText : false // if you wanna try out the fitText plugin (http://fittextjs.com/) set this to true. Don't forget the wrapper should be fluid.
    };
    
    $.Arctext.prototype     = {
        _init               : function( options ) {
            
            this.options        = $.extend( true, {}, $.Arctext.defaults, options );
            
            // apply the lettering plugin.
            this._applyLettering();
            
            this.$el.data( 'arctext', true );
            
            // calculate values
            this._calc();
            
            // apply transformation.
            this._rotateWord();
            
            // load the events
            this._loadEvents();
            
        },
        _applyLettering     : function() {
        
            this.$el.lettering();
            
            if( this.options.fitText )
                this.$el.fitText();
            
            this.$letters   = this.$el.find('span').css('display', 'inline-block');
        
        },
        _calc               : function() {
            
            if( this.options.radius === -1 )
                return false;
            
            // calculate word / arc sizes & distances.
            this._calcBase();
            
            // get final values for each letter.
            this._calcLetters();
        
        },
        _calcBase           : function() {
            
            // total word width (sum of letters widths)
            this.dtWord     = 0;
            
            var _self       = this;
            
            this.$letters.each( function(i) {
                                
                var $letter         = $(this),
                    letterWidth     = $letter.outerWidth( true );
                
                _self.dtWord += letterWidth;
                
                // save the center point of each letter:
                $letter.data( 'center', _self.dtWord - letterWidth / 2 );
                
            });
            
            // the middle point of the word.
            var centerWord = this.dtWord / 2;
            
            // check radius : the minimum value allowed is half of the word length.
            if( this.options.radius < centerWord )
                this.options.radius = centerWord;
            
            // total arc segment length, where the letters will be placed.
            this.dtArcBase  = this.dtWord;
            
            // calculate the arc (length) that goes from the beginning of the first letter (x=0) to the end of the last letter (x=this.dtWord).
            // first lets calculate the angle for the triangle with base = this.dtArcBase and the other two sides = radius.
            var angle       = 2 * Math.asin( this.dtArcBase / ( 2 * this.options.radius ) );
            
            // given the formula: L(ength) = R(adius) x A(ngle), we calculate our arc length.
            this.dtArc      = this.options.radius * angle;
            
        },
        _calcLetters        : function() {
            
            var _self       = this,
                iteratorX   = 0;
                
            this.$letters.each( function(i) {
                    
                var $letter         = $(this),
                    // calculate each letter's semi arc given the percentage of each letter on the original word.
                    dtArcLetter     = ( $letter.outerWidth( true ) / _self.dtWord ) * _self.dtArc,
                    // angle for the dtArcLetter given our radius.
                    beta            = dtArcLetter / _self.options.radius,
                    // distance from the middle point of the semi arc's chord to the center of the circle.
                    // this is going to be the place where the letter will be positioned.
                    h               = _self.options.radius * ( Math.cos( beta / 2 ) ),
                    // angle formed by the x-axis and the left most point of the chord.
                    alpha           = Math.acos( ( _self.dtWord / 2 - iteratorX ) / _self.options.radius ),
                    // angle formed by the x-axis and the right most point of the chord.
                    theta           = alpha + beta / 2,
                    // distances of the sides of the triangle formed by h and the orthogonal to the x-axis.
                    x               = Math.cos( theta ) * h,
                    y               = Math.sin( theta ) * h,
                    // the value for the coordinate x of the middle point of the chord.
                    xpos            = iteratorX + Math.abs( _self.dtWord / 2 - x - iteratorX ),
                    // finally, calculate how much to translate each letter, given its center point.
                    // also calculate the angle to rotate the letter accordingly.
                    xval    = 0| xpos - $letter.data( 'center' ),
                    yval    = 0| _self.options.radius - y,
                    angle   = ( _self.options.rotate ) ? 0| -Math.asin( x / _self.options.radius ) * ( 180 / Math.PI ) : 0;
                
                // the iteratorX will be positioned on the second point of each semi arc
                iteratorX = 2 * xpos - iteratorX;
                
                // save these values
                $letter.data({
                    x   : xval,
                    y   : ( _self.options.dir === 1 ) ? yval : -yval,
                    a   : ( _self.options.dir === 1 ) ? angle : -angle
                });
                    
            });
        
        },
        _rotateWord         : function( animation ) {
            
            if( !this.$el.data('arctext') ) return false;
            
            var _self = this;
            
            this.$letters.each( function(i) {
                
                var $letter         = $(this),
                    transformation  = ( _self.options.radius === -1 ) ? 'none' : 'translateX(' + $letter.data('x') + 'px) translateY(' + $letter.data('y') + 'px) rotate(' + $letter.data('a') + 'deg)',
                    transition      = ( animation ) ? 'all ' + ( animation.speed || 0 ) + 'ms ' + ( animation.easing || 'linear' ) : 'none';
                
                $letter.css({
                    '-webkit-transition' : transition,
                    '-moz-transition' : transition,
                    '-o-transition' : transition,
                    '-ms-transition' : transition,
                    'transition' : transition
                })
                .css({
                    '-webkit-transform' : transformation,
                    '-moz-transform' : transformation,
                    '-o-transform' : transformation,
                    '-ms-transform' : transformation,
                    'transform' : transformation
                });
            
            });
            
        },
        _loadEvents         : function() {
            
            if( this.options.fitText ) {
            
                var _self = this;
                
                $(window).on( 'resize.arctext', function() {
                    
                    _self._calc();
                    
                    // apply transformation.
                    _self._rotateWord();
                    
                });
            
            }
        
        },
        set                 : function( opts ) {
            
            if( !opts.radius &&  
                !opts.dir &&
                opts.rotate === 'undefined' ) {
                    return false;
            }
            
            this.options.radius = opts.radius || this.options.radius;
            this.options.dir    = opts.dir || this.options.dir;
            
            if( opts.rotate !== undefined ) {
                this.options.rotate = opts.rotate;
            }   
            
            this._calc();
            
            this._rotateWord( opts.animation );
            
        },
        destroy             : function() {
            
            this.options.radius = -1;
            this._rotateWord();
            this.$letters.removeData('x y a center');
            this.$el.removeData('arctext');
            $(window).off('.arctext');
            
        }
    };
    
    var logError            = function( message ) {
        if ( this.console ) {
            console.error( message );
        }
    };
    
    $.fn.arctext            = function( options ) {
    
        if ( typeof options === 'string' ) {
            
            var args = Array.prototype.slice.call( arguments, 1 );
            
            this.each(function() {
            
                var instance = $.data( this, 'arctext' );
                
                if ( !instance ) {
                    logError( "cannot call methods on arctext prior to initialization; " +
                    "attempted to call method '" + options + "'" );
                    return;
                }
                
                if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
                    logError( "no such method '" + options + "' for arctext instance" );
                    return;
                }
                
                instance[ options ].apply( instance, args );
            
            });
        
        } 
        else {
        
            this.each(function() {
            
                var instance = $.data( this, 'arctext' );
                if ( !instance ) {
                    $.data( this, 'arctext', new $.Arctext( options, this ) );
                }
            });
        
        }
        
        return this;
        
    };
    
})( jQuery );
// END arctext.js -------------------------------------

jQuery(function($) {
    let $demo = $('#demo');
    $demo.arctext({radius: 200, rotate: false});
});
#demo {
    font-size: 2rem; /* just for demonstration */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

<p id="demo">Non-rotated letters</p>

您必须在元素中修剪空格文本,例如&lt; p id =“ demo”&gt; hello world&lt;/p&gt;
接下来,将新版本的jQuery和arctext.js添加到您的html。
然后使用此命令 $('#demo')。arctext({radius:200,rotate:false}); 执行弧。

您可能会更改半径以符合您的需求。

Use Arctext.js will save your time and easy.

Demos: 1, 2, 3

/**
 * Arctext.js
 * A jQuery plugin for curved text
 * http://www.codrops.com
 *
 * Copyright 2011, Pedro Botelho / Codrops
 * Free to use under the MIT license.
 *
 * Date: Mon Jan 23 2012
 */

(function( $, undefined ) {
    
    /*! 
    * FitText.js 1.0
    *
    * Copyright 2011, Dave Rupert http://daverupert.com
    * Released under the WTFPL license 
    * http://sam.zoy.org/wtfpl/
    *
    * Date: Thu May 05 14:23:00 2011 -0600
    */
    $.fn.fitText = function( kompressor, options ) {

        var settings = {
            'minFontSize' : Number.NEGATIVE_INFINITY,
            'maxFontSize' : Number.POSITIVE_INFINITY
        };

        return this.each(function() {
            var $this = $(this);              // store the object
            var compressor = kompressor || 1; // set the compressor
    
            if ( options ) { 
              $.extend( settings, options );
            }
    
            // Resizer() resizes items based on the object width divided by the compressor * 10
            var resizer = function () {
                $this.css('font-size', Math.max(Math.min($this.width() / (compressor*10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize)));
            };

            // Call once to set.
            resizer();

            // Call on resize. Opera debounces their resize by default. 
            $(window).resize(resizer);
        });

    };

    /*
     * Lettering plugin
     *
     * changed injector function:
     *   add   for empty chars.
     */
    function injector(t, splitter, klass, after) {
        var a = t.text().split(splitter), inject = '', emptyclass;
        if (a.length) {
            $(a).each(function(i, item) {
                emptyclass = '';
                if(item === ' ') {
                    emptyclass = ' empty';
                    item=' ';
                }   
                inject += '<span class="'+klass+(i+1)+emptyclass+'">'+item+'</span>'+after;
            }); 
            t.empty().append(inject);
        }
    }
    
    var methods             = {
        init : function() {

            return this.each(function() {
                injector($(this), '', 'char', '');
            });

        },

        words : function() {

            return this.each(function() {
                injector($(this), ' ', 'word', ' ');
            });

        },
        
        lines : function() {

            return this.each(function() {
                var r = "eefec303079ad17405c889e092e105b0";
                // Because it's hard to split a <br/> tag consistently across browsers,
                // (*ahem* IE *ahem*), we replaces all <br/> instances with an md5 hash 
                // (of the word "split").  If you're trying to use this plugin on that 
                // md5 hash string, it will fail because you're being ridiculous.
                injector($(this).children("br").replaceWith(r).end(), r, 'line', '');
            });

        }
    };

    $.fn.lettering          = function( method ) {
        // Method calling logic
        if ( method && methods[method] ) {
            return methods[ method ].apply( this, [].slice.call( arguments, 1 ));
        } else if ( method === 'letters' || ! method ) {
            return methods.init.apply( this, [].slice.call( arguments, 0 ) ); // always pass an array
        }
        $.error( 'Method ' +  method + ' does not exist on jQuery.lettering' );
        return this;
    };
    
    /*
     * Arctext object.
     */
    $.Arctext               = function( options, element ) {
    
        this.$el    = $( element );
        this._init( options );
        
    };
    
    $.Arctext.defaults      = {
        radius  : 0,    // the minimum value allowed is half of the word length. if set to -1, the word will be straight.
        dir     : 1,    // 1: curve is down, -1: curve is up.
        rotate  : true, // if true each letter will be rotated.
        fitText : false // if you wanna try out the fitText plugin (http://fittextjs.com/) set this to true. Don't forget the wrapper should be fluid.
    };
    
    $.Arctext.prototype     = {
        _init               : function( options ) {
            
            this.options        = $.extend( true, {}, $.Arctext.defaults, options );
            
            // apply the lettering plugin.
            this._applyLettering();
            
            this.$el.data( 'arctext', true );
            
            // calculate values
            this._calc();
            
            // apply transformation.
            this._rotateWord();
            
            // load the events
            this._loadEvents();
            
        },
        _applyLettering     : function() {
        
            this.$el.lettering();
            
            if( this.options.fitText )
                this.$el.fitText();
            
            this.$letters   = this.$el.find('span').css('display', 'inline-block');
        
        },
        _calc               : function() {
            
            if( this.options.radius === -1 )
                return false;
            
            // calculate word / arc sizes & distances.
            this._calcBase();
            
            // get final values for each letter.
            this._calcLetters();
        
        },
        _calcBase           : function() {
            
            // total word width (sum of letters widths)
            this.dtWord     = 0;
            
            var _self       = this;
            
            this.$letters.each( function(i) {
                                
                var $letter         = $(this),
                    letterWidth     = $letter.outerWidth( true );
                
                _self.dtWord += letterWidth;
                
                // save the center point of each letter:
                $letter.data( 'center', _self.dtWord - letterWidth / 2 );
                
            });
            
            // the middle point of the word.
            var centerWord = this.dtWord / 2;
            
            // check radius : the minimum value allowed is half of the word length.
            if( this.options.radius < centerWord )
                this.options.radius = centerWord;
            
            // total arc segment length, where the letters will be placed.
            this.dtArcBase  = this.dtWord;
            
            // calculate the arc (length) that goes from the beginning of the first letter (x=0) to the end of the last letter (x=this.dtWord).
            // first lets calculate the angle for the triangle with base = this.dtArcBase and the other two sides = radius.
            var angle       = 2 * Math.asin( this.dtArcBase / ( 2 * this.options.radius ) );
            
            // given the formula: L(ength) = R(adius) x A(ngle), we calculate our arc length.
            this.dtArc      = this.options.radius * angle;
            
        },
        _calcLetters        : function() {
            
            var _self       = this,
                iteratorX   = 0;
                
            this.$letters.each( function(i) {
                    
                var $letter         = $(this),
                    // calculate each letter's semi arc given the percentage of each letter on the original word.
                    dtArcLetter     = ( $letter.outerWidth( true ) / _self.dtWord ) * _self.dtArc,
                    // angle for the dtArcLetter given our radius.
                    beta            = dtArcLetter / _self.options.radius,
                    // distance from the middle point of the semi arc's chord to the center of the circle.
                    // this is going to be the place where the letter will be positioned.
                    h               = _self.options.radius * ( Math.cos( beta / 2 ) ),
                    // angle formed by the x-axis and the left most point of the chord.
                    alpha           = Math.acos( ( _self.dtWord / 2 - iteratorX ) / _self.options.radius ),
                    // angle formed by the x-axis and the right most point of the chord.
                    theta           = alpha + beta / 2,
                    // distances of the sides of the triangle formed by h and the orthogonal to the x-axis.
                    x               = Math.cos( theta ) * h,
                    y               = Math.sin( theta ) * h,
                    // the value for the coordinate x of the middle point of the chord.
                    xpos            = iteratorX + Math.abs( _self.dtWord / 2 - x - iteratorX ),
                    // finally, calculate how much to translate each letter, given its center point.
                    // also calculate the angle to rotate the letter accordingly.
                    xval    = 0| xpos - $letter.data( 'center' ),
                    yval    = 0| _self.options.radius - y,
                    angle   = ( _self.options.rotate ) ? 0| -Math.asin( x / _self.options.radius ) * ( 180 / Math.PI ) : 0;
                
                // the iteratorX will be positioned on the second point of each semi arc
                iteratorX = 2 * xpos - iteratorX;
                
                // save these values
                $letter.data({
                    x   : xval,
                    y   : ( _self.options.dir === 1 ) ? yval : -yval,
                    a   : ( _self.options.dir === 1 ) ? angle : -angle
                });
                    
            });
        
        },
        _rotateWord         : function( animation ) {
            
            if( !this.$el.data('arctext') ) return false;
            
            var _self = this;
            
            this.$letters.each( function(i) {
                
                var $letter         = $(this),
                    transformation  = ( _self.options.radius === -1 ) ? 'none' : 'translateX(' + $letter.data('x') + 'px) translateY(' + $letter.data('y') + 'px) rotate(' + $letter.data('a') + 'deg)',
                    transition      = ( animation ) ? 'all ' + ( animation.speed || 0 ) + 'ms ' + ( animation.easing || 'linear' ) : 'none';
                
                $letter.css({
                    '-webkit-transition' : transition,
                    '-moz-transition' : transition,
                    '-o-transition' : transition,
                    '-ms-transition' : transition,
                    'transition' : transition
                })
                .css({
                    '-webkit-transform' : transformation,
                    '-moz-transform' : transformation,
                    '-o-transform' : transformation,
                    '-ms-transform' : transformation,
                    'transform' : transformation
                });
            
            });
            
        },
        _loadEvents         : function() {
            
            if( this.options.fitText ) {
            
                var _self = this;
                
                $(window).on( 'resize.arctext', function() {
                    
                    _self._calc();
                    
                    // apply transformation.
                    _self._rotateWord();
                    
                });
            
            }
        
        },
        set                 : function( opts ) {
            
            if( !opts.radius &&  
                !opts.dir &&
                opts.rotate === 'undefined' ) {
                    return false;
            }
            
            this.options.radius = opts.radius || this.options.radius;
            this.options.dir    = opts.dir || this.options.dir;
            
            if( opts.rotate !== undefined ) {
                this.options.rotate = opts.rotate;
            }   
            
            this._calc();
            
            this._rotateWord( opts.animation );
            
        },
        destroy             : function() {
            
            this.options.radius = -1;
            this._rotateWord();
            this.$letters.removeData('x y a center');
            this.$el.removeData('arctext');
            $(window).off('.arctext');
            
        }
    };
    
    var logError            = function( message ) {
        if ( this.console ) {
            console.error( message );
        }
    };
    
    $.fn.arctext            = function( options ) {
    
        if ( typeof options === 'string' ) {
            
            var args = Array.prototype.slice.call( arguments, 1 );
            
            this.each(function() {
            
                var instance = $.data( this, 'arctext' );
                
                if ( !instance ) {
                    logError( "cannot call methods on arctext prior to initialization; " +
                    "attempted to call method '" + options + "'" );
                    return;
                }
                
                if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
                    logError( "no such method '" + options + "' for arctext instance" );
                    return;
                }
                
                instance[ options ].apply( instance, args );
            
            });
        
        } 
        else {
        
            this.each(function() {
            
                var instance = $.data( this, 'arctext' );
                if ( !instance ) {
                    $.data( this, 'arctext', new $.Arctext( options, this ) );
                }
            });
        
        }
        
        return this;
        
    };
    
})( jQuery );
// END arctext.js -------------------------------------

jQuery(function($) {
    let $demo = $('#demo');
    $demo.arctext({radius: 200, rotate: false});
});
#demo {
    font-size: 2rem; /* just for demonstration */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

<p id="demo">Non-rotated letters</p>

See it in action on jsfiddle.

You have to trimmed space text in an element such as <p id="demo">hello world</p>.
Next, add new version of jQuery and arctext.js to your HTML.
Then use this command $('#demo').arctext({radius: 200, rotate: false}); to execute arc.

You may change radius to match your need.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文