2015-09-23 56 views
2

我正在用Raphael.js實現拖放系統。爲此,我將mousedown上的原始x和y位置存儲起來,如果在mouseup上存在碰撞,我想將位置重置爲原始位置。下面是代碼,不會復位位(「本」指的是拉斐爾對象這裏):Raphael.js attr函數設置錯誤值

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:這是一個簡化版本,不用碰撞測試,這仍然再現BUG:http://jsfiddle.net/6ozsfdaf

+0

您可以創建樣品的jsfiddle這並分享? – rajuGT

+0

是的,這裏是一個簡化版本,沒有碰撞測試,它仍然重現了這個錯誤:https://jsfiddle.net/6ozsfdaf/ – 1nterference

回答

1

我不知道爲什麼會這樣。我甚至嘗試使用onmousedown事件捕獲onstart之前的座標,甚至沒有工作。 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, ">"); 
}; 
+0

這是一個很好的臨時解決方案,但仍然無法完全工作。在你的小提琴中,如果你第一次把物體拉得很快,你仍然可以將它的位置改變大約20-30px。 – 1nterference

+0

我嘗試了很多次,拉對象,但也沒有發現小的差異。你是指紙張/窗戶?如果是這樣的話,它只是等待鼠標指針進入紙張,最後在onclick它坐下來,它最初。 – rajuGT

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

發現了一個有趣的解決辦法:你能避免這種情況,如果你添加的埃普西隆既this.original_x和this.original_y。如果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()。 Raphael然後使用您修改過的數組數組。這是固定的小提琴: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()}); 
};