我一直在努力工作,這是一個特殊的圖形,它是Mike Bostock模板中的一個修改過的子彈圖。我想用一些按鈕事件來增強它,特別是:當你點擊一個按鈕時,它會調用一個過渡動畫來改變圖形標記爲新的值。原始數據表單中的代碼都提供了新值和舊值。爲了清晰和上下文,我已經將代碼包括在內。搜索我的評論「//混淆下面」來到我定義我的按鈕功能的部分。D3.js + CSS按鈕功能
<!DOCTYPE html>
<html>
<head>
<title>Bullet Chart</title>
<meta charset="utf-8">
</head>
<style>
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: auto;
padding-top: 40px;
position: relative;
/*width: 100%;*/
}
table{
width:60%;
margin-left:auto;
margin-right:auto;
}
td{width:50%;}
.bulleT { font: 10px sans-serif; margin-left:auto;margin-right:auto;}
.bulleT .marker { stroke: #4D4D4D; stroke-width: 2px;}
.bulleT .marker.s0 { fill-opacity:0; stroke: #999999; stroke-width: 2px; }
.bulleT .marker.s1 { fill-opacity:0; stroke: #000; stroke-width: 2px; }
.bulleT .tick line { stroke: #666; stroke-width: .5px; }
.bulleT .range.s0 { fill: #005C7A; }
.bulleT .range.s1 { fill: #29A3CC; }
.bulleT .range.s2 { fill: #c6dbef; }
.bulleT .range.s3 { fill: #29A3CC; }
.bulleT .range.s4 { fill: #005C7A; }
.bulleT .measure.s0 { fill: #4D4D4D; }
.bulleT .measure.s1 { fill: #999999; }
.bulleT .measure.s2 { fill: #eeeeee; }
.bulleT .measure.s3 { fill: #999999; }
.bulleT .measure.s4 { fill: #4D4D4D; }
.bulleT .title { font-size: 12px; font-weight: bold; }
.bulleT .subtitle.s04 { fill: #000000; font-size: 16px; font-weight: bold;}
.bulleT .subtitle.s13 { fill: #999999; font-size: 12px; font-weight: bold;}
.bulleT .subtitle.s2 { fill: #999999; font-size: 10px;}
.option {
\t font-family: Play;
\t color: #ffffff;
\t font-size: 12px;
width: 6%;
\t background: #303030;
\t padding: 10px 20px 10px 20px;
}
.option:hover {
\t background: #4c4d4d;
}
div#option2{
position:relative;
top: 10px;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<div id="canvas-svg">
<div id="canvas-svg">
<table>
<tr>
<td>
<div id="BulleT_horizontal"></div>
</td>
</tr>
</table>
</div>
<div id="option1" class="option"> Outcome 1</div>
<div id="option2" class="option"> Outcome 2</div>
<p>The Bullet Chart is here.</p>
<script>
(function() {
// Simple modification based on mbostock's Bullet Charts.
d3.bulleT = function() {
var orient = "left",
reverse = false,
vertical = false,
terjedelem = bulleTTerjedelem,
ranges = bulleTRanges,
markers = bulleTMarkers,
measures = bulleTMeasures,
width = 380,
height = 30,
tickFormat = null;
// For each small multiple
function bulleT(g) {
g.each(function(d, i) {
var terjedelemz = terjedelem.call(this, d, i),
rangez = ranges.call(this, d, i).slice().sort(d3.descending),
markerz = markers.call(this, d, i),
measurez = measures.call(this, d, i).slice().sort(d3.descending),
g = d3.select(this);
var wrap = g.select("g.wrap");
if (wrap.empty()) wrap = g.append("g").attr("class", "wrap");
// Compute the x-scale.
var x0 = d3.scale.linear()
.domain([terjedelemz[0], terjedelemz[1]])
.range(reverse ? [width, 0] : [0, width]);
// Stash the new scale.
this.__chart__ = x0;
// Derive width-scales from the x-scales.
var w = bulleTWidth(x0,terjedelemz[0]);
// Update the range rects.
rangez.unshift(terjedelemz[1]);
var range = wrap.selectAll("rect.range")
.data(rangez);
range.enter().append("rect")
.filter(function(d, i){ if(i != 3){ return d} })
.attr("class", function(d, i) { return "range s" + i; })
.attr("width", w)
.attr("y", 0)
.attr("height",height)
.attr("x", reverse ? x0 : 0);
range.enter().append("line")
.filter(function(d, i){ if(i == 3){ return d} })
.attr("class", "marker")
.attr("x1", x0)
.attr("x2", x0)
.attr("y1", 0)
.attr("y2", height);
// Append the measure rects.
measurez.unshift(terjedelemz[1]);
var measure = wrap.selectAll("rect.measure")
.data(measurez);
measure.enter().append("rect")
.attr("class", function(d, i) { return "measure s" + i; })
.attr("width", w)
.attr("height", height/2)
.attr("x", reverse ? x0 : 0)
.attr("y", height/4);
// Append rect and line marker.
var marker = wrap.selectAll("rect.marker")
.data(markerz);
marker.enter().append("rect")
.filter(function(d, i){ if(i == 1){ return d} })
.attr("class", "marker s1")
.attr("width", 6)
.attr("y", -(height/10))
.attr("height",function(d) {return height+(height/5);})
.attr("x", x0)
.attr("transform", "translate(-3,0)");
//confusion below
var option1 = d3.select("#option1");
option1.on('click.outcome', outcome1);
//option1.on('click.val', val=[100,200,1000,20]);
var option2 = d3.select("#option2");
option2.on('click.outcome', outcome2);
function outcome1(val) {
d.markerz = [1000, 2000, 10, 20]
d3.selectAll('rect.marker')
.transition()
.duration(3000)
.attr("x", function(d) {return d})
}
function outcome2(val) {
d.markerz = [-1000, -2000, -10, -20]
d3.selectAll('rect.marker')
.transition()
.duration(3000)
.attr("x", function(d) {return d})
};
marker.enter().append("line")
.filter(function(d, i){ if(i == 0){ return d} })
.attr("class", "marker s0")
.attr("x1", x0)
.attr("x2", x0)
.attr("y1", height/4)
.attr("y2", height-(height/4));
// Compute the tick format.
var format = tickFormat || x0.tickFormat(8);
// Update the tick groups.
var tick = g.selectAll("tick")
.data(x0.ticks(8), function(d) {
return this.textContent || format(d);
});
// Initialize the ticks with the old scale, x0.
var tickEnter = tick.enter().append("g")
.attr("class", "tick")
.attr("transform", bulleTTranslate(x0))
.style("opacity", 1);
tickEnter.append("line")
.attr("y1", height)
.attr("y2", height * 7/6);
tickEnter.append("text")
.attr("text-anchor", "middle")
.attr("transform", function(d){
if (vertical) {
return "rotate(90)";
}
})
.attr("dy", function(d){
if(vertical){return width/60; }else{ return height+15 }
})
.attr("dx", function(d){
if(vertical){return height+15 ;}
})
.text(format);
});
}
// left, right, top, bottom
bulleT.orient = function(x) {
if (!arguments.length) return orient;
orient = x;
reverse = orient == "right" || orient == "bottom";
return bulleT;
};
// terjedelem
bulleT.terjedelem = function(x) {
if (!arguments.length) return terjedelem;
terjedelem = x;
return bulleT;
};
// ranges (bad, satisfactory, good)
bulleT.ranges = function(x) {
if (!arguments.length) return ranges;
ranges = x;
return bulleT;
};
//*
// markers (previous, goal)
bulleT.markers = function(x) {
if (!arguments.length) return markers;
markers = x;
return bulleT;
};
// measures (actual, forecast)
bulleT.measures = function(x) {
if (!arguments.length) return measures;
measures = x;
return bulleT;
};
//*/
bulleT.vertical = function(x) {
if (!arguments.length) return vertical;
vertical = x;
return bulleT;
};
bulleT.width = function(x) {
if (!arguments.length) return width;
width = x;
return bulleT;
};
bulleT.height = function(x) {
if (!arguments.length) return height;
height = x;
return bulleT;
};
bulleT.tickFormat = function(x) {
if (!arguments.length) return tickFormat;
tickFormat = x;
return bulleT;
};
return bulleT;
};
function bulleTTerjedelem(d) {
return d.terjedelem;
}
function bulleTRanges(d) {
return d.ranges;
}
function bulleTMarkers(d) {
return d.markers;
}
function bulleTMeasures(d) {
return d.measures;
}
function bulleTTranslate(x) {
return function(d) {
return "translate(" + x(d) + ",0)";
};
}
function bulleTWidth(x,y) {
var x0 = x(0);
return function(d) {
return Math.abs(x(d-y) - x0);
};
}
})();
var Tscore_Man_Height = -1019;
var Tscore_Woman_Height = -261;
var Tscore_Man_Weight = -4.64;
var Tscore_Woman_Weight = -1.6;
var Tscore2 = 1300
// terjedelem is the hungarian translation of the statistical term of range
var data = [
{"title":"Exper","dimension":"(diff)","subtitle":Tscore_Man_Height,"terjedelem":[-3000,3000],"ranges":[ -2000, -1000, 0, 1000, 2000],"measures":[-1366,-676,605,1108.81],"markers":[-23,Tscore_Man_Height]},
{"title":"Gold","dimension":"(diff)","subtitle":Tscore_Woman_Height,"terjedelem":[-8000,8000],"ranges":[-5250,-2750,0,2750,5250],"measures":[-901,110,845.5,2107.5],"markers":[412,Tscore_Woman_Height]},
{"title":"Tech","dimension":"(diff)","subtitle":Tscore_Man_Weight,"terjedelem":[-20,20],"ranges":[-13.33,-6.66,0,6.66,13.33],"measures":[-8.7,-.9,4.9,10.7],"markers":[1,Tscore_Man_Weight]},
{"title":"Units","dimension":"(diff)","subtitle":Tscore_Woman_Weight,"terjedelem":[-80,80],"ranges":[-53.33,-26.66,0,26.66,53.33],"measures":[-18,-7.8,3.8,23],"markers":[-3,Tscore_Woman_Weight]}
]
var Width = 400, Height = 50;
var margin = {top: 5, right: 20, bottom: 20, left: 60},
width = Width - margin.left - margin.right,
height = Height - margin.top - margin.bottom;
var chart = d3.bulleT()
.width(width)
.height(height);
function bulleT(whichData,whereToPut,direction) {
var a=Width, b=Height;
if(direction == "vertical"){
Height=a;Width=b+30;
vertical = true;
}else{
Height=a-20;Width=b;
vertical = false;
}
var svg = d3.select(whereToPut).selectAll("svg")
.data(whichData)
.enter().append("svg")
.attr("class", "bulleT")
.attr("width", Width)
.attr("height", Height)
.append("g")
.attr("transform", function(){
if(direction == "vertical"){
return "rotate(-90)translate("+ -(Height-margin.left) +",10)";
}else{
return "translate("+ margin.left +","+ margin.top +")";
}
})
.call(chart.vertical(vertical));
var title = svg.append("g")
.style("text-anchor", function(){
if(direction == "vertical"){
return "middle";
}else{
return "end";
}
})
.attr("transform", function(){
if(direction == "vertical"){
return "rotate(90)translate("+ Width/4 +",20)";
}else{
return "translate(-16," + height/3 + ")";
}
});
title.append("text")
.attr("class", "title")
.text(function(d) { return d.title; });
title.append("text")
.attr("dy", "1.2em")
.text(function(d) { return d.dimension; })
title.append("text")
.attr("class",function(d) {
switch (true)
{
case ((d.markers[1] < 30) || (70 < d.markers[1])):
return "subtitle s04";
break;
break;
case ((30 <= d.markers[1]) && (d.markers[1] < 40)):
return "subtitle s13";
break;
case ((40 <= d.markers[1]) && (d.markers[1] <= 60)):
return "subtitle s2";
break;
case ((60 < d.markers[1]) && (d.markers[1] <= 70)):
return "subtitle s13";
break;
}
}
)
.attr("dy", function(){
return "2.4em";
})
.text(function(d) { return d.subtitle; });
};
bulleT(data,"#BulleT_vertical","vertical"); // "horizontal" or "vertical"
bulleT(data,"#BulleT_horizontal","horizontal");
</script>
</body>
</html>
當我點擊按鈕,他們都做同樣的事情,即使我改變markerz不同的值。而且,他們甚至沒有做正確的事情,這些價值觀似乎是錯誤的,因爲一些標記從圖形邊界飛出。所以無論我做什麼似乎都不會改變數據解析的方式。另外,我並不完全相信這個原始數值數據會隨着圖的x比例縮放,或者當我通過按鈕功能時需要再次縮放它。縮放似乎與上面代碼中的x0有關。出於某種原因,我無法使用我的按鈕。
這裏有一個類似的更新塊具有功能按鈕的功能:
http://bl.ocks.org/CodeXmonk/6187523
我的圖是在不同的我不會改變比在該標記定位等措施或任何東西。而且我沒有隨機化數據,我已經預先編碼了原始數據,我想使用我的css按鈕來回切換。
所以我在尋找的是如何編碼按鈕來處理預先存在的比例尺並加載原始數據並將其放入markerz或.transition()動畫的其他變量中。這樣,這些按鈕就可以在整個圖形上移動標記。
對不起,我不能讓這個縮短。我希望這將是值得每個人的,雖然因爲d3.js + css界面是一個非常強大的組合。我希望我們都可以從這個例子中學習。
感謝您閱讀