2015-09-24 16 views
13

Pracuję nad this plnkr. Mam trzy linie pod kątem 30, 45 i 60. Chcę zastosować pędzel na tych liniach, tak aby podczas rysowania wykresu linie zostały przerysowane w miejscu, w którym przecinał przesuwane prostokąty z odpowiednimi wartościami na osi. Pomocna lub wskazówka do rozwiązania tego problemu jest bardzo doceniana.pędzel na obróconych liniach za pomocą d3, aby utworzyć efekt powiększenia

EDYCJA: Jeśli masz różne rozwiązania, aby narysować obrócone linie i pędzel na nich, jest to również mile widziane. Proszę pomóż.

var ga = d3.select("svg") 
    .append("g") 
    .attr("class", "a axis") 
    .attr("transform", "translate(" + margin.left + "," + (height + margin.top) + ")") 
    .selectAll("g") 
    .data([30, 45, 60]) 
    .enter() 
    .append("g") 
    .attr("class", "rotatedlines") 
    .attr("transform", function(d) { return "rotate(" + -d + ")"; }) 
    .attr("stroke-width", 1) 
    .attr("stroke", "black") 
    .attr("stroke-dasharray", "5,5"); 

Example result

+0

Czy chcesz zastąpić istniejący wykres nowym powiększonym widokiem, podobnym do [wykres reputacji SE] (http://stackexchange.com/users/4536689/d3-gxt-java?tab=reputation)? – approxiblue

+0

tak - Chcę nadpisać dokładnie tak, jak pokazano w przykładzie. – somename

+0

W twoim przykładzie zrobiłeś linie używając rotacji 30,45,60 ... czy to jest prawdziwy zestaw danych, czy masz jakieś prawdziwe x (data) i y (punkty) wartości jak tutaj http://stackexchange.com/users/4536689/d3-gxt-java? tab = reputation – Cyril

Odpowiedz

5

wyjaśnić moje rozwiązanie:

Podstawowe kroki podjąć, są następujące:

  • zaktualizować domeny x i y przeskalowują do zakresu szczotek
  • przerysuj osie
  • oblicz współczynnik skali i tłumaczyć acji dla linii skalę
  • i przekładać pojemniki linii odpowiednio
  • zresetować szczotka

Zauważ, że kroki 3 i 4 są konieczne tylko dlatego, że nie używasz wagi wyciągnąć wszystko - lepszy podejście polegałoby na zdefiniowaniu dwóch punktów dla każdej linii jako danych, które są powiązane z elementami, a następnie wykorzystania skal do ponownego rysowania. Ułatwi to kod.

Przy twoim podejściu nadal jest to możliwe. Aby to ułatwić, wprowadziłem kilka modyfikacji kodu - w szczególności wyczyściłem różne zagnieżdżone elementy g za pomocą różnych tłumaczeń i zdefiniowałem linie za pomocą ich atrybutów x1, x2, y1, y2, zamiast poprzez tłumaczenie pojemników. Obie te zmiany ułatwiają implementację funkcjonalności, ponieważ tylko jedna transformacja ma miejsce, co nie wymaga uwzględnienia wielu innych transformacji. Zagnieżdżono również linie w wielu elementach g, dzięki czemu można je łatwiej skalować i tłumaczyć.

Funkcja obsługi szczotka teraz wygląda tak:

// update scales, redraw axes 
var extent = brush.extent(); 
x.domain(brush.empty() ? x2.domain() : [ extent[0][0], extent[1][0] ]); 
y.domain(brush.empty() ? y2.domain() : [ extent[0][1], extent[1][1] ]); 
xAxisG.call(xAxis); 
yAxisG.call(yAxis); 

Kod ten powinien być dość oczywista - Domeny skalach są aktualizowane zgodnie z aktualnym stopniu szczotki i osie są przerysowane .

// compute and apply scaling and transformation of the g elements containing the lines 
var sx = (x2.domain()[1] - x2.domain()[0])/(x.domain()[1] - x.domain()[0]), 
    sy = (y2.domain()[1] - y2.domain()[0])/(y.domain()[1] - y.domain()[0]), 
    dx = -x2(x.domain()[0]) - x2.range()[0], 
    dy = -y2(y.domain()[1]) - y2.range()[1]; 
d3.selectAll("g.container") 
    .attr("transform", "translate(" + [sx * dx, sy * dy] + ")scale(" + [sx, sy] + ")"); 

To jest skomplikowana część - na podstawie nowych dziedzin skalach, musimy obliczyć skalę i tłumaczenie wierszy. Czynniki skalujące to po prostu stosunek starego zakresu do nowego zakresu (zauważ, że zrobiłem kopie skal, które nie zostały zmodyfikowane), tj. Liczba większa niż 1. Tłumaczenie określa przesunięcie (0,0) współrzędna i jest obliczana na podstawie różnicy starej (0,0) współrzędnej (otrzymuję ją z zakresu oryginalnych skal) i pozycji nowego pochodzenia domeny zgodnie z oryginalnymi skalami.

Stosując tłumaczenie i skalę w tym samym czasie, musimy pomnożyć przesunięcia za pomocą współczynników skalowania.

// reset brush 
brush.clear(); 
d3.select(".brush").call(brush); 

Na koniec wyczyszczamy pędzel i resetujemy go, aby pozbyć się szarego prostokąta.

Kompletne demo here.

+0

dziękuję bardzo lars - to jest niesamowite! – somename

2

Można uzyskać dostęp do zakresu pędzla poprzez d3.event.target.extent(). Przepływ na rysunku skala jest taka:

  • skala Set
  • oś Set
  • Draw oś

Jak tylko szczotka jest zrobione, trzeba zmodyfikować skalę, a następnie ponownie -wybierz oś zgodnie z bieżącą domeną x i y. Czy to miałeś na myśli?

ja oczyścić kod trochę i zrobił mały pokaz: http://plnkr.co/edit/epKbXbcBR2MiwUOMlU5A?p=preview

+0

Dziękuję za odpowiedź .. Muszę przerysować również obrócone linie - tam, gdzie przecinały się one ze szczotkowanym obszarem. Jeśli obszar pędzla nie przecina obróconych linii, nie powinien pojawić się na przerysowanej mapie. Czy masz pojęcie, jak to osiągnąć? – somename

+0

To jest prosta część, myślałem, że już to rozwiązałeś :-) Zobacz tę wersję: http://plnkr.co/edit/Aw6Gc1PNGtiVSWXNaJU2?p=preview W linii 116. Podzielę płótno i linie, a następnie może przeskalować element 'g' z czymś podobnym do' transform = "translate (-50, 470) scale (2)" '. – Rudolf

+0

Btw, d3 ma również bibliotekę powiększania, z której można było wypożyczyć matematykę. – Rudolf

Powiązane problemy