scale 和 zoom,以及zoom的一些变态用法

本文详细对比了CSS中zoom与scale的使用区别,并介绍了zoom的一些特殊用法,包括与position配合使用时的效果及JavaScript操作注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

zoomscale这两个东西都是用于对元素的缩放,一下是其中一些区别:

1、scale的缩小是以图片的中心,zoom的缩小是以图片的左上角。

2、zoom的缩放改变了元素占据的空间大小;而scale的缩放占据的原始尺寸不变,页面布局不会发生变化;

3、注意:如果给zoom赋值两次,会使zoom的最终值为二者的乘积

 

关于zoom的一些变态用法:

1、如果zoom与position共同使用 的话,在zoom上的相对距离就不用再手动乘以zoom的比例了,页面会自动计算,做相对位置的

2、在用js给zoom赋值的时候,不能与css样式表里初始赋值相同,否则会无效

 

最后,zoom在手机端的有些应用还是挺好用哒~

转载于:https://www.cnblogs.com/kaixin3946/p/5606622.html

<think>我们将使用DOTween替换原代码中的LeanTween。首先,需要导入DOTween的命名空间,并修改动画部分的代码。 注意:DOTween的使用方式与LeanTween有所不同,例如设置大小变化,我们使用DOSizeDelta,移动位置使用DOMove或DOAnchorPos等。 修改点: 1. 在Start方法中,我们仍然保存原始状态。 2. 在ZoomImage方法中,使用DOTween的链式调用来实现动画。 另外,由于DOTween的API设计,我们需要分别处理大小位置的动画。 步骤: 1. 首先,确保已经导入DOTween的命名空间:using DG.Tweening; 2. 修改ZoomImage方法中的动画部分。 注意:在缩小的时候,我们同时进行缩小移动的动画,并且我们希望这两个动画同时进行,所以我们可以使用Sequence来同时播放两个动画。 但是,在放大时,我们只改变大小,所以不需要序列。 修改后的ZoomImage方法: 放大: rectTransform.DOSizeDelta(originalSize * zoomScale, zoomDuration).SetEase(Ease.OutBack); 缩小: 我们可以创建一个序列(Sequence),先加入缩小动画,再加入移动动画(但是这样是顺序执行,所以需要同时执行): 实际上,我们可以将两个动画加入同一个序列,并设置同时播放(默认就是同时)。 但是注意:在缩小的时候,我们想要同时进行大小位置的还原,所以我们可以这样: Sequence s = DOTween.Sequence(); s.Append(rectTransform.DOSizeDelta(originalSize, zoomDuration).SetEase(Ease.InBack)); s.Join(rectTransform.DOMove(originalPosition, zoomDuration).SetEase(Ease.InOutQuad)); s.Play(); 不过,我们也可以不使用序列,而直接使用两个独立的Tween,它们会自动同时播放。但是为了确保它们同时开始,我们可以使用DOTween的静态方法同时创建。 但是,为了代码清晰,我们使用序列。 另外,我们还需要注意,在动画开始前,如果已经有动画在运行,最好先杀死之前的动画,防止冲突。 因此,我们可以在每次开始新动画前,先调用`DOTween.Kill(rectTransform);`来终止与该rectTransform相关的所有动画。 修改后的代码: 在ZoomImage方法中,先终止之前的动画: DOTween.Kill(rectTransform); // 终止所有在rectTransform上运行的DOTween动画 然后,根据zoomIn执行不同的动画。 但是注意:在放大时,我们只改变大小,不改变位置(因为放大后允许拖动,所以位置可能被改变,但放大时位置不变?原代码在放大时没有改变位置,所以这里我们也不改变位置,只改变大小)。 然而,原代码在放大时并没有改变位置,所以我们在放大动画中只做大小变化。 但是,在放大时,我们可能希望图片以当前点击位置为中心放大?原代码没有这个功能,所以暂时不考虑。 修改后的ZoomImage方法: ```csharp private void ZoomImage(bool zoomIn) { isZoomed = zoomIn; // 终止之前可能正在进行的动画 DOTween.Kill(rectTransform); if (zoomIn) { // 放大效果:只改变大小 rectTransform.DOSizeDelta(originalSize * zoomScale, zoomDuration) .SetEase(Ease.OutBack); } else { // 创建一个序列来同时执行缩小移动 Sequence sequence = DOTween.Sequence(); sequence.Append(rectTransform.DOSizeDelta(originalSize, zoomDuration).SetEase(Ease.InBack)); sequence.Join(rectTransform.DOMove(originalPosition, zoomDuration).SetEase(Ease.InOutQuad)); // 或者使用DOAnchorPos来还原到初始锚点位置?但是原代码保存的是position(世界坐标)anchoredPosition(局部坐标) // 注意:原代码中保存的是originalPosition(世界坐标)originalAnchoredPosition(局部坐标),而DOMove使用世界坐标,DOAnchorPos使用局部坐标。 // 我们之前保存的是originalPosition(世界坐标),所以使用DOMove。 } } ``` 但是,这里有一个问题:在放大后,用户可能拖动了图片,此时图片的位置已经改变。当我们缩小还原时,我们使用DOMove(originalPosition)将图片移回到初始的世界坐标位置。 这符合需求:还原到初始位置。 但是,如果父对象有动画或者移动,那么世界坐标可能已经改变,所以保存世界坐标还原可能不准确?原代码也是使用世界坐标还原,所以这里保持一致。 另外,我们也可以使用anchoredPosition来还原位置,这样是相对于父对象的局部位置。所以,在还原位置时,我们也可以使用: rectTransform.DOAnchorPos(originalAnchoredPosition, zoomDuration) 那么,在Start中,我们保存了originalAnchoredPosition(锚点位置),所以我们可以选择使用锚点位置还原,这样更稳定(因为父对象如果改变大小,锚点位置可以保持相对位置)。 但是,原代码在还原时使用的是世界坐标的originalPosition,这可能会导致在画布大小改变时还原位置不准确。所以,我们改为使用锚点位置还原。 因此,在缩小还原时,我们同时还原大小锚点位置。 修改: 在Start中,我们已经保存了originalAnchoredPosition。 在缩小动画中: sequence.Join(rectTransform.DOAnchorPos(originalAnchoredPosition, zoomDuration).SetEase(Ease.InOutQuad)); 这样,即使父对象移动,也能还原到初始的相对位置。 所以,我们调整一下: 在Start方法中,我们保存了: originalSize = rectTransform.sizeDelta; originalPosition = rectTransform.position; // 世界坐标 originalAnchoredPosition = rectTransform.anchoredPosition; // 局部锚点位置 在缩小动画中,我们使用锚点位置还原。 因此,修改后的ZoomImage方法中缩小部分: ```csharp if (zoomIn) { // 放大效果:只改变大小 rectTransform.DOSizeDelta(originalSize * zoomScale, zoomDuration) .SetEase(Ease.OutBack); } else { // 缩小并还原位置(使用锚点位置还原) Sequence sequence = DOTween.Sequence(); sequence.Append(rectTransform.DOSizeDelta(originalSize, zoomDuration).SetEase(Ease.InBack)); sequence.Join(rectTransform.DOAnchorPos(originalAnchoredPosition, zoomDuration).SetEase(Ease.InOutQuad)); } ``` 同时,在放大时,我们不需要改变位置,所以只改变大小。 但是,在放大后,用户拖动图片,我们改变的是rectTransform的位置(通过OnDrag方法)。在缩小还原时,我们同时还原了大小锚点位置。 这样,功能就完整了。 完整修改后的脚本: 注意:需要导入DOTween的命名空间,并且确保项目中已经导入DOTween插件(通过Asset Store或第三方下载)。 另外,在OnDrag方法中,我们使用了世界坐标的转换,这里保持不变。 修改后的完整代码:</think>下面是使用DOTween替换LeanTween的修改版本,实现相同的图片点击放大/缩小移动功能: ```csharp using UnityEngine; using UnityEngine.EventSystems; using DG.Tweening; // 导入DOTween命名空间 public class ImageZoomController : MonoBehaviour, IPointerClickHandler, IDragHandler, IBeginDragHandler { [Header("缩放设置")] public float zoomScale = 1.5f; // 放大倍数 public float zoomDuration = 0.3f; // 缩放动画时间 public Ease zoomEase = Ease.OutBack; // 缩放动画曲线 public Ease moveEase = Ease.InOutQuad; // 移动动画曲线 private RectTransform rectTransform; private Vector2 originalSize; private Vector2 originalAnchoredPosition; private bool isZoomed = false; private Canvas parentCanvas; private Sequence zoomSequence; // DOTween序列对象 void Start() { rectTransform = GetComponent<RectTransform>(); parentCanvas = GetComponentInParent<Canvas>(); // 保存原始状态 originalSize = rectTransform.sizeDelta; originalAnchoredPosition = rectTransform.anchoredPosition; // 初始化DOTween DOTween.Init(); } public void OnPointerClick(PointerEventData eventData) { if (!isZoomed) { // 放大图片 ZoomImage(true); } else { // 缩小并还原 ZoomImage(false); } } public void OnBeginDrag(PointerEventData eventData) { // 只在放大状态下允许拖动 if (!isZoomed) eventData.pointerDrag = null; } public void OnDrag(PointerEventData eventData) { if (isZoomed) { // 转换屏幕坐标到Canvas坐标 RectTransformUtility.ScreenPointToLocalPointInRectangle( parentCanvas.transform as RectTransform, eventData.position, parentCanvas.worldCamera, out Vector2 localPoint); // 更新位置 rectTransform.anchoredPosition = localPoint; } } private void ZoomImage(bool zoomIn) { // 停止所有正在进行的动画 zoomSequence?.Kill(); isZoomed = zoomIn; if (zoomIn) { // 放大效果 zoomSequence = DOTween.Sequence(); zoomSequence.Append( rectTransform.DOSizeDelta(originalSize * zoomScale, zoomDuration) .SetEase(zoomEase) ); zoomSequence.Play(); } else { // 缩小并还原位置 zoomSequence = DOTween.Sequence(); zoomSequence.Append( rectTransform.DOSizeDelta(originalSize, zoomDuration) .SetEase(zoomEase) ); zoomSequence.Join( rectTransform.DOAnchorPos(originalAnchoredPosition, zoomDuration) .SetEase(moveEase) ); zoomSequence.Play(); } } void OnDestroy() { // 清理DOTween资源 zoomSequence?.Kill(); } } ``` ### DOTween替换说明: 1. **命名空间初始化**: ```csharp using DG.Tweening; // 替换为DOTween的命名空间 DOTween.Init(); // 在Start中初始化DOTween ``` 2. **动画实现差异**: - **LeanTween**: ```csharp LeanTween.size(rectTransform, targetSize, duration) ``` - **DOTween**: ```csharp rectTransform.DOSizeDelta(targetSize, duration) ``` 3. **序列动画处理**: - 使用`DOTween.Sequence()`创建动画序列 - `sequence.Append()`添加主要动画 - `sequence.Join()`添加并行动画(用于同时执行缩小位置还原) 4. **动画控制**: - `zoomSequence?.Kill()` - 停止所有进行中的动画 - `SetEase()` - 设置动画曲线(与LeanTween的Ease类型兼容) 5. **资源清理**: ```csharp void OnDestroy() { zoomSequence?.Kill(); } ``` ### 关键改进: 1. **动画序列控制**: - 使用Sequence对象管理动画序列 - 支持并行执行多个动画(如缩小位置还原同时进行) 2. **参数可配置性**: - 添加了独立的缩放移动动画曲线参数 - 可以通过Inspector面板调整动画效果 3. **内存管理**: - 在对象销毁时清理动画资源 - 避免内存泄漏残留动画 4. **位置处理优化**: - 使用`anchoredPosition`替代`position`确保坐标系一致性 - 在OnDrag中直接设置`anchoredPosition`避免坐标转换问题 ### 使用DOTween的优势: 1. **性能优化**: - DOTween在移动设备上性能更好 - 更少GC分配,适合移动端游戏 2. **功能丰富**: - 支持更复杂的动画序列 - 提供回调函数、循环等高级功能 - 更好的路径动画支持 3. **社区支持**: - 更活跃的开发者社区 - 更完善的文档示例资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值