JavaScript-D3入門五-資料和字串陣列對映到顏色模型
阿新 • • 發佈:2018-11-19
基於《JavaScript-D3入門四-事件繫結》中的程式碼。
這裡只要soccerviz2.js代替上一篇的soccerviz.js,就可以在Web Server上執行html,一邊修改程式碼一邊觀察執行效果。
下面是soccerviz2.js原始碼
//soccerviz2.js //演示顏色對映的幾種方式 function createSoccerViz() { d3.csv("/data/worldcup.csv", data => {overallTeamViz(data)}) function overallTeamViz(incomingData) { //根據incomingData的行數新增g.overallG d3.select("svg") .append("g") .attr("id", "teamsG") .attr("transform", "translate(50,300)") .selectAll("g") .data(incomingData) .enter() .append("g")//設incomingData中資料的行數為n,新增n個g物件。 .attr("class", "overallG") .attr("transform", (d, i) =>"translate(" + (i * 50) + ", 0)");//為n個物件設定各自的(x,y)屬性 //返回class屬性為overallG的所有g節點,即teamG是一個含g節點的陣列。 var teamG = d3.selectAll("g.overallG"); //每個g.overallG物件下新建circle,帶動畫效果 teamG .append("circle") .attr("r", 0) .transition().delay((d, i) => i * 100).duration(500)//多個circle依次變大 .attr("r", 40) .transition().duration(500) .attr("r", 20); //g.overallG下新建text teamG .append("text") .attr("y", 30) .text(d => d.team); //改變現有DOM元素在父節點中的先後位置, //感覺在這裡呼叫沒有什麼意義,所以把下面兩行註釋掉了 //d3.select("g.overallG").raise();//往後移動 //d3.select("g.overallG").lower();//往前移動 //使text節點不處理滑鼠事件。據說這樣的設定可以讓滑鼠事件穿透當前節點(即當前節點就像不存在一樣)。 teamG.select("text").style("pointer-events", "none"); //incomingData第一行資料除了team,region其它column都作為key //dataKeys=["win","loss","draw","points","gf","ga","cs","yc","rc"] const dataKeys = Object.keys(incomingData[0]) .filter(d => d !== "team" && d !== "region"); //在body下新增<div id='controls'>節點,在這個節點下再新增button節點 //Hint: 由於button.teams是不存在的,所以會新增button節點. d3.select("#controls").selectAll("button.teams") .data(dataKeys).enter() .append("button") .on("click", buttonClick)//事件繫結 .html(d => d); //點選某個button物件更新檢視 /* function buttonClick(datapoint) { //datapoint的值為["win","loss","draw","points","gf","ga","cs","yc","rc"]陣列中的元素! var maxValue = d3.max(incomingData, d => parseFloat(d[datapoint])) //color map //採用RGB顏色模型過度,中間色是灰色的,不符合我們的需求 //var ybRamp = d3.scaleLinear() // .domain([0, maxValue]).range(["blue", "yellow"]); //中間色用HSL(hue,saturation,lightness)顏色模型過度 var ybRamp = d3.scaleLinear() .interpolate(d3.interpolateHsl)//.interpolate(d3.interpolateLab)//D3也支援Lab色彩模型 .domain([0, maxValue]).range(["yellow", "blue"]); //linear map var radiusScale = d3.scaleLinear() .domain([0, maxValue]).range([2, 20]) //更新circle物件的屬性,帶動畫效果 d3.selectAll("g.overallG").select("circle") .transition().duration(1000)//這行添加了動畫效果 .attr("r", d => { if (radiusScale(d[datapoint]) > 0) return radiusScale(d[datapoint]); else return 0;//r屬性不接受negative number. }).style("fill", d => ybRamp(d[datapoint])); }//buttonClick */ /* function buttonClick(datapoint) { var maxValue = d3.max(incomingData, function (el) { return parseFloat(el[datapoint]) }) //字串陣列到顏色模型的對映. var tenColorScale = d3.scaleOrdinal() .domain(["UEFA", "CONMEBOL", "CAF", "AFC"]) .range(d3.schemeCategory10); //沒在domain裡的字串,顏色對映為unknown裡指定的顏色. //var tenColorScale = d3.scaleOrdinal() // .domain(["UEFA", "CONMEBOL"]) // .range(d3.schemeCategory10) // .unknown("#c4b9ac"); //radius對映 var radiusScale = d3.scaleLinear().domain([0, maxValue]).range([2, 20]); d3.selectAll("g.overallG").select("circle").transition().duration(1000) .style("fill", p => tenColorScale(p.region)) .attr("r", p => radiusScale(p[datapoint])) } */ function buttonClick(datapoint) { var maxValue = d3.max(incomingData, d => parseFloat(d[datapoint])); //colorbrewer.Reds[3]為包含多個顏色的一個數組。 var colorQuantize = d3.scaleQuantize() .domain([0, maxValue]).range(colorbrewer.Reds[3]); var radiusScale = d3.scaleLinear() .domain([0, maxValue]).range([2, 20]); d3.selectAll("g.overallG").select("circle").transition().duration(1000) .style("fill", d => colorQuantize(d[datapoint])) .attr("r", d => radiusScale(d[datapoint])) } //highlight同一個region的物件。 teamG.on("mouseover", highlightRegion) function highlightRegion(d) { //這裡的this為teamG陣列中的某一個物件。 d3.select(this).select("text").classed("active", true).attr("y", 10); //修改circle的class屬性。 /* 通過修改circle的class屬性來改變circle屬性 d3.selectAll("g.overallG").select("circle").each(function (p) { p.region == d.region ? d3.select(this).classed("active", true) : d3.select(this).classed("inactive", true); }); */ //通過修改circle的fill風格來改變circle的顏色 var teamColor = d3.rgb("#75739F"); d3.selectAll("g.overallG").select("circle").style("fill", p => p.region === d.region ? teamColor.darker(.75) : teamColor.brighter(.5)); //把this節點,移到parent節點的最後,否則會被同級g節點遮住。 this.parentElement.appendChild(this); }//highlightRegion // teamG.on("mouseout", unHighlight) function unHighlight() { d3.selectAll("g.overallG").select("circle").attr("class", "");//修改class屬性的另一種方式 d3.selectAll("g.overallG").select("text") .classed("active", false).attr("y", 30); }//unHighlight }//overallTeamViz }//createSoccerViz