2016-05-12 54 views
3

我正在嘗試使用可在移動設備上工作的d3.js創建交互式財富輪。眼下http://plnkr.co/edit/JBJ1odoGvfWFODuIRqKZd3財富之輪

svg.on("mousemove", function(d) { 
    if (isDown){ 
     var angleDeg = Math.atan2(lastY - d3.event.y, lastX - d3.event.x) * 180/Math.PI; 
     lastX = d3.event.x; 
     lastY = d3.event.y; 
     curAngle = angleDeg; 
     svg.attr("transform", "translate(" + width/2 + "," + height/2 + ") rotate(" + curAngle + "," + 0 + "," + 0 + ")"); 
    } 
    }); 

我試圖讓這個你可以單擊並拖動餅圖切片和「旋轉」是圍繞只要鼠標是:這是我一直在努力什麼迄今下。我使用Math.atan2來獲取鼠標移動過程中圓上兩點之間的角度,並相應地更改餅圖角度。看起來我所擁有的幾乎就在那裏,但有一個滯後/抖動。有什麼我可以做的,以使它看起來像這樣? :http://www.fusioncharts.com/charts/pie2d_5/

理想情況下,從長遠來看,我希望mouseup事件爲spin創建某種速度,並且無論向上指向哪個slice都能被查詢。

但現在我只是想創建一個平滑的拖動。

回答

4

爲什麼你是'緊張'是因爲你使用鼠標座標相互關係。你想要做的是使用一個固定點,即輪子的中心。

因此,而不是更新lastX和lastY與d.event.x/Y保持這個爲:

var lastX = width/2; //center points of circle 
var lastY = height/2; 

,並使用該在你的算法,像這樣:

if (isDown) { 
    var thisX = d3.event.x - lastX, 
     thisY = d3.event.y - lastY; 
    var angleDeg = Math.atan2(lastY - d3.event.y, lastX - d3.event.x) * 180/Math.PI; 
    svg.attr("transform", "translate(" + width/2 + "," + height/2 + ") rotate(" + angleDeg + "," + 0 + "," + 0 + ")"); 
    } 

我已經把這對JSFiddle作爲plnkr不能正常工作,與鼠標事件等等:https://jsfiddle.net/thatOneGuy/ourpo8p7/1/

即使這並不完美。

基本上這裏發生的是,它獲取鼠標座標並旋轉到該座標。但是你不想要這個,你只希望它在移動鼠標的時候移動,即使這樣你只希望它移動光標移動的量,而不是跳到光標(如果這有意義的話:P)。

所以你要做的就是從0開始,如果你在鼠標移動時移動光標,保存旋轉位置,所以當你重新開始時,你可以開始你離開的地方。這很難解釋。

反正當鼠標下來,保存鼠標座標和圓弧的中心之間的角度:

var thisX = d3.event.x - lastX, 
    thisY = d3.event.y - lastY; 
    curAngle = Math.atan2(lastY - d3.event.y, lastX - d3.event.x) 
    if (curAngle < 0) curAngle += 2 * Math.PI; //make sure its positive 
    curAngle = curAngle * 180/Math.PI; //change to degrees 

現在的鼠標移動,你有那麼你從0開始,從計算的角度對這個值了,但添加旋轉車輪時計算出的最後一個角度(如果有的話)。

var thisX = d3.event.x - lastX, 
     thisY = d3.event.y - lastY; 
    angleDeg = Math.atan2(lastY - d3.event.y, lastX - d3.event.x) // * 180/Math.PI) - curAngle 
    if (angleDeg < 0) angleDeg += 2 * Math.PI; 
    angleDeg = angleDeg * 180/Math.PI; 
    angleDeg = angleDeg - curAngle + finishAngle; //reset to 0 and add last rotation calculated 
    if (angleDeg < 0) angleDeg += 360; 
    d3.select('#degrees').text(Math.round(angleDeg)) 
    svg.attr("transform", "translate(" + width/2 + "," + height/2 + ") rotate(" + angleDeg + "," + 0 + "," + 0 + ")"); 

最後,制定出旋轉角度上面使用時mouseup

finishAngle = angleDeg; 

工作小提琴:https://jsfiddle.net/thatOneGuy/v8xce8k3/1/

+0

感謝您的詳細答覆!這很有道理,而且效果很好。 – QuantumRich

+0

我也想問你是否知道有一種方法可以爲觸摸事件做同樣的事情。是否有X,Y用於touchstart/end events? – QuantumRich

+1

@QuantumRich看看這個例子http://bl.ocks。組織/ emeeks/9e6b87735d2da05813e3 – thatOneGuy