JavaScript

超轻量级php框架startmvc

arctext.js实现文字平滑弯曲弧形效果的插件

更新时间:2020-08-26 01:42:01 作者:startmvc
本文介绍了实现文字平滑弯曲弧形效果的插件-arctext.js,分享给大家,具体如下:扇形的文

本文介绍了实现文字平滑弯曲弧形效果的插件-arctext.js,分享给大家,具体如下:

扇形的文字

有时候产品大佬就是很任性,说做一个宣传页,一个类似拱门的效果,每次文字不一样,但是文字得呈现拱形状,类似上图啦。

尝试自己使用canvas画和css3的rotate旋转div,两种方法都是计算旋转角度的时候很麻烦,因为可能5个字10个字,但是得均匀地呈拱形分布,要知道让每个文字都沿着弯曲路径排布相当的复杂,于是便发现了这个好用的插件---arctext.js

它能够自动计算每个文字正确的旋转角度,并且生成对应的CSS ,其实就是基于css3和jquery,使用起来也很方便。

1.创建一个容器装文字


<h3 id="title">文字弯曲效果类似扇形拱桥状</h3>

2.引入jquery和arctext.js


<script type="text/javascript" src="//code.jquery.com/jquery-1.8.2.min.js" ></script>
<script src="jquery.arctext.js"></script>

3.调用arctext的方法:


$(function(){
 $("#title").show().arctext({
 radius:180
 })
 })

arctext参数说明:

  • radius:弯曲度数,最小的值是文字长度,如果设置为-1,则显示直线。
  • rotate:默认true,为false则不旋转文字
  • dir:默认1 (1:向下弯曲 非1(-1,0,2等):向上弯曲 )
  • fitText:默认false,如果你想尝试使用fitText插件,设置为true,记住包装的标签需要fluid布局。

效果图完整demo:


<!DOCTYPE html>
<html>
<head lang="en">
 <meta charset="UTF-8">
 <title></title>
 <style>
 #title{
 font-size: 20px;
 color: #ffe400;
 text-align: center;
 }
 </style>
</head>
<body>
 <h3 id="title">文字弯曲效果类似扇形拱桥状</h3>
<script type="text/javascript" src="//code.jquery.com/jquery-1.8.2.min.js" ></script>
<script src="jquery.arctext.js"></script>
<script>
 $(function(){
 $("#title").arctext({
 radius:180
 })
 })
</script>
</body>
</html>

jquery.arctext.js


/**
 * 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 );

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

arctext.js文字平滑弯曲弧形效果