UGUI实现随意调整Text中的字体间距

UGUI中是没有可以随意调整字体间的距离的方法,仔细研究一下可以通过控制每个字体的网格顶点位置进行调整字体之间的距离,分析一下最简单情况:输入的文本是单行的,且末尾没有换行符;

unity在UnityEngine.UI命名空间中定义了一个BaseMeshEffect抽象类,他提供了一个抽象方法ModifyMesh(VertexHelper vh),使得可以轻松地获得text文本中所有字体 的顶点信息,我们的移动字体的操作将在这里面进行。VertexHelper类主要是用于提供字体网格数据的工具类;

上述便是挂载TestSpacingText脚本之后的效果图。下面贴出代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextSpacingTest : BaseMeshEffect
{
 public float spacing = 0;
 public override void ModifyMesh(VertexHelper vh)
 {
  List<UIVertex> vertexs = new List<UIVertex>();
  vh.GetUIVertexStream(vertexs);
  int vertexIndexCount = vertexs.Count;
  for (int i = 6; i < vertexIndexCount; i++)
  {
   UIVertex v = vertexs[i];
   v.position += new Vector3(spacing * (i / 6), 0, 0);
   vertexs[i] = v;
   if (i % 6 <= 2)
   {
    vh.SetUIVertex(v, (i / 6) * 4 + i % 6);
   }
   if (i % 6 == 4)
   {
    vh.SetUIVertex(v, (i / 6) * 4 + i % 6 - 1);
   }
  }
 }
}

分析代码:

1)首先创建一个字体间距的变量,然后需要继承BaseMeshEffect类并且实现其中的抽象的方法MeshModify()函数。
2)创建一个容器从网格信息生成器vh中将字体的顶点信息全部加载保存下来
3)接下来开始遍历获取到的顶点,我们知道每个字体是由两个三角形的组成的网格,字体是显示在这样的网格上的,因此每个字体也就对应6个顶点。那么就开始移动每个顶点就可以了。
4)移动顶点之后要记得设置UV顶点与顶点索引的对应关系,因为一个字体网格由两个三角形组成,那么就重叠了两个顶点,故而一个字体的6个顶点,就只对应4个UV顶点索引,如上代码显示的那样。

分析如下:

接下来看看比较复杂的情况:

文本的情况为,可以有多行,或单行,单行、多行时末尾均可以有换行符。

核心思路:

1)先考虑仅仅是多行且末尾行的末尾没有换行符的情况,解决了这个核心问题,再考虑其他的问题。
2)将多行的文本按照换行符进行分割,这样每一行就形成了一个字符串,此时对每一行进行上面简单的操作,就可以实现移动的了。
3)考虑到所有的文本的顶点信息数据都存储在vh中,可以创建一个行数据结构Line以此来存储每行的基本属性(比如:本行开始定点的索引位置,结束顶点的索引位置,所有顶点的数量)。
4)简单多行的情况,利用上面的分行的思路就可以解决,接下来分析其他的问题。
5)单行时末尾有换行符,我们在分割字符串之后要加以判断是否有空串的情况 ,若有那么就认为末尾产生了换行符,此时空串不再创建LIne对象,只用创建一个Line对象。解法看代码。
6)多行时末尾有换行符,同样用于上面一样的方法进行检验,最后一个空串不在创建Line对象,解法看代码。
7)之后若是想扩展修改字体垂直方向的间距也可以在此基础上修改,非常简单。

接下来看代码:

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;

internal class Line
{
 //每行开始顶点索引
 private int startVertexIndex;
 public int StartVertexIndex
 {
  get
  {
   return startVertexIndex;
  }
 }

 //每行结束顶点索引
 private int endVertexIndex;
 public int EndVertexIndex
 {
  get
  {
   return endVertexIndex;
  }
 }

 //每行顶点总量
 private int countVertexIndex;
 public int CountVertexIndex
 {
  get
  {
   return countVertexIndex;
  }
 }

 public Line(int startVertexIndex,int countVertexIndex)
 {
  this.startVertexIndex = startVertexIndex;
  this.countVertexIndex = countVertexIndex;
  this.endVertexIndex = this.startVertexIndex + countVertexIndex - 1;

 }
}

