如何将可拖拽线段限制在指定长度的圆弧范围内?
拖拽线段长度限制解决方案
核心思路
- 计算固定端点到当前拖拽位置的距离
- 若距离超过100,将拖拽点限制在以固定点为圆心、100为半径的圆周上(保持鼠标方向)
- 若距离未超过100,正常使用拖拽位置
代码修改步骤
- 在
create函数开头定义最大长度常量:
const MAX_LENGTH = 100;
- 修改
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
相关产品推荐
相关产品推荐

