赞
踩
工作时分配给我的要实现的功能,写的时候遇到挺多的坑的,在此记录一下
放大缩小的效果
2.编译器扩展窗口记录
1.Json序列化存储图片轴心位置, 放大倍率,放大所需要的事件
2.用了编译器扩展工具便于保存轴心信息
1.Image和RawImage的坐标都是以轴心位置计算的,更改轴心就需要重定位
2.确保画布的分辨率和测试的屏幕分辨率一致
3.计算轴心偏移和别忘记在乘以自己的放大倍率
1.打开WSC/保存图片轴心工具,在Image位置挂在需要保存轴心的图像,输出name作为key,并在Scene窗口中直接拖动轴心确定位置(不建议在Inspector中手动输入轴心修改,这样会让图像重定位)
2.程序调用
无论是简化key传入还是传入轴心对象的方式都需要传入要放大的Image
using System; using System.IO; using System.Collections; using System.Collections.Generic; using UnityEditor; using UnityEngine; using UnityEngine.UI; using DG.Tweening; namespace YBZ { public class ControlImage : MonoBehaviour { // 需要控制的图片 [Header("2D的图像,如果是视屏改为RawImage进行推流即可")] public Image image; // Start is called before the first frame update void Start() { if(image == null){ if(!TryGetComponent<Image>(out image)){ gameObject.AddComponent<Image>(); image = GetComponent<Image>(); } } rect = image.GetComponent<RectTransform>(); // 先读取json中的文件 Utility.Instance.ReadData(); StartCoroutine(five()); } IEnumerator five(){ Utility.Instance.ImageZoom(image, Utility.Instance.dict["1"]); yield return new WaitForSeconds(1); Utility.Instance.ImageZoom(image, Utility.Instance.dict["2"]); yield return new WaitForSeconds(1.01f); Utility.Instance.ImageZoom(image, Utility.Instance.dict["3"]); yield return new WaitForSeconds(1.01f); Utility.Instance.ImageZoom(image, Utility.Instance.dict["4"]); yield return new WaitForSeconds(1.01f); Utility.Instance.ImageZoom(image, Utility.Instance.dict["5"]); yield return new WaitForSeconds(3.01f); Utility.Instance.ImageZoom(image, Utility.Instance.dict["6"]); yield return new WaitForSeconds(1.01f); Utility.Instance.ImageZoom(image, Utility.Instance.dict["7"]); yield return new WaitForSeconds(1.51f); Utility.Instance.ImageZoom(image, Utility.Instance.dict["8"]); yield return new WaitForSeconds(1.51f); Utility.Instance.ImageZoom(image, Utility.Instance.dict["9"]); yield return new WaitForSeconds(2.01f); Utility.Instance.ImageZoom(image, Utility.Instance.dict["10"]); yield return new WaitForSeconds(2.01f); Utility.Instance.ImageZoom(image, Utility.Instance.dict["11"]); yield return new WaitForSeconds(2.01f); Utility.Instance.ImageZoom(image, Utility.Instance.dict["12"]); yield return new WaitForSeconds(2.01f); Utility.Instance.ImageZoom(image, Utility.Instance.dict["RESET"]); } // 图片的放大接口 public void ZoomEvent(Image image, string key){ Utility.Instance.ZoomPivot(image, key); } } // 单例模式 // 命名冲突时,请指定命名空间 // 使用前一定要读取数据! public class Utility{ public static Utility instance; public static Utility Instance { get{ if(instance == null) instance = new Utility(); return instance; } } // 放大点位置的字典 public Dictionary<String, ZoomPoint> dict = new Dictionary<string, ZoomPoint>(); //json文件的位置,这个位置默认是在SteamingAssets下的 private string jsonFileName ="/2DPivots.json"; private string filePath =""; // "StreamingAssets/2Dpivots" public void SetFilePath(string value) => filePath = value; // 写入数据 public void WriteDataTest(){ Data data = new Data(); data.zoomPoints = new List<ZoomPoint>(); ZoomPoint point1 = new ZoomPoint { name = "1", pivot = new Vector2(0.75f,0.75f) }; ZoomPoint point2 = new ZoomPoint { name = "2", pivot = new Vector2(0.5f,0.5f) }; data.zoomPoints[0] = point1; data.zoomPoints[1] = point2; string js = JsonUtility.ToJson(data); // 获取项目路径 string fileUrl; if(filePath == ""){ fileUrl = Application.streamingAssetsPath + jsonFileName; }else{ fileUrl = filePath; } using(StreamWriter sw = new StreamWriter(fileUrl)) { sw.WriteLine(js); //保存数据 sw.Close(); sw.Dispose(); } } public void WriteData(ZoomPoint zp){ Data data = ReadData(); if(data != null && data.zoomPoints != null){ foreach(var temp in data.zoomPoints){ if(temp.name == zp.name){ Debug.LogError("轴心名字重复 !(⊙_⊙)?"); return; } } } data.zoomPoints.Add(zp); string js = JsonUtility.ToJson(data); // 获取项目路径 string fileUrl; if(filePath == ""){ fileUrl = Application.streamingAssetsPath + jsonFileName; }else{ fileUrl = filePath; } using(StreamWriter sw = new StreamWriter(fileUrl)) { sw.WriteLine(js); //保存数据 sw.Close(); // 关闭文档 sw.Dispose(); } Debug.Log("保存成功(*^▽^*)"); } /// <summary> /// 读取数据,在外界不需要接受Data只需要调用即可,返回的Data仅供我自己编写其他程序耦合使用,忽略返回值 /// 请在调用dict 前一定要先调用ReadData函数 /// </summary> public Data ReadData(){ // 获取项目路径 string fileUrl; if(filePath == ""){ fileUrl = Application.streamingAssetsPath + jsonFileName; }else{ fileUrl = filePath; } //读取文件 string readDate; using (StreamReader sr = File.OpenText(fileUrl)){ readDate = sr.ReadLine(); sr.Close(); } Data data = JsonUtility.FromJson<Data>(readDate); // 分配内存 if(data == null ){ data = new Data(); data.zoomPoints = new List<ZoomPoint>(); return data; } // 数据保存到字典里 foreach(ZoomPoint zp in data.zoomPoints){ dict.TryAdd(zp.name, zp); } return data; } /// <summary> /// 按点放大轴心,无法捕获动画一定确保放大的动画之间不会冲突,简化了ImageZoom的调用 /// </summary> /// <param name="zoomObj">被放大图像</param> /// <param name="key">轴心的名字</param> public void ZoomPivot(Image zoomObj, string key){ ImageZoom(zoomObj, dict[key]); } /// <summary> /// 按倍率,轴心定位的方法放大图形,如果目标的轴心不在中心,会在设定完轴心后将目标移动到轴心, /// 需要注意的事,图片的坐标位置是以轴心位置为确定的,也因此放大缩小不改变图像的世界坐标 /// </summary> /// <param name="zoomObj">需要方法的图像</param> /// <param name="x">轴心的x</param> /// <param name="y">轴心的y</param> /// <param name="zoomMagnification">放大倍率</param> /// public void ImageZoom(Image zoomObj , ZoomPoint zp){ float x = zp.pivot.x; float y = zp.pivot.y; float zoomMagnification = zp.zoomMagnification; float time = zp.time; // 当前和目标按图轴心位置 Vector3 currentPivotPostition = new Vector3(zoomObj.rectTransform.rect.width * zoomObj.rectTransform.pivot.x, zoomObj.rectTransform.rect.height * zoomObj.rectTransform.pivot.y) * zoomMagnification; Vector3 targetPivotPosition = new Vector3(zoomObj.rectTransform.rect.width * x, zoomObj.rectTransform.rect.height * y) * zoomMagnification; zoomObj.rectTransform.pivot = new Vector2(x, y); // 设定轴心 zoomObj.transform.position += targetPivotPosition - currentPivotPostition; // 重定位 Vector3 targetPostion = zoomObj.transform.position + currentPivotPostition - targetPivotPosition; //位移 Translate(zoomObj, targetPostion, time); // 2023.7.30 经过测试,缩放仍然是更具初始轴心,能够达到理想效果不需要将LocalScale恢复为1 // 为了结算范围失控的问题,需要将localScale恢复为1,再放大为需要的大小 // zoomObj.rectTransform.localScale = new Vector3(1,1,1); Vector3 targetScale = new Vector3(zoomMagnification, zoomMagnification, zoomMagnification); zoomObj.rectTransform.DOScale(targetScale, time); } // 该方法主要是需要将目标点移动到坐标终点 public void Translate(Image zoomObj, Vector3 target, float time){ // 计算当前轴心和新轴心之间的位置 Vector3 current = zoomObj.transform.position; // 移动 zoomObj.transform.DOMove(target, time); } } // 数据存储接受类 [Serializable] public class Data{ // 不能用字典直接存储,可以采用数据列表这样的连续空间 // public ZoomPoint[] zoomPoints; // public Dictionary<string, ZoomPoint> zoomPoints; public List<ZoomPoint> zoomPoints; } // 可序列化 [Serializable] public class ZoomPoint { // 点名称, 将作为Key被字典存储 public string name; // 轴心X坐标 public Vector2 pivot = Vector2.one / 2; // 放大倍率,小于1是为缩小倍率,小于0是取绝对值,不允许原点对称缩放,需要保证计算轴心逻辑正确 // 默认设为1.5f 放大倍率 public float zoomMagnification = 5f; // 改变的需要的时间,默认设为1f public float time = 1.0f; public override string ToString() { return $"name = {this.name}, pivot = ({pivot.ToString()}), zoomMagnification = {this.zoomMagnification}, time = {this.time}"; } } // 实现编译器窗口扩展 public class Editor : ScriptableWizard { // 文件路径 public string filePath = Application.streamingAssetsPath + "/2DPivots.json"; [SerializeField] public Image image; // 作为轴心点保存定位的Key new public string name; // 轴心 public Vector2 pivot; // 放大倍率 public float zoomMagnification = 5f; // 动画时间 public float time = 1.0f; [MenuItem("WSC/保存图片轴心")] public static void CreateWizard() { ScriptableWizard.DisplayWizard<Editor>("Image zoom info save","退出", "保存当前轴心"); } private int count = 1; void OnWizardCreate() { Utility.Instance.SetFilePath(filePath); Utility.Instance.ReadData(); Debug.Log("轴心更新完毕(^-^)V"); } void OnWizardOtherButton(){ pivot = image.rectTransform.pivot; if (name == null) name = (count++).ToString(); ZoomPoint zp = new ZoomPoint { name = this.name, pivot = pivot, zoomMagnification = this.zoomMagnification, time = this.time }; // reset image pivot Utility.Instance.WriteData(zp); } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。