/// <summary>
/// 这是设置字体移动的核心类
/// 执行多重行移动的核心算法是:将多重行分开依次进行处理,每一行的处理都是前面对单行处理的子操作
/// 但是由vh是记录一个文本中所有的字的顶点,所以说需要分清楚每行开始,每行结束,以及行的字个数,
/// 如此需要创建一个行的数据结构,以保存这些信息
/// </summary>
public class TextSpacingMulTest : BaseMeshEffect
{
 public float spacing = 0;
 public override void ModifyMesh(VertexHelper vh)
 {
  Text text = GetComponent<Text>();
  string[] ls = text.text.Split('\n');
  int length = ls.Length;
  bool isNewLine = false;
  Line[] line;
  if (string.IsNullOrEmpty(ls[ls.Length - 1]) == true)
  {
   line = new Line[length - 1];
   isNewLine = true;
  }
  else
  {
   line = new Line[length];

  }
  //Debug.Log("ls长度" + ls.Length);
  for (int i = 0; i < line.Length; i++)
  {
   if (i == 0 && line.Length == 1&&isNewLine==false)//解决单行时没有换行符的情况
   {
    line[i] = new Line(0, ls[i].Length * 6);
    break;
   }
   if (i == 0&&line.Length>=1)//解决单行时有换行符的情况,以及多行时i为0的情况
   {
    line[i] = new Line(0, (ls[i].Length+1) * 6);
   }
   else
   {
    if (i < line.Length - 1)
    {
     line[i] = new Line(line[i - 1].EndVertexIndex + 1, (ls[i].Length + 1) * 6);
    }
    else
    {
     if (isNewLine == true)//解决多行时,最后一行末尾有换行符的情况
     {
      line[i] = new Line(line[i - 1].EndVertexIndex + 1, (ls[i].Length + 1) * 6);
     }
     else
     {
      line[i] = new Line(line[i - 1].EndVertexIndex + 1, ls[i].Length * 6);
     }
    }
   }
  }

  List<UIVertex> vertexs = new List<UIVertex>();
  vh.GetUIVertexStream(vertexs);
  int countVertexIndex = vertexs.Count;
  //Debug.Log("顶点总量" + vertexs.Count);
  for (int i = 0; i < line.Length; i++)
  {
   if (line[i].CountVertexIndex == 6) { continue; }
   for (int k = line[i].StartVertexIndex+6; k <= line[i].EndVertexIndex; k++)
   {
    UIVertex vertex = vertexs[k];
    vertex.position += new Vector3(spacing * ((k-line[i].StartVertexIndex) / 6), 0, 0);
    //Debug.Log("执行");
    vertexs[k] = vertex;
    if (k % 6 <= 2)
    {
     vh.SetUIVertex(vertex, (k / 6) * 4 + k % 6);
    }
    if (k % 6 == 4)
    {
     vh.SetUIVertex(vertex, (k / 6) * 4 + k % 6 - 1);
    }
   }

  }

 }
}

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

(0)

