Unity Image(RawImage) 实现按轴心放大缩小,序列化存储轴心信息,实现编译器窗口保存轴心

工作时分配给我的要实现的功能,写的时候遇到挺多的坑的,在此记录一下

效果

放大缩小的效果
请添加图片描述

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 updatevoid 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;// 改变的需要的时间,默认设为1fpublic 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;// 作为轴心点保存定位的Keynew 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 pivotUtility.Instance.WriteData(zp);}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/53984.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FANUC机器人SRVO-300机械手断裂故障报警原因分析及处理办法

FANUC机器人SRVO-300机械手断裂故障报警原因分析及处理办法 首先,我们查看报警说明书上的介绍: 总结:即在机械手断裂设置为无效时,机器人检测出了机械手断裂信号(不该有的信号,现在检测到了,所以报警) 使机械手断裂设定为无效/有效的具体方法:  按下示教器的MENU菜单…

弘扬“两弹一星”精神,勇攀科学技术高峰——道本科技商业大学党日活动圆满落幕

2023年8月2日&#xff0c;道本科技与商业大学携手举办了一场主题为“弘扬‘两弹一星’精神&#xff0c;勇攀科学技术高峰”的党日活动。本次活动旨在了解党领导下的中国核工业发展历程&#xff0c;传承和弘扬“两弹一星”精神&#xff0c;同时展示道本科技创新产品&#xff0c;…

智慧工地云平台源码,基于微服务+Java+Spring Cloud +UniApp +MySql开发

智慧工地可视化系统利用物联网、人工智能、云计算、大数据、移动互联网等新一代信息技术&#xff0c;通过工地中台、三维建模服务、视频AI分析服务等技术支撑&#xff0c;实现智慧工地高精度动态仿真&#xff0c;趋势分析、预测、模拟&#xff0c;建设智能化、标准化的智慧工地…

【雕爷学编程】MicroPython动手做(29)——物联网之SIoT

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

Web压测工具http_load原理分析

01、前言 http_load是一款测试web服务器性能的开源工具&#xff0c;从下面的网址可以下载到最新版本的http_load&#xff1a; http://www.acme.com/software/http_load/ 这个软件一直在保持着更新&#xff08;不像webbench&#xff0c;已经是十年的老古董了。 webbench的源…

卷积神经网络【图解CNN】

文章目录 1.卷积运算2.池化3.全连接层 卷积神经网络可以看作一个函数或者黑箱&#xff0c;输入就是图片的像素阵列&#xff0c;输出就是这个图片是什么&#xff1f; 图片是X&#xff0c;那么就输出‘x’&#xff0c;图片是‘O’,那么就输出O&#xff1b; 在计算机眼中&#xff…

Python web实战之Django用户认证详解

关键词&#xff1a; Python Web 开发、Django、用户认证、实战案例 概要 今天来探讨一下 Django 的用户认证吧&#xff01;在这篇文章中&#xff0c;我将为大家带来一些有关 Django 用户认证的最佳实践。 1. Django 用户认证 在开发 Web 应用程序时&#xff0c;用户认证是一个…

思维能力的学习

前言 在工作中&#xff0c;随着工作时间的增长&#xff0c;我们与他人的差异不是知识本身的差异&#xff0c;主要是思维方面的差异&#xff0c;所以我们需要培养自己的思维能力。 思维能力的学习 思维是一个具备内在框架和逻辑的系统工程&#xff0c;思维覆盖了学习、认知、问…

Java课题笔记~ Spring 概述

Spring 框架 一、Spring 概述 1、Spring 框架是什么 Spring 是于 2003 年兴起的一个轻量级的 Java 开发框架&#xff0c;它是为了解决企业应用开发的复杂性而创建的。Spring 的核心是控制反转&#xff08;IoC&#xff09;和面向切面编程&#xff08;AOP&#xff09;。 Spring…

Detecting Everything in the Open World: Towards Universal Object Detection

1. 论文简介 论文题目《Detecting Everything in the Open World: Towards Universal Object Detection》发表情况&#xff0c;CVPR2023[论文地址][https://arxiv.org/pdf/2303.11749.pdf][代码地址][https://github.com/zhenyuw16/UniDetector] 2.背景与摘要 本文旨在解决通…

Pytorch入门学习——快速搭建神经网络、优化器、梯度计算

我的代码可以在我的Github找到 GIthub地址 https://github.com/QinghongShao-sqh/Pytorch_Study 因为最近有同学问我如何Nerf入门&#xff0c;这里就简单给出一些我的建议&#xff1a; &#xff08;1&#xff09;基本的pytorch&#xff0c;机器学习&#xff0c;深度学习知识&a…

渗透-01:DNS原理和HTML字符编码-HTML实体编码

一、DNS概念 DNS (Domain Name System 的缩写)就是根据域名查出IP地址(常用) DNS分类&#xff1a; 正向解析&#xff1a;已知域名解析IP反向解析&#xff1a;已知IP解析对应的域名 二、查询过程 工具软件dig可以显示整个查询过程 [rootnode01 ~]# dig baidu.com; <<>&…