2013-03-29 9 views
5

Jestem nowy w js i D3. Wygenerowałem mapę termiczną sortowania i chciałbym zmienić kolor płytki za pomocą funkcji on.mouse na D3. Mogę wyraźnie zmienić kolor, ale chcę użyć aktywnej reguły CSS. Prawdopodobnie coś prostego do naprawienia. Każda pomoc będzie bardzo ceniona. Pełny kod znajduje się poniżej.Zmiana koloru D3 na mouseover przy użyciu klasy ("active", true)

Dzięki.

<!DOCTYPE html> 
<meta charset="utf-8"> 
<head> 
<script src="http://d3js.org/d3.v3.min.js"></script> 
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> 
<title>MJ-Heatmap</title> 
<header> 
<H1>Country By District_Port_Nme Heatmap</H1> 
<p></p> 
</header> 
<style> 
body { 
font: 10px sans-serif; 
} 
.label { 
font-weight: bold; 
} 
.tile { 
shape-rendering: crispEdges; 
} 
.axis path, 
.axis line { 
fill: none; 
stroke: #000; 
shape-rendering: crispEdges; 
} 
<!-- CSS active state not working -- > 
.tile active { 
fill: red; 
} 
</style> 
</head> 
<body> 
<script type="text/javascript"> 
var buckets = [ 
{country:"Brazil", distrinct_port_nme:"Baltimore, Maryland", sum_teu: 2, sum_weight: 18585, count_shipments: 1}, 
{country:"Colombia", distrinct_port_nme:"Baltimore, Maryland", sum_teu:28, sum_weight:258028, count_shipments:11}, 
{country:"Brazil", distrinct_port_nme:"Chicago, Illinois", sum_teu: 2, sum_weight: 18585, count_shipments: 1}, 
{country:"Colombia", distrinct_port_nme:"Houston, Texas", sum_teu:14, sum_weight: 95995, count_shipments: 7}, 
{country:"Brazil", distrinct_port_nme:"Long Beach, California", sum_teu: 2, sum_weight: 18584, count_shipments: 1}, 
{country:"China", distrinct_port_nme:"Long Beach, California", sum_teu: 2, sum_weight: 19180, count_shipments: 1}, 
{country:"Colombia", distrinct_port_nme:"Long Beach, California", sum_teu:12, sum_weight:117873, count_shipments: 6}, 
{country:"Singapore", distrinct_port_nme:"Long Beach, California", sum_teu: 6, sum_weight: 77176, count_shipments: 4}, 
{country:"Belgium", distrinct_port_nme:"Los Angeles, California", sum_teu: 2, sum_weight: 17780, count_shipments: 1}, 
{country:"Brazil", distrinct_port_nme:"Los Angeles, California", sum_teu: 2, sum_weight: 18584, count_shipments: 1}, 
{country:"Colombia", distrinct_port_nme:"Los Angeles, California", sum_teu: 7, sum_weight: 52046, count_shipments: 5}, 
{country:"Hong Kong", distrinct_port_nme:"Los Angeles, California", sum_teu: 2, sum_weight: 19180, count_shipments: 1}, 
{country:"India", distrinct_port_nme:"Los Angeles, California", sum_teu:48, sum_weight:460563, count_shipments:24}, 
{country:"Singapore", distrinct_port_nme:"Los Angeles, California", sum_teu:12, sum_weight:115384, count_shipments: 6}, 
{country:"Brazil", distrinct_port_nme:"New York, New York", sum_teu: 4, sum_weight: 27032, count_shipments: 2}, 
{country:"Colombia", distrinct_port_nme:"New York, New York", sum_teu: 8, sum_weight: 42885, count_shipments: 4}, 
{country:"India", distrinct_port_nme:"New York, New York", sum_teu:14, sum_weight:129116, count_shipments: 7}, 
{country:"Singapore", distrinct_port_nme:"New York, New York", sum_teu:42, sum_weight:560628, count_shipments:27}, 
{country:"Brazil", distrinct_port_nme:"Newark, New Jersey", sum_teu: 2, sum_weight: 18584, count_shipments: 1}, 
{country:"Colombia", distrinct_port_nme:"Newark, New Jersey", sum_teu:83, sum_weight:785372, count_shipments:42}, 
{country:"India", distrinct_port_nme:"Newark, New Jersey", sum_teu:62, sum_weight:587654, count_shipments:31}, 
{country:"Brazil", distrinct_port_nme:"Norfolk, Virginia", sum_teu: 8, sum_weight: 33622, count_shipments: 4}, 
{country:"India", distrinct_port_nme:"Norfolk, Virginia", sum_teu: 2, sum_weight: 17780, count_shipments: 1}, 
{country:"Brazil", distrinct_port_nme:"Philadelphia, Pennsylvania", sum_teu: 2, sum_weight: 20160, count_shipments: 1} 
]; 
// margins 
var margin = {top: 20, right: 90, bottom: 30, left: 100, left_padding: 100}, 
width = 700 - margin.left - margin.right, 
height = 500 - margin.top - margin.bottom; 
// axes and color scale 
var x = d3.scale.ordinal() 
.rangeBands([0, width], .2), 
y = d3.scale.ordinal() 
.rangeBands([height,0], .2), 
z = d3.scale.linear().range(["lightgrey", "steelblue"]); 
var xStep = .5, 
yStep = 50; 
var svg = d3.select("body").append("svg") 
.attr("width", width + margin.left + margin.right) 
.attr("height", height + margin.top + margin.bottom) 
.append("g") 
.attr("transform", "translate(" + 0 + "," + margin.top + ")"); 
// Compute the scale domains. 
x.domain(buckets.map(function(d){return d.country})); 
y.domain(buckets.map(function(d){return d.distrinct_port_nme})); 
z.domain([0, d3.max(buckets.map(function(d){return d.count_shipments}))]); 
// Display the tiles for each bucket. 
svg.selectAll(".tile") 
.data(buckets) 
.enter().append("rect") 
.attr("class", "tile") 
.attr("x", function(d) { return x(d.country) + margin.left+margin.left_padding; }) 
.attr("y", function(d) { return y(d.distrinct_port_nme); }) 
.attr("width",x.rangeBand()) 
.attr("height",y.rangeBand()) 
.style("stroke","goldenrod") 
.style("fill", function(d) { return z(d.count_shipments); }) 
.on("mouseover", function() { d3.select(this).classed("active", true) })  // classed("active",boolean) not working 
.on("mouseout", function() { d3.select(this).classed("active", false) }); 
// .on("mouseover", function() { d3.select(this).style("fill", "aliceblue");}); // this change work fine 
// .on("mouseout", function(){d3.select(this).style("fill", "white");});   // this change work fine 
svg.selectAll("text") 
.data(buckets) 
.enter().append("text") 
.text("text") 
.attr("x", function(d) { return x(d.country) + margin.left + margin.left_padding + x.rangeBand()/2; }) 
.attr("y", function(d) { return y(d.distrinct_port_nme) + y.rangeBand()/2; }) 
.attr("dx",0) 
.attr("dy",".35em") 
.attr("text-anchor","middle") 
.style("fill","black").attr("font-size","14").attr("font-weight","Bold") 
.text(function(d) { return d.count_shipments; }); 
// Add a legend for the color values. 
var legend = svg.selectAll(".legend") 
.data(z.ticks(6).slice(1).reverse()) 
.enter().append("g") 
.attr("class", "legend") 
.attr("transform", function(d, i) { return "translate(" + 0 + "," + (10 + i * 20) + ")"; }); 
legend.append("rect") 
.attr("width", 20) 
.attr("height", 20) 
.style("fill", z); 
legend.append("text") 
.attr("x", 26) 
.attr("y", 10) 
.attr("dy", ".35em") 
.text(String); 
svg.append("text") 
.attr("class", "label") 
.attr("x", 0) 
.attr("y", 0) 
.attr("dy", ".35em") 
.text("count_shipments"); 
// Add an x-axis with label. 
svg.append("g") 
.attr("class", "x axis") 
.attr("transform", "translate("+ (margin.left+margin.left_padding) + "," + height + ")") 
.attr("text_anchor", "top") 
.call(d3.svg.axis().scale(x).orient("bottom")) 
.append("text") 
.attr("class", "label") 
.attr("x", width-10) 
.attr("y", -5) 
.attr("text-anchor", "end") 
.text("Country"); 
// Add a y-axis with label. 
svg.append("g") 
.attr("class", "y axis") 
.attr("transform", "translate("+ (margin.left+margin.left_padding) + "," + 0 + ")") 
.attr("text-anchor","right") 
.call(d3.svg.axis().scale(y).orient("left")) 
.append("text") 
.attr("class", "label") 
.attr("y", 3) 
.attr("dy", ".71em") 
.attr("text-anchor", "end") 
.attr("transform", "rotate(-90)") 
.text("distrinct_port_nme"); 
</script> 
</body> 
</html> 

