我正在研究一个将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还是有点陌生,所以我可能会缺少一些真正的基础知识,但是任何见解都将不胜感激!
答案 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>