You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Visual Studio 2017中用CocosSharp实现CCLayer双指缩放遇阻求助

解决CocosSharp中CCLayer双指缩放无效果的问题

首先,咱们来拆解下你代码里的核心问题,再给出更合理的实现方案:

1. 选错了触摸事件:OnTouchesBegan只触发一次

OnTouchesBegan是在触摸刚按下时触发的,这时候PreviousLocationOnScreen和当前LocationOnScreen其实是同一个点,算出来的Delta必然是0,自然不会有缩放效果。双指缩放需要在手指移动过程中持续计算距离变化,所以得用OnTouchesMoved事件来处理。

2. 缩放逻辑不合理:直接累加距离差会导致失控

你现在把距离差直接加到ScaleX/Y上,这种方式会让缩放速度完全不可控,也不符合用户的操作直觉。正确的做法应该是计算当前两指距离和上一次距离的比例,用这个比例去乘以当前的缩放值,这样缩放才会跟着手指的开合幅度线性变化。

修正后的完整实现

下面是调整后的代码,我会标注关键细节:

第一步:绑定正确的触摸事件

先把监听器的事件换成OnTouchesMoved:

var touchListener = new CCEventListenerTouchAllAtOnce();
// 替换为移动事件处理
touchListener.OnTouchesMoved = HandleTouchMoved;
// 记得在触摸结束时重置状态
touchListener.OnTouchesEnded = (touches, evt) => _lastTouchDistance = 0;
touchListener.OnTouchesCancelled = (touches, evt) => _lastTouchDistance = 0;
layer.AddEventListener(touchListener);

第二步:实现正确的缩放逻辑

编写HandleTouchMoved方法,同时处理缩放范围和中心优化:

// 记录上一次的双指距离,避免每次用单指的PreviousLocation计算误差
private double _lastTouchDistance = 0;

private void HandleTouchMoved(List<CCTouch> touches, CCEvent touchEvent)
{
    if (touches.Count != 2)
    {
        // 非双指触摸时重置状态
        _lastTouchDistance = 0;
        return;
    }

    CCTouch t1 = touches[0];
    CCTouch t2 = touches[1];

    // 优先使用图层坐标系下的触摸点,避免屏幕坐标和节点坐标的转换问题
    CCPoint loc1 = t1.GetLocation(layer);
    CCPoint loc2 = t2.GetLocation(layer);

    // 计算当前两指距离
    double currentDistance = Math.Sqrt(Math.Pow(loc1.X - loc2.X, 2) + Math.Pow(loc1.Y - loc2.Y, 2));

    if (_lastTouchDistance > 0)
    {
        // 计算缩放比例
        double scaleRatio = currentDistance / _lastTouchDistance;

        // 应用等比缩放
        layer.Scale *= (float)scaleRatio;

        // 可选:限制缩放范围,防止图层缩得太小或太大
        layer.Scale = Math.Clamp(layer.Scale, 0.5f, 3f);

        // 可选:以两指中点为中心缩放,让操作更自然
        CCPoint midPoint = new CCPoint((loc1.X + loc2.X) / 2, (loc1.Y + loc2.Y) / 2);
        CCPoint localMidPoint = layer.ConvertToNodeSpace(midPoint);
        layer.Position = layer.Position + (localMidPoint - layer.AnchorPointInPoints) * (1 - (float)scaleRatio);
    }

    // 更新上次距离为当前值
    _lastTouchDistance = currentDistance;
}

额外提示

如果发现缩放方向不对或者坐标偏移,可以检查下是否是坐标系的问题——CocosSharp的节点坐标系和屏幕坐标系Y轴方向可能相反,用t1.GetLocation(layer)直接获取图层内的触摸点,能避免大部分坐标转换问题。

内容的提问来源于stack exchange,提问作者Alexus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:42:12