2017-04-04 9 views
2

スクロール可能なリストを作成しようとしています。私はここで他のチュートリアルを見てきましたが、動作していないようです。基本的に私はdivにSVGを追加しています。このSVGの内部には、D3JS積み重ね棒グラフがあります。この棒グラフの右側には、内部にsvgを持つ 'g'要素が追加されています。私はこの右のSVGの高さを設定しました。この中で私はSVGの高さを越えて広がるリストを作成しました。私はこのsvgのCSSを 'overflow-y:scroll'に設定しました。スクロール可能なSVGを動的に作成

これにもかかわらず、私はこのsvgをスクロールすることはできません。代わりに、それはリストのサイズに成長し、意図した範囲にまで拡張されます。以下のコードをご覧ください。

var barSVG = d3.select("#documents_reviewed_bar_chart").append("svg") 
    .classed('barChart-docs-reviewed', true) 
    .attr('id', 'barSVG') 
    .attr("width", width + margin.left + margin.right) 
    .attr("height", height + margin.top + margin.bottom) 
    .append("g") 
    .attr('id', 'gElement') 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");  

var count = 0; 

var graph = barSVG.append('g') 
    .attr('id', 'graphElement') 

color.domain(d3.keys(data[0]).filter(function(key) { return key !== "Date"; })); 


data.forEach(function(d) { 
    var myDate = d.Date; //add to stock code 
    var y0 = 0; 

    d.people = color.domain().map(function(name) { return {myDate:myDate, name: name, y0: y0, y1: y0 += +d[name]}; }); 
    d.total = d.people[d.people.length - 1].y1; 
    count = isNaN(d.total) ? count : count + d.total 

}); 


x.domain(data.map(function(d) { return d.Date; })); 
y.domain([0, d3.max(data, function(d) { return d.total; })]); 

graph.append("g") 
    .attr("class", "x axis") 
    .attr("transform", "translate(0," + height + ")") 
    .call(xAxis) 
    .selectAll("text") 
     .style("text-anchor", "end") 
     .attr("dx", "-.8em") 
     .attr("dy", ".15em") 
     .attr("transform", "rotate(-65)") 
     .style("cursor", "pointer") 
     .on('click', renderHorizontalChart); 

graph.append("g") 
    .attr("class", "y axis") 
    .call(yAxis) 
    .append("text") 
    .attr("transform", "rotate(-90)") 
    .attr("y", 6) 
    .attr("dy", ".71em") 
    .style("text-anchor", "end"); 
    //.text("Population"); 

graph.append('text') 
    .text('Total: ' + count) 
    .attr('x', 20) 
    .attr('y', -10) 


var state = graph.selectAll(".state") 
    .data(data) 
    .enter().append("g") 
    .attr("class", "g") 
    .attr("transform", function(d) { return "translate(" + "0" + ",0)"; }); 
    //.attr("transform", function(d) { return "translate(" + x(d.Date) + ",0)"; }) 

state.selectAll("rect") 
    .data(function(d) { 
     return d.people; 
    }) 
    .enter().append("rect") 
    .attr("width", x.rangeBand()) 
    .attr("y", height) 
    .attr("x",function(d) { //add to stock code 
     return x(d.myDate) 
     }) 
    .attr("height", 0) 
    .style("fill", function(d) { return color(d.name); }) 
    .transition() 
    .duration(1000) 
    .attr("y", function(d) { return y(d.y1); }) 
    .attr("height", function(d) { return y(d.y0) - y(d.y1); }) 
    .attr("class", function(d) { 
     classLabel = d.name.replace(/,\s/g, ''); //remove spaces 
     return "class" + classLabel; 
    }); 


state.selectAll("rect") 
    .on("mouseover", function(d){ 

     var delta = d.y1 - d.y0; 
     var xPos = parseFloat(d3.select(this).attr("x")); 
     var yPos = parseFloat(d3.select(this).attr("y")); 
     var height = parseFloat(d3.select(this).attr("height")) 

     d3.select(this).attr("stroke","black").attr("stroke-width",2); 

     tooltip.style("visibility", "visible"); 
     tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px"); 
     tooltip.style('background', 'black') 
     tooltip.style('color', 'white') 
     tooltip.style('border-radius', '3px') 
     tooltip.style('padding', '5px') 
     tooltip.style('opacity', '0.8') 
     tooltip.style('font-size', '10px;') 


     tooltip.text(d.name +": "+ delta) 

    }) 
    .on("mouseout",function(){ 

     tooltip.style("visibility", "hidden"); 
     graph.select(".tooltip").remove(); 
     d3.select(this).attr("stroke","pink").attr("stroke-width",0.2); 

     }) 


var itemsAmount = 0 
var rightSVG = barSVG.append('svg').classed('rightSVG', true) 
    .attr('height', '390') 
    .attr('id', 'rightSVG') 



var legendSVG = rightSVG.append('svg').classed('legendSVG', true) 
    .attr('id', 'legendSVG') 


var legend = legendSVG.selectAll(".legend") 
    .data(color.domain().slice().reverse()) 
    .enter().append("g") 
    //.attr("class", "legend") 
    .attr("class", function (d) { 
     itemsAmount = itemsAmount + 1 
     legendClassArray.push(d.replace(/,\s/g, '')); //remove spaces 
     return "legend"; 
    }) 
    .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; }); 

