1. 程式人生 > >d3.js——給柱形圖添加事件出現的問題總結

d3.js——給柱形圖添加事件出現的問題總結

htm 代碼 lac ring tle log 顏色 out edge

首先做出一個動態的柱形圖(這兒用的d3.js的版本是v3,用v4的話有些函數會發生變化)

效果圖:

技術分享

代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>histogramTransitionEvent</title>
    <style>
        .axis path,
        .axis line{
            fill: none;
            stroke: black;
            shape
-rendering: crispEdges; } .axis text { font-family: sans-serif; font-size: 11px; } .MyText { fill: white; text-anchor: middle; } </style> </head> <body> <script src="d3.js"></script> <script> //
添加svg畫布 var width=400; var height=400; //在 body 裏添加一個 SVG 畫布 var svg = d3.select("body") .append("svg") .attr("width",width) .attr("height",height); //畫布周邊的空白 var padding={ left:30, right:30, top:20, bottom:20 }; //定義一個數組 var
dataset=[10,20,30,40,33,24,12,5]; //x軸的比例尺 var xScale=d3.scale.ordinal() // 使用了d3.scale.ordinal() 它支持範圍分檔。與定量比例尺(如d3.scale.linear())返回連續的範圍值不同,序數比例尺使用的是離散範圍值,也就是輸出值是事先就確定好的。 // 映射範圍時,可以使用range(),也可以使用rangeBands()。後者接收一個最小值和一個最大值,然後根據輸入值域的長度自動將其切分成相等的塊或“檔”。0.2也就是檔間距為每一檔寬度的20%。 .domain(d3.range(dataset.length)) .rangeRoundBands([0,width-padding.left-padding.right]); //y軸的比例尺 var yScale = d3.scale.linear() .domain([0,d3.max(dataset)]) .range([height-padding.top-padding.bottom,0]); //定義坐標軸 //定義x軸 var xAxis = d3.svg.axis() .scale(xScale) .orient("bottom"); //定義y軸 var yAxis = d3.svg.axis() .scale(yScale) .orient("left"); //添加矩形和文字元素 var rectPadding = 4; var rects = svg.selectAll(".MyRect") .data(dataset) .enter() .append("rect") .attr("class","MyRect") .attr("transform","translate("+padding.left+","+padding.top+")") .attr("x",function(d,i){ return xScale(i)+rectPadding/2; }) .attr("width",xScale.rangeBand()-rectPadding) .attr("y",function(d){ var min = yScale.domain()[0]; return yScale(min); }) .attr("height", function(d){ return 0; }) .transition() .delay(function(d,i){ return i * 200; }) .duration(2000) .ease("bounce") .attr("y",function(d){ return yScale(d); }) .attr("height",function(d){ return height-padding.top-padding.bottom-yScale(d); })//console.log(width-padding.left-padding.right); //添加文字元素 var texts = svg.selectAll(".MyText") .data(dataset) .enter() .append("text") .attr("class","MyText") .attr("transform","translate("+padding.left+","+padding.top+")") .attr("x",function(d,i){ return xScale(i)+rectPadding/2; }) .attr("y",function(d){ var min = yScale.domain()[0]; // console.log(yScale(min)); return yScale(min); }) .transition() .delay(function(d,i){ return i*200; }) .duration(2000) .ease("bounce") .attr("y",function(d){ return yScale(d); }) .attr("dx",function(){ return (xScale.rangeBand()-rectPadding)/2; }) .attr("dy",function(){ return 20; }) .text(function(d){ return d; }); //添加坐標軸元素 //添加x軸 svg.append("g") .attr("class","axis") .attr("transform","translate("+padding.left+","+(height-padding.bottom)+")") .call(xAxis); //添加y軸 svg.append("g") .attr("class","axis") .attr("transform","translate("+padding.left+","+padding.top+")") .call(yAxis); </script> </body> </html>

現在像個這個動態的柱形圖添加mouseover和mouseout事件。

做法:

1.去掉style樣式中的.MyText類,直接在添加矩形的時候添加顏色屬性

2.在添加矩形的時候添加事件

...

//添加矩形和文字元素
    var rectPadding = 4;
    var rects = svg.selectAll(".MyRect")
        .data(dataset)
        .enter()
        .append("rect")
        .attr("class","MyRect")
        .attr("transform","translate("+padding.left+","+padding.top+")")
        .attr("x",function(d,i){
            return xScale(i)+rectPadding/2;
        })
        .attr("width",xScale.rangeBand()-rectPadding)
        
        .attr("y",function(d){
            var min = yScale.domain()[0];
            return yScale(min);
        })
        .attr("height", function(d){
            return 0;
        })
        .transition()
        .delay(function(d,i){
            return i * 200;
        })
        .duration(2000)
        .ease("bounce")
        .attr("y",function(d){
            return yScale(d);
        })
        .attr("height",function(d){
            return height-padding.top-padding.bottom-yScale(d);
        })
        .attr("fill","steelblue")
        //添加事件
        .on("mouseover",function(d,i){
            d3.select(this)
                .attr("fill","yellow");
        })
        .on("mouseout",function(d,i){
            d3.select(this)
                .transition()
                .duration(500)
                .attr("fill","steelblue");
        });

...

但是這樣會報錯,會顯示on不是一個函數

後來知道應該把on事件放在transition()之前,但是為啥這麽做可以現在還不知道

 ...

//添加矩形和文字元素
    var rectPadding = 4;
    var rects = svg.selectAll(".MyRect")
        .data(dataset)
        .enter()
        .append("rect")
        .attr("class","MyRect")
        .attr("transform","translate("+padding.left+","+padding.top+")")
        .attr("x",function(d,i){
            return xScale(i)+rectPadding/2;
        })
        .attr("width",xScale.rangeBand()-rectPadding)
        //添加事件在 transition()之前
        .on("mouseover",function(d,i){
            d3.select(this)
                .attr("fill","yellow");
        })
        .on("mouseout",function(d,i){
            d3.select(this)
                .transition()
                .duration(500)
                .attr("fill","steelblue");
        })
        .attr("y",function(d){
            var min = yScale.domain()[0];
            return yScale(min);
        })
        .attr("height", function(d){
            return 0;
        })
        .transition()
        .delay(function(d,i){
            return i * 200;
        })
        .duration(2000)
        .ease("bounce")
        .attr("y",function(d){
            return yScale(d);
        })
        .attr("height",function(d){
            return height-padding.top-padding.bottom-yScale(d);
        })
        .attr("fill","steelblue");

...

最終效果圖:

技術分享

這裏面矩形圖的教程來源:http://d3.decembercafe.org/pages/lessons/9.html

d3.js——給柱形圖添加事件出現的問題總結