- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想在悬停在节点上时显示复选框,以便在单击该复选框时,该节点的名称应显示在蜘蛛图的顶部,如果未选中,则该名称应该消失。
我使用鼠标悬停事件来显示复选框,但不起作用
.on("mouseover", function(d) {
d3.select(this).transition()
.duration(200)
.style('cursor', 'pointer')
.html('<input type="checkbox" name="name" class="checkbox" />')
})
完整代码和演示
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script>
</head>
<body>
<svg className='spider-graph-svg'>
</svg>
<script>
var data = {
"name": "root@gmail.com",
"children": [{
"name": "Person Name 1",
"children": [{
"name": "Branch 4.1"
}, {
"name": "Branch 4.2"
}, {
"name": "Branch 4.2"
},
{
"name": "Branch 4.2"
}, {
"name": "Branch 4.2"
},
{
"name": "Branch 4.2"
}
]
}, {
"name": "Person name 2",
"children": [{
"name": "Branch 4.1"
}, {
"name": "Branch 4.2"
}, {
"name": "Branch 4.2"
},
{
"name": "Branch 4.2"
}, {
"name": "Branch 4.2"
},
{
"name": "Branch 4.2"
}
]
}, {
"name": "Person Name 3",
"children": [{
"name": "Branch 4.1"
}, {
"name": "Branch 4.2"
}, {
"name": "Branch 4.2"
},
{
"name": "Branch 4.2"
}, {
"name": "Branch 4.2"
},
{
"name": "Branch 4.2"
}
]
}, {
"name": "Person Name 4",
"children": [{
"name": "Branch 4.1"
}, {
"name": "Branch 4.2"
}, {
"name": "Branch 4.2"
},
{
"name": "Branch 4.2"
}, {
"name": "Branch 4.2"
},
{
"name": "Branch 4.2"
}
]
}]
};
const LAST_CHILDREN_WIDTH = 13;
let flagForChildren = false;
let groups = [];
data.children.forEach(d => {
let a = [];
if (d.children.length > 0) {
flagForChildren = true;
}
for (let i = 0; i < d.children.length; i += 2) {
let b = d.children.slice(i, i + 2);
if (b[0] && b[1]) {
a.push(Object.assign(b[0], {
children: [b[1]]
}));
} else {
let child = b[0];
if (i >= 6) {
child = Object.assign(child, {
children: [{
name: "..."
}]
});
}
a.push(child);
}
}
d.children = a;
groups.push(d);
});
data.children = groups;
let split_index = Math.round(data.children.length / 2);
let rectangleHeight = 45;
let leftData = {
name: data.name,
children: JSON.parse(JSON.stringify(data.children.slice(0, split_index)))
};
let leftDataArray = [];
leftDataArray.push(leftData);
// Right data
let rightData = {
name: data.name,
children: JSON.parse(JSON.stringify(data.children.slice(split_index)))
};
// Create d3 hierarchies
let right = d3.hierarchy(rightData);
let left = d3.hierarchy(leftData);
// Render both trees
drawTree(right, "right");
drawTree(left, "left");
// draw single tree
function drawTree(root, pos) {
let SWITCH_CONST = 1;
if (pos === "left") {
SWITCH_CONST = -1;
}
const margin = {
top: 20,
right: 120,
bottom: 20,
left: 120
},
width = window.innerWidth - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
let svg = d3
.select("svg")
.attr("height", height + margin.top + margin.bottom)
.attr("width", width + margin.right + margin.left)
.attr('view-box', '0 0 ' + (width + margin.right) + ' ' + (height + margin.top + margin.bottom))
.style("margin-top", "20px")
.style("margin-left", "88px");
const myTool = d3.select("body").append("div")
.attr("class", "mytooltip")
.style("opacity", "0")
.style("display", "none");;
// Shift the entire tree by half it's width
let g = svg.append("g").attr("transform", "translate(" + width / 2 + ",0)");
let deductWidthValue = flagForChildren ? 0 : width * 0.33;
// Create new default tree layout
let tree = d3
.tree()
// Set the size
// Remember the tree is rotated
// so the height is used as the width
// and the width as the height
.size([height - 50, SWITCH_CONST * (width - deductWidthValue) / 2])
.separation((a, b) => a.parent === b.parent ? 4 : 4.25);
tree(root);
let nodes = root.descendants();
let links = root.links();
// Set both root nodes to be dead center vertically
nodes[0].x = height / 2;
// Create links
let link = g
.selectAll(".link")
.data(links)
.enter();
link
.append("line")
.attr("class", function(d) {
if (d.target.depth === 2) {
return 'link'
} else {
return 'hard--link'
}
})
.attr("x1", function(d) {
if (
d.target.depth === 3
) {
return 0;
}
return d.source.y + 100 / 2; //d.source.y + 100/2
})
.attr("x2", function(d) {
if (
d.target.depth === 3
) {
return 0;
} else if (d.target.depth === 2) {
return d.target.y;
}
return d.target.y + 100 / 2; //d.target.y + 100/2;
})
.attr("y1", function(d) {
if (
d.target.depth === 3
) {
return 0;
}
return d.source.x + 50 / 2;
})
.attr("y2", function(d) {
if (
d.target.depth === 3
) {
return 0;
} else if (d.target.depth === 2) {
return d.target.x + LAST_CHILDREN_WIDTH / 2;
}
return d.target.x + 50 / 2;
});
//Rectangle width
let node = g
.selectAll(".node")
.data(nodes)
.enter()
.append("g")
.on("mouseover", function(d) {
d3.select(this).transition()
.duration(200)
.style('cursor', 'pointer')
.html('<input type="checkbox" name="name" class="checkbox" />')
})
.attr("class", function(d) {
return "node" + (d.children ? " node--internal" : " node--leaf");
})
.attr("transform", function(d) {
if (d.parent && d.parent.parent) { // this is the leaf node
if (d.parent.parent.parent) {
return (
"translate(" +
d.parent.y +
"," +
(d.x + LAST_CHILDREN_WIDTH + 15) +
")"
);
}
return "translate(" + d.y + "," + d.x + ")";
}
return "translate(" + d.y + "," + d.x + ")";
});
// topic rect
node
.append("rect")
.attr("height", (d, i) => d.parent && d.parent.parent ? 15 : rectangleHeight)
.attr("width", (d, i) => d.parent && d.parent.parent ? 15 : rectangleWidth(d))
.attr("rx", (d, i) => d.parent && d.parent.parent ? 5 : 5)
.attr("ry", (d, i) => d.parent && d.parent.parent ? 5 : 5)
// topic edges
node.append('line')
.attr('x1', d => {
if (d.depth === 2) {
return 10
}
})
.attr('x2', d => {
if (d.depth === 2) {
return 10
}
})
.attr('y1', d => {
if (d.depth === 2) {
if (d.children) {
return 0;
}
return 40;
}
})
.attr('y2', d => {
if (d.depth === 2) {
return 40
}
})
.attr('class', 'hard--link')
// topic names
node
.append("text")
.attr("dy", function(d, i) {
return d.parent && d.parent.parent ? 10 : rectangleHeight / 2;
})
.attr("dx", function(d, i) {
if (!(d.parent && d.parent.parent)) {
return 12;
} else {
return 20;
}
})
.style("fill", function(d, i) {
return d.parent && d.parent.parent ? "Black" : "White";
})
.text(function(d) {
let name = d.data.topic_name || d.data.name;
return name.length > 12 ? `${name.substring(0, 12)}...` : name;
})
.style("text-anchor", function(d) {
if (d.parent && d.parent.parent) {
return pos === "left" && "end"
}
})
.style("font-size", "12")
.attr("transform", function(d) {
if (d.parent && d.parent.parent) {
return pos === "left" ? "translate(-30,0)" : "translate(5,0)"
}
})
}
function rectangleWidth(d) {
const MIN_WIDTH = 50;
const MAX_WIDTH = 100;
let dynamicLength = 6;
if (d.data.topic_name) {
dynamicLength = d.data.topic_name.length;
} else if (d.data.name) {
dynamicLength = d.data.name.length;
}
dynamicLength = dynamicLength < 3 ? MIN_WIDTH : MAX_WIDTH;
return dynamicLength;
}
</script>
</body>
</html>
最佳答案
由于 input
元素不是 svg
元素,您不能像 html 元素那样简单地插入一个复选框并使其工作。我们必须使用 foreignObject
并在其中附加 input
。
一旦你创建了那些小的 rects
,我们需要附加一个包含我们的复选框的 foreignObject
并像这样隐藏它们:
// topic rect
node
.append("rect")
.attr("height", (d, i) => d.parent && d.parent.parent ? 15 : rectangleHeight)
.attr("width", (d, i) => d.parent && d.parent.parent ? 15 : rectangleWidth(d))
.attr("rx", (d, i) => d.parent && d.parent.parent ? 5 : 5)
.attr("ry", (d, i) => d.parent && d.parent.parent ? 5 : 5)
node.append('foreignObject').attr('width', '40')
.attr('height', '40').append('xhtml:input')
.attr('type', 'checkbox').style('display', 'none')
// An on click function for the checkboxes
.on("click",function(d){
console.log(d)
});
当用户将鼠标悬停在 rects
上时,我们可以简单地取消隐藏复选框,如果未选中则再次隐藏它们(否则继续显示直到用户取消选中):
.on("mouseover", function(d) {
d3.select(this).select('input').style('display', '');
})
.on('mouseout', function(d) {
if (!d3.select(this).select('input').property('checked')) {
d3.select(this).select('input').style('display', 'none');
}
});
完整代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script>
</head>
<body>
<svg className='spider-graph-svg'>
</svg>
<script>
var prevElem;
var data = {
"name": "root@gmail.com",
"children": [{
"name": "Person Name 1",
"children": [{
"name": "Branch 4.1"
}, {
"name": "Branch 4.2"
}, {
"name": "Branch 4.2"
},
{
"name": "Branch 4.2"
}, {
"name": "Branch 4.2"
},
{
"name": "Branch 4.2"
}
]
}, {
"name": "Person name 2",
"children": [{
"name": "Branch 4.1"
}, {
"name": "Branch 4.2"
}, {
"name": "Branch 4.2"
},
{
"name": "Branch 4.2"
}, {
"name": "Branch 4.2"
},
{
"name": "Branch 4.2"
}
]
}, {
"name": "Person Name 3",
"children": [{
"name": "Branch 4.1"
}, {
"name": "Branch 4.2"
}, {
"name": "Branch 4.2"
},
{
"name": "Branch 4.2"
}, {
"name": "Branch 4.2"
},
{
"name": "Branch 4.2"
}
]
}, {
"name": "Person Name 4",
"children": [{
"name": "Branch 4.1"
}, {
"name": "Branch 4.2"
}, {
"name": "Branch 4.2"
},
{
"name": "Branch 4.2"
}, {
"name": "Branch 4.2"
},
{
"name": "Branch 4.2"
}
]
}]
};
const LAST_CHILDREN_WIDTH = 13;
let flagForChildren = false;
let groups = [];
data.children.forEach(d => {
let a = [];
if (d.children.length > 0) {
flagForChildren = true;
}
for (let i = 0; i < d.children.length; i += 2) {
let b = d.children.slice(i, i + 2);
if (b[0] && b[1]) {
a.push(Object.assign(b[0], {
children: [b[1]]
}));
} else {
let child = b[0];
if (i >= 6) {
child = Object.assign(child, {
children: [{
name: "..."
}]
});
}
a.push(child);
}
}
d.children = a;
groups.push(d);
});
data.children = groups;
let split_index = Math.round(data.children.length / 2);
let rectangleHeight = 45;
let leftData = {
name: data.name,
children: JSON.parse(JSON.stringify(data.children.slice(0, split_index)))
};
let leftDataArray = [];
leftDataArray.push(leftData);
// Right data
let rightData = {
name: data.name,
children: JSON.parse(JSON.stringify(data.children.slice(split_index)))
};
// Create d3 hierarchies
let right = d3.hierarchy(rightData);
let left = d3.hierarchy(leftData);
// Render both trees
drawTree(right, "right");
drawTree(left, "left");
// draw single tree
function drawTree(root, pos) {
let SWITCH_CONST = 1;
if (pos === "left") {
SWITCH_CONST = -1;
}
const margin = {
top: 20,
right: 120,
bottom: 20,
left: 120
},
width = window.innerWidth - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
let svg = d3
.select("svg")
.attr("height", height + margin.top + margin.bottom)
.attr("width", width + margin.right + margin.left)
.attr('view-box', '0 0 ' + (width + margin.right) + ' ' + (height + margin.top + margin.bottom))
.style("margin-top", "20px")
.style("margin-left", "88px");
const myTool = d3.select("body").append("div")
.attr("class", "mytooltip")
.style("opacity", "0")
.style("display", "none");;
// Shift the entire tree by half it's width
let g = svg.append("g").attr("transform", "translate(" + width / 2 + ",0)");
let deductWidthValue = flagForChildren ? 0 : width * 0.33;
// Create new default tree layout
let tree = d3
.tree()
// Set the size
// Remember the tree is rotated
// so the height is used as the width
// and the width as the height
.size([height - 50, SWITCH_CONST * (width - deductWidthValue) / 2])
.separation((a, b) => a.parent === b.parent ? 4 : 4.25);
tree(root);
let nodes = root.descendants();
let links = root.links();
// Set both root nodes to be dead center vertically
nodes[0].x = height / 2;
// Create links
let link = g
.selectAll(".link")
.data(links)
.enter();
link
.append("line")
.attr("class", function(d) {
if (d.target.depth === 2) {
return 'link'
} else {
return 'hard--link'
}
})
.attr("x1", function(d) {
if (
d.target.depth === 3
) {
return 0;
}
return d.source.y + 100 / 2; //d.source.y + 100/2
})
.attr("x2", function(d) {
if (
d.target.depth === 3
) {
return 0;
} else if (d.target.depth === 2) {
return d.target.y;
}
return d.target.y + 100 / 2; //d.target.y + 100/2;
})
.attr("y1", function(d) {
if (
d.target.depth === 3
) {
return 0;
}
return d.source.x + 50 / 2;
})
.attr("y2", function(d) {
if (
d.target.depth === 3
) {
return 0;
} else if (d.target.depth === 2) {
return d.target.x + LAST_CHILDREN_WIDTH / 2;
}
return d.target.x + 50 / 2;
});
//Rectangle width
let node = g
.selectAll(".node")
.data(nodes)
.enter()
.append("g")
.on("mouseover", function(d) {
d3.select(this).select('input').style('display', '')
})
.on('mouseout', function(d) {
if (!d3.select(this).select('input').property('checked')) {
d3.select(this).select('input').style('display', 'none')
}
})
.attr("class", function(d) {
return "node" + (d.children ? " node--internal" : " node--leaf");
})
.attr("transform", function(d) {
if (d.parent && d.parent.parent) { // this is the leaf node
if (d.parent.parent.parent) {
return (
"translate(" +
d.parent.y +
"," +
(d.x + LAST_CHILDREN_WIDTH + 15) +
")"
);
}
return "translate(" + d.y + "," + d.x + ")";
}
return "translate(" + d.y + "," + d.x + ")";
});
// topic rect
node
.append("rect")
.attr("height", (d, i) => d.parent && d.parent.parent ? 15 : rectangleHeight)
.attr("width", (d, i) => d.parent && d.parent.parent ? 15 : rectangleWidth(d))
.attr("rx", (d, i) => d.parent && d.parent.parent ? 5 : 5)
.attr("ry", (d, i) => d.parent && d.parent.parent ? 5 : 5)
// Create foreign object checkboxes and keep them hidden
node.append('foreignObject').attr('width', '40').attr('height', '40').append('xhtml:input').attr('type', 'checkbox').style('display', 'none')
// topic edges
node.append('line')
.attr('x1', d => {
if (d.depth === 2) {
return 10
}
})
.attr('x2', d => {
if (d.depth === 2) {
return 10
}
})
.attr('y1', d => {
if (d.depth === 2) {
if (d.children) {
return 0;
}
return 40;
}
})
.attr('y2', d => {
if (d.depth === 2) {
return 40
}
})
.attr('class', 'hard--link')
// topic names
node
.append("text")
.attr("dy", function(d, i) {
return d.parent && d.parent.parent ? 10 : rectangleHeight / 2;
})
.attr("dx", function(d, i) {
if (!(d.parent && d.parent.parent)) {
return 12;
} else {
return 20;
}
})
.style("fill", function(d, i) {
return d.parent && d.parent.parent ? "Black" : "White";
})
.text(function(d) {
let name = d.data.topic_name || d.data.name;
return name.length > 12 ? `${name.substring(0, 12)}...` : name;
})
.style("text-anchor", function(d) {
if (d.parent && d.parent.parent) {
return pos === "left" && "end"
}
})
.style("font-size", "12")
.attr("transform", function(d) {
if (d.parent && d.parent.parent) {
return pos === "left" ? "translate(-30,0)" : "translate(5,0)"
}
})
}
function rectangleWidth(d) {
const MIN_WIDTH = 50;
const MAX_WIDTH = 100;
let dynamicLength = 6;
if (d.data.topic_name) {
dynamicLength = d.data.topic_name.length;
} else if (d.data.name) {
dynamicLength = d.data.name.length;
}
dynamicLength = dynamicLength < 3 ? MIN_WIDTH : MAX_WIDTH;
return dynamicLength;
}
</script>
</body>
</html>
我相信您可以从这里完成剩下的工作。
关于javascript - 悬停在节点上时显示节点内的复选框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50251227/
我正在学习和使用 jQuery,并且想要显示某些元素的删除图标。 我有一个外部主 div,其中包含许多元素的包装器。在元素包装器内部,我想当用户将鼠标悬停在元素包装器上时显示删除图标,并在用户移出元素
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我从 Qt 开始,每当有人将鼠标悬停在 QPushButton 上时,我想将 QPushButton 设置为不同的图标。到目前为止,这是我的代码: #include QPushButton *but
我从 Qt 开始,我想在有人将鼠标悬停在 QPushButton 上时将其设置为不同的图标。到目前为止,这是我的代码: #include QPushButton *button = new QPus
我有以下代码... jQuery(function($) { var timer; $('.action-viewer').hide(); $('.task').on('mouseover
我有一张照片,当用户将鼠标悬停在它上面时,我会在照片顶部显示(使用绝对定位)2 个箭头,一个用于进入上一张照片,一个用于进入下一张照片。这是到目前为止的代码... $('a.large_product
$('li > a').hover( function(){ $(this).animate({ backgroundColor: '#2a639a', color: '#fff'
我有一个悬停事件附加到几个链接,当您点击它时,会出现一个框。 有没有一种方法可以让悬停事件仅在鼠标悬停在链接上超过 500 毫秒时触发?因此,目前只要鼠标移到链接上,就会出现该框,但我希望只有当鼠标悬
我正在创建包含各种样式控件的演示应用程序。它允许我快速预览更改。 我的问题是下面的代码不起作用: Pressed button 它表示 IsPressed 的 setter 受到保护。我明白了,但我需
我正在尝试使用 js 并创建带有一些“信息文本”的“描述框” HTML google JS function info() {} 我不知道是哪个代码用一些文本创建了所谓的“描
我有一个 Accordion 风格的菜单,在悬停状态下工作正常,但我想改为点击... $(document).ready(function(){ $('#nav > li').hover(
我正在使用 Chartjs v.1.0.2 并尝试将点设置为仅在悬停在当前点上时出现。同样的问题是当我使用悬停或鼠标悬停时。可以使用 getPointsAtEvent(e); 找到当前点,但它仅在我将
我使用foreach 语句访问IEnumerable 的所有元素并将其呈现在详细信息页面中。我想让每个元素的悬停属性只影响一个元素。所以我使用 jQuery 单独影响每个元素 但是当我运行代码并将鼠标
首先提前感谢您的帮助。 案例:我在一行中有多个 div。这些 div 位于一个框中,我可以在此框中水平滚动以查看其他 div。我制作了两个按钮(L 表示左侧,R 表示右侧),以便在悬停或单击这些按钮时
我正在创建一个应用外观页面。 我希望在鼠标悬停时打开底部菜单上的其中一个按钮。 这感觉像是一项简单的任务,但我所做的一切似乎都不起作用。我错过了什么,我做了很多研究,但似乎找不到解决方案。 我尝试使用
我遇到的问题是,当您将鼠标悬停在按钮上时,只有按钮的某些部分会触发悬停/可点击状态,而不是所有实际 block 。有什么想法吗? 这是使用它的站点:http://www.revival.tv/turn
我有一位客户想要在他们的网站上实现特定功能,但我有点困惑如何做到这一点。 基本上,如果你查看他们的 existing site您可以看到 4 个圆形按钮。 他们想要的是,当有人将鼠标悬停(或单击,如果
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 关闭 9 年前。 关于您编写的代码问题的问题必须在问题本身中描述具体问题 — 并且包括有效代码 以
我目前正在编写我的第一个响应式网站(总的来说我是一个初学者)并且我遇到了很多障碍。其中之一是我的菜单有问题。我会尽量具体。我有一个用于桌面的水平菜单和一个用于平板电脑/手机的垂直菜单。我不知道如何解决
我正在为网站创建菜单。我正试图在链接上实现悬停 和点击 效果。我希望列表元素 a 上的悬停事件触发彩色动画并添加“事件”类。如果触发了点击和悬停事件,我想为该元素分配相同的类。问题是,一旦元素未悬停并
我是一名优秀的程序员,十分优秀!