public void OnPointerClick(PointerEventData eventData) { Vector2 localPos; RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, eventData.position, eventData.pressEventCamera, out localPos); for (int i = eventList.Count - 1; i >= 0; i--) { RichTextEvent e = eventList[i]; if (e.rect.Contains(localPos)) { clickAction.Invoke(e.name, e.parameter); break; } } }
private void ApplyUnderlineEffect(RichTextUnderlineTag tag, IList <UIVertex> verts) { float fontSize2 = fontSize * 0.5f; float unitsPerPixel = 1 / pixelsPerUnit; //0 1|4 5|8 9 |12 13 //3 2|7 6|11 10|14 15 //<material=underline c=#ffffff h=1 n=1 p=2>下划线</material> //以上面为例: //tag.start为42,对应“>” | start对应“下”的左上角顶点 //tag.end为44,对应“划” | end对应“线”下一个字符的左上角顶点 //Debug.Log(tag.start); //Debug.Log(tag.end); int start = tag.start * 4; int end = Mathf.Min(tag.end * 4 + 4, verts.Count); UIVertex vt1 = verts[start + 3]; UIVertex vt2; float minY = vt1.position.y; float maxY = verts[start].position.y; //换行处理,如需换行,则将一条下划线分割成几条 //顶点取样分布,如上图的2,6,10,其中end - 2表示最后一个取样点,即10 //对应例子中的下、划、线的右下角顶点 for (int i = start + 2; i <= end - 2; i += 4) { vt2 = verts[i]; bool newline = Mathf.Abs(vt2.position.y - vt1.position.y) > fontSize2; if (newline || i == end - 2) { RichTextImageInfo imageInfo = new RichTextImageInfo(); //计算宽高 int tailIndex = !newline && i == end - 2 ? i : i - 4; vt2 = verts[tailIndex]; minY = Mathf.Min(minY, vt2.position.y); maxY = Mathf.Max(maxY, verts[tailIndex - 1].position.y); imageInfo.size = new Vector2((vt2.position.x - vt1.position.x) * unitsPerPixel, tag.height); //计算位置 Vector2 vertex = new Vector2(vt1.position.x, minY); vertex *= unitsPerPixel; vertex += new Vector2(imageInfo.size.x * 0.5f, -tag.height * 0.5f); vertex += new Vector2(rectTransform.sizeDelta.x * (rectTransform.pivot.x - 0.5f), rectTransform.sizeDelta.y * (rectTransform.pivot.y - 0.5f)); imageInfo.position = vertex; imageInfo.color = tag.color; imageInfoList.Add(imageInfo); if (!string.IsNullOrEmpty(tag.eventName)) { //下划线pos: //x:vt1.x + 图片宽度的一半 //y:minY - tag.height * 0.5f RichTextEvent e = new RichTextEvent(); e.name = tag.eventName; e.parameter = tag.eventParameter; e.rect = new Rect( vt1.position.x * unitsPerPixel, minY * unitsPerPixel, imageInfo.size.x, (maxY - minY) * unitsPerPixel ); eventList.Add(e); } vt1 = verts[i + 1]; minY = vt1.position.y; if (newline && i == end - 2) { i -= 4; } } else { minY = Mathf.Min(minY, verts[i].position.y); maxY = Mathf.Max(maxY, verts[i - 1].position.y); } } }
protected string CalculateLayoutWithImage(string richText, out IList <UIVertex> verts) { Vector2 extents = rectTransform.rect.size; var settings = GetGenerationSettings(extents); float unitsPerPixel = 1 / pixelsPerUnit; float spaceWidth = cachedTextGenerator.GetPreferredWidth(replaceStr, settings) * unitsPerPixel; float fontSize2 = fontSize * 0.5f; //解析图片标签,并将标签替换为空格 imageInfoList.Clear(); Match match = null; StringBuilder builder = new StringBuilder(); while ((match = imageTagRegex.Match(richText)).Success) { RichTextImageInfo imageInfo = new RichTextImageInfo(); imageInfo.name = match.Groups[1].Value; string paras = match.Groups[2].Value; if (!string.IsNullOrEmpty(paras)) { var keyValueCollection = imageParaRegex.Matches(paras); for (int i = 0; i < keyValueCollection.Count; i++) { string key = keyValueCollection[i].Groups[1].Value; string value = keyValueCollection[i].Groups[2].Value; imageInfo.SetValue(key, value); } } imageInfo.size = new Vector2(fontSize2 * imageInfo.widthScale, fontSize2 * imageInfo.heightScale); imageInfo.startVertex = match.Index * 4; int num = Mathf.CeilToInt(imageInfo.size.x / spaceWidth);//占据几个空格 imageInfo.vertexLength = num * 4; imageInfoList.Add(imageInfo); builder.Length = 0; builder.Append(richText, 0, match.Index); for (int i = 0; i < num; i++) { builder.Append(replaceStr); } builder.Append(richText, match.Index + match.Length, richText.Length - match.Index - match.Length); richText = builder.ToString(); } // Populate charaters cachedTextGenerator.Populate(richText, settings); verts = cachedTextGenerator.verts; // Last 4 verts are always a new line... int vertCount = verts.Count - 4; //换行处理 //0 1|4 5|8 9 //3 2|7 6|11 10 //例如前两个字为图片标签,第三字为普通文字;那么startVertex为0,vertexLength为8 for (int i = 0; i < imageInfoList.Count; i++) { RichTextImageInfo imageInfo = imageInfoList[i]; int startVertex = imageInfo.startVertex; int vertexLength = imageInfo.vertexLength; int maxVertex = Mathf.Min(startVertex + vertexLength, vertCount); //如果最边缘顶点超过了显示范围,则将图片移到下一行 //之后的图片信息中的起始顶点都往后移 if (verts[maxVertex - 2].position.x * unitsPerPixel > rectTransform.rect.xMax) //所有空格在同一行 { richText = richText.Insert(startVertex / 4, "\r\n"); for (int j = i; j < imageInfoList.Count; j++) { imageInfoList[j].startVertex += 8; } cachedTextGenerator.Populate(richText, settings); verts = cachedTextGenerator.verts; vertCount = verts.Count - 4; } else //空格不在同一行 { float lastX = verts[startVertex].position.x; for (int j = startVertex + 4; j < startVertex + vertexLength; j += 4) { if (verts[j].position.x < lastX) { richText = richText.Insert(startVertex / 4, "\r\n"); for (int k = i; k < imageInfoList.Count; k++) { imageInfoList[k].startVertex += 8; } cachedTextGenerator.Populate(richText, settings); verts = cachedTextGenerator.verts; vertCount = verts.Count - 4; break; } else { lastX = verts[j].position.x; } } } } //计算位置 for (int i = imageInfoList.Count - 1; i >= 0; i--) { RichTextImageInfo imageInfo = imageInfoList[i]; int startVertex = imageInfo.startVertex; if (startVertex < vertCount) { UIVertex uiVertex = verts[startVertex]; Vector2 pos = uiVertex.position; pos *= unitsPerPixel; pos += new Vector2(imageInfo.size.x * 0.5f, fontSize2 * 0.5f); pos += new Vector2(rectTransform.sizeDelta.x * (rectTransform.pivot.x - 0.5f), rectTransform.sizeDelta.y * (rectTransform.pivot.y - 0.5f)); imageInfo.position = pos; imageInfo.color = Color.white; if (!string.IsNullOrEmpty(imageInfo.eventName)) { //图片pos: //x:起点x + 图片宽度的一半 //y:起点y + fontSize2 * 0.5f RichTextEvent e = new RichTextEvent(); e.name = imageInfo.eventName; e.parameter = imageInfo.eventParameter; e.rect = new Rect( verts[startVertex].position.x * unitsPerPixel, verts[startVertex].position.y * unitsPerPixel + fontSize2 * 0.5f - imageInfo.size.y * 0.5f, imageInfo.size.x, imageInfo.size.y ); eventList.Add(e); } } else { imageInfoList.RemoveAt(i); } } isImageDirty = true; return(richText); }