Raphael.js attr函数设置了错误的值

时间:2015-09-23 11:34:40

标签: javascript svg raphael

我正在用Raphael.js实现一个拖放系统。为此,我将原始的x和y位置存储在mousedown上,如果鼠标上有碰撞,我想将位置重置为原始位置。这是重置的代码(“this”指的是raphael对象):

    var transformString = "t" + this.original_x + "," + this.original_y;
    this.attr("transform", transformString);

奇怪的是,在设置属性后,变换字符串会改变几个像素。我调用了这个:

    var transformString = "t" + this.original_x + "," + this.original_y;
    this.attr("transform", transformString);
    console.log("transformString: " + transformString);
    console.log("transformAttrib: " + this.attr("transform"));

AFAIK,两种记录值在任何情况下都应该相等。但它们有时会下降20px。有谁知道这里发生了什么?

E:这是一个简化版本,没有碰撞测试,仍然会重现错误:http://jsfiddle.net/6ozsfdaf

3 个答案:

答案 0 :(得分:1)

我不太确定为什么会出现这个问题,但我想知道这是否是一个更好的解决方案。而不是每次解析字符串,只需存储转换并使用它。

我还将它切换为使用transform()方法,而不是attr(transform:..)方法。虽然我认为这通常会起作用,但逻辑​​上并不完全正确,因为SVG属性不会使用Raphael变换字符串,但我认为Raph会截取并处理它(但可能更容易出错)。

在变换字符串中也要注意't'是相对变换而'T'是绝对变换(我不认为那是因为没有先前的变换,但是我想知道它是否是也相关)。

this.start = function() {
    if (this.reference.static) return;
    this.original_t = this.transform();
    this.animate({r: 70, opacity: 0.25}, 500, ">");
};

this.move = function(dx, dy) {
    this.transform( this.original_t + 't' + dx + ',' + dy);
};

this.up = function() {
    this.transform( this.original_t );
    console.log("transformString: " + this.original_t);
    console.log("transformAttrib: " + this.transform());

    this.attr({fill: "#fff"});
    this.animate({r: 50, opacity: 1}, 500, ">");
};

jsfiddle

答案 1 :(得分:1)

我不确定为什么会这样。我甚至尝试使用onstart事件在onmousedown之前捕获坐标,即使这不起作用。 Raphael提供的使用getBBox()获取坐标的不同方法,直接访问xy也没有帮助。

所以我想的是,我们应该手动维护和跟踪坐标。因此,我使用了original_xoriginal_y变量,这些变量在您创建并使用某个变换值设置后捕获<path>的位置。以下是相同的代码

这是工作fiddle

this.raph = R.path(svgPath).attr({
    stroke: "hsb(0, 1, 1)",
    fill: "#fff", 
    opacity: 1.0, 
    cx: 100, 
    cy: 900 
}).transform("t" + x + "," + y); 

this.raph.original_x = x;
this.raph.original_y = y;


//comment the lines in start method which captures original_x and original_y
//this.original_x = Raphael.parseTransformString(this.attr("transform"))[0][1];
//this.original_y = Raphael.parseTransformString(this.attr("transform"))[0][2];

有关跟踪坐标的更多信息:

我们将再增加一个坐标updated_xupdated_y,它将在move方法中更新。 onFinish / onUp方法,我们可以检查是否应该更新新位置。在这里,它只是询问是否应该更新新位置,并根据我们的输入,设置最终结果。

检查fiddle

this.start = function() {
    if (this.reference.static) return;
    //this.original_x = Raphael.parseTransformString(this.attr("transform"))[0][1];
    //this.original_y = Raphael.parseTransformString(this.attr("transform"))[0][2];
    this.animate({r: 70, opacity: 0.25}, 500, ">");
    this.updated_x = this.original_x;
    this.updated_y = this.original_y;
};

this.move = function(dx, dy) {
    //var ts = Raphael.parseTransformString(this.attr("transform"));
    this.updated_x = this.original_x + dx;
    this.updated_y = this.original_y + dy;
    //ts[0][1] = this.original_x + dx; 
    //ts[0][2] = this.original_y + dy; 
    this.attr({transform: 't' + this.updated_x + ',' + this.updated_y});
};

this.up = function() {

    if(confirm("Shall I update the new position??")) {
        this.original_x = this.updated_x;
        this.original_y = this.updated_y;
    }

    var transformString = "t" + this.original_x + "," + this.original_y;
    this.attr("transform", transformString);    
    this.attr({fill: "#fff"});
    this.animate({r: 50, opacity: 1}, 500, ">");
};

答案 2 :(得分:1)

找到一个有趣的修复:如果你向this.original_x和this.original_y添加epsilon,你可以避免这种情况。如果this.original_x和this.original_y与起始坐标不完全相同,问题似乎就消失了。查看:http://jsfiddle.net/6ozsfdaf/13/

this.up = function() {
    var ts; 
    this.original_x += 0.0000000001;
    this.original_y += 0.0000000001;
    var transformString = "t" + this.original_x + "," + this.original_y;
    this.attr("transform", transformString);
    console.log("transformString: " + transformString);
    console.log("transformAttrib: " + this.attr("transform"));

    this.attr({fill: "#fff"});
    this.animate({r: 50, opacity: 1}, 500, ">");
};

修改 发现了问题。在Raphael中,Raphael.parseTransformString()的输出被缓存并重用。在你的move()方法中,你修改了Raphael.parseTransformString()的输出,当你为它提供相同的字符串时,Raphael会尝试使用你修改过的数组。注册第一个drag()事件时会发生这种情况。您要求它解析当前位置,然后使用新位置更新数组的输出数组。然后,稍后,当调用this.up()时,您使用相同的字符串提供Raphael.parseTransformString()。拉斐尔然后使用你修改过的数组阵列。这是固定的小提琴:http://jsfiddle.net/6ozsfdaf/16/

这是代码(每次移动时使用一个新的数组数组进行转换):

this.move = function(dx, dy) {
    var ts = [];
    ts.push(new Array('t'));
    ts[0][1] = this.original_x + dx; 
    ts[0][2] = this.original_y + dy; 
    this.attr({transform: ts.toString()});
};