javascript - D3 绑定文本和 SVG
问题描述
我正在创建我的第一个 d3.js 项目,其中包含可以使用居中文本拖动、添加或删除的圆圈,但我似乎无法将文本绑定到圆圈。我见过一些与我的问题类似的问题,但我希望这足够不同,因为我尝试应用这些解决方案但它们没有用。我不仅在寻找解决方案,而且想知道我在这里做错了什么。
任何见解都会非常有帮助!
我尝试创建一个组变量group
并假设我可以使用它来绑定两个元素。我的心理模型有什么问题?
chart = {
const dataset = [
{start: new Date("2019-09-23 1:00 AM"), target: 70},
{start: new Date("2019-09-23 8:00 AM"), target: 75},
{start: new Date("2019-09-23 9:00 PM"), target: 70},
{start: new Date("2019-09-23 1:00 PM"), target: 75},
{start: new Date("2019-09-23 5:00 PM"), target: 70},
{start: new Date("2019-09-23 6:00 PM"), target: 65},
]
var xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, function(d) {
return d.x_pos
})]).range([0, width]);
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.attr("stroke-width", 2);
svg.append("g")
.call(xAxis)
var group = svg.selectAll('g')
.data(dataset)
.enter()
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")")
group.append("circle")
.data(dataset)
.enter()
.append("circle")
.join("circle")
.attr("cx", d => x(d.start))
.attr("cy", 55)
.attr("r", 30)
.attr("fill", "red")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
.on("click", removeElement);
group.append("text")
.data(dataset)
.enter()
.append("text")
.attr("x", function(d) { return x(d.start) - 10; })
.attr("y", function(d) { return 60; })
.style("fill", "white")
.text(function(d) { return d.target })
.call(d3.drag()
.on("drag", dragged))
.on("click", removeElement)
svg.on("click", function() {
var coords = d3.mouse(this);
var newData = {
x: d3.event.x,
y: d3.event.y,
target: 0
};
dataset.push(newData);
group.append("circle")
.attr("cx", function(d) {
return x(d.start);
})
.attr("cy", function(d) {
return 55;
})
.attr("r", 30)
.style("fill", "red")
.attr('id', function(d, i) {
return 'circle_' + i;
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
.on("click", removeElement);
group.append("text")
.data(dataset)
.enter()
.append("text")
.attr("x", function(d) { return x(d.start) - 10; })
.attr("y", function(d) { return 60; })
.style("fill", "white")
.text(function(d) { return d.target })
.call(d3.drag()
.on("drag", dragged))
.on("click", removeElement)
})
function dragstarted(d) {
d3.select(this).raise().attr("stroke", "black");
}
function dragged(d) {
// tried adding .select("circle") from prior SO posts
d3.select(this)
.attr("cx", d.x = d3.event.x)
.attr("cy", d.y = 55);
d3.select(this) //.select("text")
.attr("x", d.x = d3.event.x - 10)
.attr("y", d.y = 60);
}
function dragended(d) {
d3.select(this).attr("stroke", null);
}
function removeElement(d) {
d3.event.stopPropagation()
d3.select(this)
.remove();
}
return svg.node();
}
x = d3.scaleTime()
.domain([new Date("2019, 9, 23 12:00 AM"), new Date("2019, 9, 23, 11:59 PM")])
.rangeRound([margin.left, width - margin.right])
interval = d3.timeHour.every(1)
xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(g => g.append("g")
.call(d3.axisBottom(x)
.ticks(interval)
.tickSize(-height + margin.top + margin.bottom)
.tickFormat(() => null))
.call(g => g.select(".domain")
.attr("fill", "#ddd")
.attr("stroke", null))
.call(g => g.selectAll(".tick line")
.attr("stroke", "#fff")
.attr("stroke-opacity", d => d <= d3.timeHour(d) ? 1 : 0.5)))
.call(g => g.append("g")
.call(d3.axisBottom(x)
.ticks(d3.timeHour)
.tickPadding(0))
.attr("text-anchor", null)
.call(g => g.select(".domain").remove())
.call(g => g.selectAll("text").attr("x", 6)))
margin = ({top: 10, right: 0, bottom: 20, left: 0})
height = 120
d3 = require("d3@5")
解决方案
您需要将 svg 视为一组元素,其中元素也可以是元素组。
有一个里面有文字的圆圈是什么样子的?
<svg...>
<g id="myGroup">
<circle style="" cx="250" cy="250" r="245"></circle>
<text x="50%" y="50%" stroke="#111"> Hello !</text>
</g>
</svg>
现在,如果您想从头开始生成此 svg:
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
var group = document.createElementNS("http://www.w3.org/2000/svg","g");
group.setAttribute("id","myGroup")
var newCircle = document.createElementNS(svgNS,"circle");
var newText = document.createElementNS(svgNS,"text");
newText.setAttributeNS(null,"x", "50%");
newText.setAttributeNS(null,"y", "50%");
document.getElementById("svg").appendChild(myGroup);
document.getElementById("myGroup").appendChild(newCircle);
圆圈和文本绑定到一个组中。然后拖动你的组,而不是你的圈子;)
推荐阅读
- azure-media-services - (ResourceGroupNotFound) 资源组 '????' 创建 Azure 媒体服务帐户时找不到
- delphi - 如何更改语音语言
- python - Python "in" 和 "==" 混淆
- python - 如何通过使用数据框在某一列上使用随机数
- c - 在 C 中对齐使用多少内存?
- html - 如何保持图标在 div 内严格对齐?
- html - 角度5:表格行内的模板绑定
- python - Flask-Rebar 规则验证
- node.js - Alexa 技能学习:TypeError:无法读取未定义的属性“值”
- paypal - “帐户可选”功能是否可用于 PayPal 的订阅?