Odpowiedz

13

EDIT

Po pierwsze, masz rację, że CSS jest nieco off.

.tile active { 
    fill: red; 
} 

powinno być:

.tile.active { 
    fill: red; 
} 

Następnie, coś jak to wyjaśniłem poniżej, wypełnienie starasz do elementu z

.style("fill", function(d) { return z(d.count_shipments); }) 

kończy się biorąc pierwszeństwo nad wypełnieniem zastosowane przez klasę active.

Jednak, w przeciwieństwie do tego, co początkowo sugerowano, można go obejść, po prostu zamiana style z attr, więc trzeba:

.attr("fill", function(d) { return z(d.count_shipments); }) 

(prawdopodobnie powinien to zrobić dla udaru mózgu, jak również).

Oto updated, working jsFiddle


ORIGINAL POST

Podejrzewam, że działa tak jak powinno - czyli klasa "aktywny" związanej z jego wypełnieniem jest dodany/usunięty odpowiednio - i można to sprawdzić, klikając prawym przyciskiem myszy i sprawdzając element w narzędziach programistycznych.

Myślę, że prawdziwym problemem jest to, że ustawiasz wypełnienie bezpośrednio na elemencie (jedna linia przed rozmową .on("mouseover"...)), która ZAWSZE zastępuje wypełnienie zastosowane przez twoją klasę. Ogólnie w CSS możesz (nie mówiąc, że powinieneś) użyć słowa kluczowego !important, aby wymusić akceptację wypełnienia zastosowanego przez klasę. Ale jestem pewien, że nie będzie działać z SVG (w przeciwieństwie do normalnych elementów HTML).

Tak, myślę, że jedyną opcją jest:

.style("fill", function(d) { return z(d.count_shipments); }) 
.on("mouseover", function() { 
    d3.select(this) 
    .attr('fill', '') // Un-sets the "explicit" fill (might need to be null instead of '') 
    .classed("active", true) // should then accept fill from CSS 
}) 
.on("mouseout", function() { 
    d3.select(this) 
    .classed("active", false) 
    .attr('fill', function(d) { return z(d.count_shipments); }) // Re-sets the "explicit" fill 
    }); 

Nadzieja to działa ....

+0

Dzięki za pomoc. To nie zadziałało ani po mojej stronie. Zastanawiam się, czy istnieje błąd początkującego w mojej regule CSS lub jak się do niej odwołuję. – glynnsc

+0

napraw to skrzypce http://jsfiddle.net/glynnsc/WEsUe/ – glynnsc

+0

@glynnsc Gotowy! Zobacz moje zmiany. – meetamit

Powiązane problemy