//reverse order to match order in which bars are stacked  
legendClassArray = legendClassArray.reverse(); 

legend.append("rect") 
    .attr("x", width - 0) 
    .attr("width", 18) 
    .attr("height", 18) 
    .style("fill", color) 
    .attr("id", function (d, i) { 
     return "id#" + d.replace(/,\s/g, ''); 
    }) 
    .on("mouseover",function(){  


     if (active_link === "0") d3.select(this).style("cursor", "pointer"); 
     else { 
     if (active_link.split("class").pop() === this.id.split("id#").pop()) { 
      d3.select(this).style("cursor", "pointer"); 
     } else d3.select(this).style("cursor", "auto"); 
     } 
    }) 
    .on("click",function(d){  
     if (!this.id.includes('active')) { //nothing selected, turn on this selection 

     d3.select(this) 
      .attr('id', function(){ 
       return this.id + 'active' 
      }) 
      .style("stroke", "black") 
      .style("stroke-width", 2); 


      active_link = this.id.split("id#").pop(); 
      plotSingle(this); 

     } else { //deactivate 

      d3.select(this)   
      .classed("active", false) 
      .attr('id', function() { 
       return this.id.replace('active', '') 
      }) 
      .style("stroke", "none") 
      .style("stroke-width", 0); 

      plotSingle(this); 

     } 

    }); 

legend.append("text") 
    .attr("x", width - 6) 
    .attr("y", 9) 
    .attr("dy", ".35em") 
    .style("text-anchor", "end") 
    .text(function(d) { return d; }); 

legendSVG.append("text") 
    .classed('queryButton', true) 
    .attr("x", width - 6) 
    .attr("y", height) 
    .attr("dy", ".35em") 
    .style("text-anchor", "end") 
    .text('Run Query') 
    .on('click', function(){ 
     if (newArr.length > 0) { 
      d3.select('#barSVG').remove(); 
      runScript(newArr) 
     } 
    }); 

legendSVG.append("text") 
.classed('queryButton', true) 
.attr("x", width - 6) 
.attr("y", height + 18) 
.attr("dy", ".35em") 
.style("text-anchor", "end") 
.text('Reset') 

私がスクロール可能にする特定のSVGは「rightSVG」です。

イメージでわかるように、名前は切り捨てられています。私は29のデータ項目を見ることができるスクロール可能な伝説があるべきです。 Sample Stacked Bar chart

また、私はCSSの下に追加しました:

#documents_reviewed_bar_chart, #gElement{ 
max-height: 390; 
overflow-y: scroll; 
} 
+0

[ズーム動作](https://github.com/d3/d3-zoom/blob/master/README.md)の使用を検討しましたか?私はあなたが最小/最大スケールを1に設定すると、スクロールに非常に近いものになると思います。 – transistor09

答えて

2

短い答え:あなたは別のSVG内部のスクロールSVGを持つことはできません。 overflow-y: scrollは、HTML要素に適用され、SVG要素には適用されません。

代替(とハック)答えは:技術的には、何をしたい可能ですが、あなたはforeignObject内でなければならHTML要素にあなたの内側のSVGをラップする必要があります。

この代替方法は最適ではなく、意味がなくIEでは機能しません。しかし、単に好奇心のために、これはあなたがそれを行うことができる方法である。

var outerSvg = d3.select("body") 
 
    .append("svg") 
 
    .attr("width", 500) 
 
    .attr("height", 200) 
 
    .style("background-color", "darkkhaki"); 
 
    
 
var foreign = outerSvg.append("foreignObject") 
 
    .attr("x", 300) 
 
    .attr("y", 10) 
 
    .attr("width", 150) 
 
    .attr("height", 180) 
 
    .append("xhtml:div") 
 
    .style("max-height", "180px") 
 
    .style("overflow-y", "scroll"); 
 
    
 
var innerSvg = foreign.append("svg") 
 
    .attr("width", 133) 
 
    .attr("height", 1000) 
 
    .style("background-color", "powderblue"); 
 
    
 
var color = d3.scaleOrdinal(d3.schemeCategory20); 
 
    
 
var texts = innerSvg.selectAll("foo") 
 
    .data(d3.range(65)) 
 
    .enter() 
 
    .append("text") 
 
    .attr("x", 40) 
 
    .attr("y", (d,i)=> 20 + 15*i) 
 
    .text("foo bar baz") 
 
    
 
var rects = innerSvg.selectAll("foo") 
 
    .data(d3.range(65)) 
 
    .enter() 
 
    .append("rect") 
 
    .attr("x", 10) 
 
    .attr("y", (d,i)=> 8 + 15*i) 
 
    .attr("width", 20) 
 
    .attr("height", 13) 
 
    .attr("fill", (d,i)=>color(i));
<script src="https://d3js.org/d3.v4.min.js"></script>

外SVGは淡褐色(またはカーキ)です。右の内側のSVGは青色で、<div>overflow-y: scroll;の内部にあります。

+0

ありがとう!私は基本的なコンセプトを採用し、よりハッキリではない方法で動作させました。 +1 – Kerrin631

+0

あなたが何かを作ったことを知っておきたい*ハッキー*以下。 'foreignObject'を避けるようにしてください... –

+0

@ Kerrin631あなたが思いついたあまりハッキリしない方法を見たいと思います。 – Matt

関連する問題