Javascript 沿直线拖动圆

Javascript 沿直线拖动圆,javascript,fabricjs,Javascript,Fabricjs,我想用fabric.js沿直线拖动一个圆,因此当用户用鼠标选择圆并拖动它时,它只会沿直线移动。 下面是我用一条线和一个圆做的一个小提琴,它应该沿着这条线移动: 圆圈正在移动,但边界错误。(移动的逻辑真的很混乱,很抱歉:/,我试图对其进行有益的评论) 这是我的代码,到目前为止(要查看它的实际操作,请查看小提琴): var canvas=newfabric.canvas('canvas'); fabric.Object.prototype.originX=fabric.Object.prototy

我想用fabric.js沿直线拖动一个圆,因此当用户用鼠标选择圆并拖动它时,它只会沿直线移动。 下面是我用一条线和一个圆做的一个小提琴,它应该沿着这条线移动:

圆圈正在移动,但边界错误。(移动的逻辑真的很混乱,很抱歉:/,我试图对其进行有益的评论)

这是我的代码,到目前为止(要查看它的实际操作,请查看小提琴):

var canvas=newfabric.canvas('canvas');
fabric.Object.prototype.originX=fabric.Object.prototype.originY='center';
var line1=新织物线([50,50,100,70]{
填充:“红色”,
笔划:“红色”,
冲程宽度:2,
左:80,,
前50名,
scaleX:2,
斯卡利:2,
可选:false
});
var c=新织物。圆({
左:80,,
前50名,
冲程宽度:2,
半径:5,
填写:“#000”,
笔划:“#000”
});
c、 hasControls=c.hasBorders=false;
c、 line1=line1;
canvas.add(第1行,c);
/**
*计算两个二维向量的点积。
*/
函数点向量(v1_x,v1_y,v2_x,v2_y){
返回(v1_x*v2_x)+(v1_y*v2_y);
}
/**
*计算二维向量的幅值(长度)。
*/
函数幅值向量(v_x,v_y){
返回Math.sqrt((v_x*v_x)+(v_y*v_y));
}
功能项目(pBase_x,pBase_y,pEnd_x,pEnd_y,pEnd2_x,pEnd2_y){
//==从p1到p2的vec===
var v1_x=(pEnd_x-pBase_x);
var v1_y=(未决-基础);
//==从oldLinePoint到p2的矢量===
var v2_x=(pEnd2_x-pBase_x);
var v2_y=(pEnd2_y-pBase_y);
//==v2上的项目v1===
var vProj=项目向量(v1_x,v1_y,v2_x,v2_y);
//==焦油向量===
var vTar_x=pBase_x+vProj[0];
var vTar_y=pBase_y+vProj[1];
返回[vTar_x,vTar_y];
}
功能项目(v1_x,v1_y,v2_x,v2_y){
//==点积v1 v2===
var v1v2_dot=dot_vec(v1_x,v1_y,v2_x,v2_y);
//==v2的大小===
var v1_mag=震级向量(v1_x,v1_y);
//==向量项目v1至v2===
var facVProj=(v1v2_点)/(v1_mag*v1_mag);
var vProj_x=facVProj*v1_x;
var vProj_y=facVProj*v1_y;
返回[vProj_x,vProj_y];
}
canvas.on('object:moving',function(e){
var对象=e.target;
var objType=object.get('type');
setCoords();
var mouse=canvas.getPointer(event.e);
//==从线路起点到线路终点的矢量控制===
变量向量_linestart_lineend_x=(line1.x1-line1.x2);
变量向量_linestart_lineend_y=(line1.y1-line1.y2);
//==从鼠标到线端的向量===
var vector_mouse_line_x=(mouse.x-line1.x2);
var vector_mouse_line_y=(mouse.y-line1.y2);
//==向量项目v1至v2===
var vProj=proj_vec(向量_linestart_lineend_x,向量_linestart_lineend_y,向量_mouse_line_x,向量_mouse_line_y);
var vProj_x=vProj[0];
var vProj_y=vProj[1];
//==目标结果===
var vTar_x=line1.x2+vProj_x;
var vTar__y=line1.y2+vProj_y;
//==端点之间的剪辑点===
var vProj_len=震级Vec(vProj_x,vProj_y);
var v1_len=幅值向量(向量线开始线结束x,向量线鼠标y);
如果(vProj_len<0){
vTar_x=line1.x2;
vTar_y=线路1.y2;
}
如果(vProj_len>v1_len){
vTar_x=line1.x1;
vTar_y=线路1.y1;
}
//console.log(vTar_x+“”+vTar_y);
set({'left':vTar_x});
set({'top':vTar_y});
});
谢谢你的帮助

