Javascript 动态创建可滚动的SVG

Javascript 动态创建可滚动的SVG,javascript,css,d3.js,svg,Javascript,Css,D3.js,Svg,我正在尝试创建一个可滚动列表。我在这里看过其他教程,但它似乎不起作用。本质上,我将SVG附加到一个div中。在这个SVG中是一个D3JS堆叠条形图。在这个条形图的右边,我添加了一个“g”元素,里面有一个svg。我已经为这个权利设定了一个高度。在本文中,我填充了一个列表,该列表将超出SVG的高度。我已将此svg的CSS设置为“overflow-y:scroll” 尽管如此,我还是无法让这个svg滚动。相反,它只是增长到列表的大小,并扩展到预期的边界。请参阅下面的代码 var barSVG = d3

我正在尝试创建一个可滚动列表。我在这里看过其他教程,但它似乎不起作用。本质上,我将SVG附加到一个div中。在这个SVG中是一个D3JS堆叠条形图。在这个条形图的右边,我添加了一个“g”元素,里面有一个svg。我已经为这个权利设定了一个高度。在本文中,我填充了一个列表,该列表将超出SVG的高度。我已将此svg的CSS设置为“overflow-y:scroll”

尽管如此,我还是无法让这个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个数据项

此外,我还添加了以下CSS:

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

简短回答:在另一个SVG中不能有可滚动的SVG。
overflow-y:scroll
适用于HTML元素,而不是SVG元素

备选答案(和黑客答案):从技术上讲,您想要的是可能的,但您必须将内部SVG封装在HTML元素中,该元素必须位于
外来对象

这种选择是次优的,没有什么意义,不适用于IE。然而,出于好奇,你可以这样做:

var outerSvg=d3.选择(“主体”)
.append(“svg”)
.attr(“宽度”,500)
.attr(“高度”,200)
.风格(“背景色”、“黑色”);
var foreign=outerSvg.append(“foreignObject”)
.attr(“x”,300)
.attr(“y”,10)
.attr(“宽度”,150)
.attr(“高度”,180)
.append(“xhtml:div”)
.样式(“最大高度”,“180像素”)
.样式(“溢出y”、“滚动”);
var innerssvg=foreign.append(“svg”)
.attr(“宽度”,133)
.attr(“高度”,1000)
.风格(“背景色”、“粉蓝色”);
var color=d3.scaleOrdinal(d3.schemeCategory 20);
var text=innerssvg.selectAll(“foo”)
.数据(d3.范围(65))
.输入()
.append(“文本”)
.attr(“x”,40)
.attr(“y”,(d,i)=>20+15*i)
.text(“foo-bar-baz”)
var rects=innerSvg.selectAll(“foo”)
.数据(d3.范围(65))
.输入()
.append(“rect”)
.attr(“x”,10)
.attr(“y”,(d,i)=>8+15*i)
.attr(“宽度”,20)
.attr(“高度”,13)
.attr(“填充”(d,i)=>颜色(i))

您考虑过使用吗?我想如果你把“最小/最大比例”设置为1,它会变得非常接近滚动。谢谢!我采用了基本的概念,并以一种不太老套的方式使其工作+1@Kerrin631我想看看你想出的不那么粗鲁的方式。这非常有用!我花了几个小时尝试使用SVG,直到找到这个。