d3拖动仅在突出显示轴刻度时有效

时间:2018-07-25 13:06:21

标签: javascript angularjs d3.js

我正在研究一个将Angular和D3(v3)合并在一起的软件包,并尝试将D3的拖动功能合并到该软件包中。我非常接近成功,但是当我的图第一次渲染时,除非使用光标在x轴上选择文本,否则无法拖动元素(在本例中为矩形)。突出显示文本后,用户可以拖动矩形,并且该功能似乎正常运行,但是我真的很想修复最初的错误。

我已将问题复制到Github.io project found here中。我在第903-966行的库ivml.0.0.0(包含in the repo)中定义了从d3的拖动行为,我将在下面包括:

class MyAdminURLFieldWidget(URLInput):
    template_name = 'admin/widgets/url.html'

    def __init__(self, attrs=None):
        #final_attrs = {'class': 'vURLField'}
        final_attrs = {'type': 'file'}
        if attrs is not None:
            final_attrs.update(attrs)

        super(MyAdminURLFieldWidget, self).__init__(attrs=final_attrs)



    def get_context(self, name, value, attrs):
        context = super(MyAdminURLFieldWidget, self).get_context(name, value, attrs)
        context['current_label'] = _('Currently:')
        context['change_label'] = _('Change:')        
        context['widget']['href'] = smart_urlquote('/DownloadView/' + str(value.instance.id) + '/attachment/') if value else ''
        return context


class FilesAdmin(admin.ModelAdmin):
    list_display = ('id', '_animalid', '_filename', '_filedesc', 'ispublic', 'extra_info')
    search_fields = ('subjectid__animalid','filename')
    list_per_page = 50

    def formfield_for_dbfield(self, db_field, **kwargs):                                
        if db_field.name == 'filename':
            request = kwargs.pop("request", None)
            kwargs['widget'] = MyAdminURLFieldWidget

            return db_field.formfield(**kwargs)                                 

        else:
            return super(FilesAdmin, self).formfield_for_dbfield(db_field, **kwargs)


    def _animalid(self, obj):
        return obj.subjectid.animalid

    def _filename(self, obj):
        return obj.filename.name

    def _filedesc(self, obj):
        return obj.filedescid.description

我对Angular和Javascript / D3还是有点陌生​​,所以我可能会缺少一些真正的基础知识,但是任何见解都将不胜感激!

1 个答案:

答案 0 :(得分:-1)

我已经编写了所需的条形图拖动行为的d3v5,并且首先进行任何选择都没有问题。我建议跳过D3-Angular接口,并通过调用根据参数提供的数据绘制图形的函数自己在D3v5中绘制D3内容。

original bar graph数据中,小节值是对象的frequency字段。

<!DOCTYPE html>
<!-- based on bar chart https://bl.ocks.org/mbostock/3885304 -->
<meta charset="utf-8">
<style>
.active {
  stroke: #000;
  stroke-width: 2px;
}
.axis--y path {
  display: none;
}
</style>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>

var svg = d3.select("svg"),
    margin = {top: 20, right: 20, bottom: 30, left: 40},
    width = +svg.attr("width") - margin.left - margin.right,
    height = +svg.attr("height") - margin.top - margin.bottom;

var x = d3.scaleLinear().rangeRound([0, width]),
    y = d3.scaleBand().rangeRound([height, 0]).paddingInner(0.1);

var g = svg.append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var data = [
    {letter: 'A', x: 0, frequency: 1 },
    {letter: 'B', x: 0, frequency: 13 },
    {letter: 'C', x: 0, frequency: 6 },
    {letter: 'D', x: 0, frequency: 2 },
    {letter: 'E', x: 0, frequency: 5 },
    {letter: 'F', x: 0, frequency: 9 }
];

var colorFx = function(d, i){
                  var colors = ['blue', 'green', 'yellow', 'purple', 'orange'];
                  return colors[Math.floor(Math.random()*colors.length)];
              };

  x.domain([0, 7 + d3.max(data, function(d) { return d.frequency; })]);
  y.domain(data.map(function(d) { return d.letter; }));


  g.append("g")
      .attr("class", "axis axis--x")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x));

  g.append("g")
      .attr("class", "axis axis--y")
      .call(d3.axisLeft(y));

  g.selectAll(".bar")
    .data(data)
    .enter().append("rect")
      .attr("class", "bar")
      .attr("fill", colorFx)
      .attr("x", function(d) { return 0; })
      .attr("y", function(d) { return y(d.letter); })
      .attr("width", function(d) { return x(d.frequency); } )
      .attr("height", y.bandwidth() )
    .call(d3.drag()
      .on("start", dragstarted)
      .on("drag", dragged)
      .on("end", dragended));

var prevDragPosition = { x: 0, y: 0};

function dragstarted(d) {
  prevDragPosition.x = d3.event.x;
  prevDragPosition.y = d3.event.y;
  d3.select(this).classed("active", true);
}

function dragged(d) {
  // how much do we have to move the rect
  var deltaX = x.invert(d3.event.x) - x.invert(prevDragPosition.x);
  var node = d3.select(this);
  var dd = node.attr("x");
  var rectX = d.x + deltaX;
  // limit x position to the domain
  rectX = Math.max(x.domain()[0], rectX);
  rectX = Math.min(x.domain()[1]-d.frequency, rectX);
  d.x = rectX;
  node.attr("x", x(rectX));
  prevDragPosition.x = d3.event.x;
  prevDragPosition.y = d3.event.y;
}

function dragended(d, i) {
  d3.select(this).classed("active", false);
}

</script>