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

如何将可拖拽线段限制在指定长度的圆弧范围内?

拖拽线段长度限制解决方案

核心思路

  • 计算固定端点到当前拖拽位置的距离
  • 若距离超过100,将拖拽点限制在以固定点为圆心、100为半径的圆周上(保持鼠标方向)
  • 若距离未超过100,正常使用拖拽位置

代码修改步骤

  1. 在create函数开头定义最大长度常量:
const MAX_LENGTH = 100;
  1. 修改drag事件的回调函数,替换原来的直接赋值逻辑:
this.input.on('drag', function (pointer, gameObject, dragX, dragY) {
    // 获取固定端点坐标
    const fixedPoint = curve.p0;
    // 创建从固定点指向拖拽位置的向量
    const dragVector = new Phaser.Math.Vector2(dragX - fixedPoint.x, dragY - fixedPoint.y);
    // 计算当前拖拽距离
    const currentDistance = dragVector.length();

    let targetX, targetY;
    if (currentDistance > MAX_LENGTH) {
        // 超出最大长度:归一化向量(保留方向)后缩放至最大长度,再叠加固定点坐标
        dragVector.normalize().scale(MAX_LENGTH);
        targetX = fixedPoint.x + dragVector.x;
        targetY = fixedPoint.y + dragVector.y;
    } else {
        // 未超出范围:直接使用拖拽坐标
        targetX = dragX;
        targetY = dragY;
    }

    // 更新拖拽点位置和线段端点向量
    gameObject.x = targetX;
    gameObject.y = targetY;
    gameObject.data.get('vector').set(targetX, targetY);
});

完整修改后的代码

var config = {
    "type": Phaser.AUTO,
    "width": 800,
    "height": 400,
    "backgroundColor": '#2d2d2d',
    "parent": 'phaser-example',
    "scene": {
        "preload": preload,
        "create": create,
        "update": update
    }
};

var path;
var curve;
var graphics;

var game = new Phaser.Game(config);

function preload() {
    this.load.spritesheet('dragcircle', 'https://labs.phaser.io/assets/sprites/dragcircle.png', { "frameWidth": 16 });
}

function create() {
    const MAX_LENGTH = 100; // 新增:定义最大线段长度
    graphics = this.add.graphics();

    path = { "t": 0, "vec": new Phaser.Math.Vector2() };

    curve = new Phaser.Curves.Line([ 400, 390, 300, 230 ]);

    var point0 = this.add.image(curve.p0.x, curve.p0.y, 'dragcircle', 0);
  
    var point1 = this.add.image(curve.p1.x, curve.p1.y, 'dragcircle', 0).setInteractive();
  
    point1.setData('vector', curve.p1);

    this.input.setDraggable(point1);

    // 修改后的drag事件处理逻辑
    this.input.on('drag', function (pointer, gameObject, dragX, dragY) {
        const fixedPoint = curve.p0;
        const dragVector = new Phaser.Math.Vector2(dragX - fixedPoint.x, dragY - fixedPoint.y);
        const currentDistance = dragVector.length();

        let targetX, targetY;
        if (currentDistance > MAX_LENGTH) {
            dragVector.normalize().scale(MAX_LENGTH);
            targetX = fixedPoint.x + dragVector.x;
            targetY = fixedPoint.y + dragVector.y;
        } else {
            targetX = dragX;
            targetY = dragY;
        }

        gameObject.x = targetX;
        gameObject.y = targetY;
        gameObject.data.get('vector').set(targetX, targetY);
    });

    this.input.on('dragend', function (pointer, gameObject) {
      let distance = Phaser.Math.Distance.Between(curve.p0.x, curve.p0.y, curve.p1.x, curve.p1.y);
      console.log(distance);
    });
}

function update() {
    graphics.clear();
    graphics.lineStyle(2, 0xffffff, 1);

    curve.draw(graphics);

    curve.getPoint(path.t, path.vec);
}

逻辑解释

  • 向量计算:用Phaser内置的Vector2类简化数学运算,不用手动写勾股定理或三角函数
  • 归一化向量:将向量长度缩为1,只保留方向信息
  • 缩放向量:把归一化后的向量乘以最大长度100,得到方向不变、长度刚好为100的新向量
  • 坐标叠加:把新向量的坐标加到固定点坐标上,得到限制后的拖拽点位置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 10:40:32