相关推荐

  • Unity UGUI控制text文字间距

    Unity ugui相比ngui,提供的功能少之又少,好多特性得需要自己实现.真不知道unity写这个插件后来是不是就没有更新过.发了句牢骚.如果我想控制文字的显示间距,ngui 有两种办法.1:文字之间加空格.2:调节spacing 的x值. 但对于ugui,第二种方法却没有.以前我使用ngui,这种方法用的多了,也方便,因此很想也把它这个特性转到ugui上. 思考了半天,最终想出来了解决方法,以下是实现方式: 1.定义扩展效果类 [RequireComponent(typeof(Text))

  • UGUI实现随意调整Text中的字体间距

    UGUI中是没有可以随意调整字体间的距离的方法,仔细研究一下可以通过控制每个字体的网格顶点位置进行调整字体之间的距离,分析一下最简单情况:输入的文本是单行的,且末尾没有换行符: unity在UnityEngine.UI命名空间中定义了一个BaseMeshEffect抽象类,他提供了一个抽象方法ModifyMesh(VertexHelper vh),使得可以轻松地获得text文本中所有字体 的顶点信息,我们的移动字体的操作将在这里面进行.VertexHelper类主要是用于提供字体网格数据的工具类

  • Android编程中TextView字体属性设置方法(大小、字体、下划线、背景色)

    本文实例讲述了Android编程中TextView字体属性设置方法(大小.字体.下划线.背景色).分享给大家供大家参考,具体如下: import android.content.Context; import android.graphics.Color; import android.text.SpannableString; import android.text.Spanned; import android.text.style.AbsoluteSizeSpan; import andr

  • React Native 中添加自定义字体的方法

    目录 添加字体 定义 assets 目录 执行 link 命令 在样式中使用字体 示例 在 React Native 中,如何添加自定义字体呢?React Native 提供了便捷的命令行工具来帮助我们. 添加字体 在项目根目录下创建 assets/fonts 文件夹,把字体文件放到这个文件夹下. 如图: 定义 assets 目录 在项目根目录下创建 react-native.config.js 文件,编辑其中内容,留意第 6 行,这和我们自定义字体文件所在目录一致. module.export

  • 如何在React项目中引入字体文件并使用详解

    目录 前言 下面讲下如何引入字体文件并使用 一.下载字体包 二.将字体文件放到项目里 三.使用新字体 总结 前言 在做React项目的时候,发现UI设计给出的设计稿里,某些文字所用的字体,系统默认不支持.比如设计需要的这个字体:EmerlandRegular,即使在css里将文字字体设置为他们,实际效果也显示不出来. <Typography style={{ fontSize:'22px', fontFamily:'EmerlandRegular', textAlign:'center', co

  • 利用C#实现在Word中更改字体颜色

    目录 程序环境 更改段落字体颜色 完整代码 效果图 更改特定文本字体颜色 完整代码 效果图 在日常工作中,我们有时会需要修改字体的颜色来突出文本重点,让读者更容易抓住文章要点.在今天这篇文章中,我将为大家介绍如何以编程方式,在Word更改字体颜色.本文将分为两部分分别介绍如何实现此操作.以下是我整理的步骤及方法,并附上C#/VB.NET代码供大家参考. 更改段落字体颜色 更改特定文本字体颜色 程序环境 本次测试时,在程序中引入Free Spire.Doc for .NET.可通过以下方法引用 F

  • Web Inspector:关于在 Sublime Text 中调试Js的介绍

    Sublime Text 是一款非常优秀的跨平台编辑器,拥有漂亮的用户界面和强大的功能,例如代码缩略图,多重选择,快捷命令等.还可自定义键绑定,菜单和工具栏.Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API ,Goto 功能,即时项目切换,多选择,多窗口等等. 另外,Sublime Text 插件众多,通过包管理工具可以方便安装和管理.本文介绍的 Sublime Web Inspector 便是众多插件中一款非常出色的开发辅助插件,可以帮助 Web 开发人员

  • iOS中 UIActionSheet字体的修改

    一,效果图. 二,代码. RootViewController.h #import <UIKit/UIKit.h> @interface RootViewController : UIViewController <UIActionSheetDelegate> @end RootViewController.m -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UIActionSheet *actio

  • IOS 调整内存中的图片大小实例详解

    IOS 调整内存中的图片大小实例详解 在从网路download图片,或者从相册读取图片的时候,如果ImageView的本身就是固定的300*200,那么载入2000*2000的图片是很浪费内存的. 2000*2000的内存占用是2000*2000*4bit 以下两个函数可以用来创建一个新的按照固定大小的图片.简单来说,就是Core Graphics来创建一个bitmap,然后生成一个图片. - (UIImage*)imageWithImage:(UIImage*)image scaledToSi

  • 如何用正则取input type="text"中的value

    1.如何通过正则取input type="text"中的value呢? 2.如何过滤掉input type="checkbox"的标签? 这样只能达到正则取input type="text"中的value可是不能过滤掉input type="checkbox"的标签! alert function pla(str) { var re=/]+?value=(\"|\')([^>]*)\1[^>]+?>

  • Android中App字体大小不随系统改变而改变

    在 "设置" , "显示" , "字体大小" 里面我们可以设置系统字体大小 App界面字体,如果被修改之后,可能就达不到理想状态的效果,界面布局就发生了变化. 未修改过的效果(测试机型:Nexus 5): 正常 小 超大 修改之后的效果(测试机型:Nexus 5): 正常 小 超大 我们从这两组对比图中可以直观的看到修改后的App字体大小不随系统改变而改变. 其实实现起来很简单,无需设置布局文件里面的 "textSize",只

随机推荐