var canvas = new fabric.Canvas('canvas');
fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';

var line1 = new fabric.Line([50, 50, 100, 70], {
  fill: 'red',
  stroke: 'red',
  strokeWidth: 2,
  left: 80,
  top: 50,
  scaleX: 2,
  scaleY: 2,
  selectable: false
});

var c = new fabric.Circle({
  left: 80,
  top: 50,
  strokeWidth: 2,
  radius: 5,
  fill: '#000',
  stroke: '#000'
});
c.hasControls = c.hasBorders = false;
c.line1 = line1;

canvas.add(line1, c);


/**
 * Calculates the dot product of two 2-Dimensional Vectors.
 */
function dot_vec(v1_x, v1_y, v2_x, v2_y){
    return (v1_x*v2_x) + (v1_y*v2_y);
}

/**
 * Calculates the magnitude(length) of a 2-Dimensional Vector.
 */
function magnitudeVec(v_x, v_y){
    return Math.sqrt( (v_x*v_x) + (v_y*v_y) );
}


function proj_vec(pBase_x, pBase_y, pEnd_x, pEnd_y, pEnd2_x, pEnd2_y){
    //=== vec from p1 to p2 ===
    var v1_x = (pEnd_x - pBase_x);
    var v1_y = (pEnd_y - pBase_y);

    //=== vec from oldLinePoint to p2 ===
    var v2_x = (pEnd2_x - pBase_x);
    var v2_y = (pEnd2_y - pBase_y);

    //=== proj v1 on v2 ===
    var vProj = proj_vec(v1_x, v1_y, v2_x, v2_y);

    //=== tar vec ===
    var vTar_x = pBase_x + vProj[0];
    var vTar_y = pBase_y + vProj[1];

    return [vTar_x, vTar_y];
}

function proj_vec(v1_x, v1_y, v2_x, v2_y){
    //=== dot product v1 v2 ===
    var v1v2_dot = dot_vec(v1_x, v1_y, v2_x, v2_y);

    //=== magnitude of v2 ===
    var v1_mag = magnitudeVec(v1_x, v1_y);


    //=== vec proj. v1 to v2 ===
    var facVProj = (v1v2_dot) / (v1_mag*v1_mag);
    var vProj_x = facVProj * v1_x;
    var vProj_y = facVProj * v1_y;

    return [vProj_x, vProj_y];
}



canvas.on('object:moving', function(e) {
  var object = e.target;
  var objType = object.get('type');
  object.setCoords();
  var mouse = canvas.getPointer(event.e);

    //=== vec from line start to line end ===
    var vector_linestart_lineend_x = (line1.x1 - line1.x2);
    var vector_linestart_lineend_y = (line1.y1 - line1.y2);

    //=== vec from mouse to line end ===
    var vector_mouse_line_x = (mouse.x - line1.x2);
    var vector_mouse_line_y = (mouse.y - line1.y2);

    //=== vec proj. v1 to v2 ===
    var vProj = proj_vec(vector_linestart_lineend_x, vector_linestart_lineend_y, vector_mouse_line_x, vector_mouse_line_y);
    var vProj_x = vProj[0];
    var vProj_y = vProj[1];

    //=== target result ===
    var vTar_x = line1.x2 + vProj_x;
    var vTar_y = line1.y2 + vProj_y;


    //=== clip Point between endpoints ===
    var vProj_len = magnitudeVec(vProj_x, vProj_y);
    var v1_len = magnitudeVec(vector_linestart_lineend_x, vector_mouse_line_y);

    if (vProj_len < 0) {
        vTar_x = line1.x2;
        vTar_y = line1.y2;
    }
    if (vProj_len > v1_len) {
        vTar_x = line1.x1;
        vTar_y = line1.y1;
    }

    // console.log(vTar_x + " " + vTar_y);

   object.set({'left': vTar_x});
   object.set({'top': vTar_y});

});