Ant-design的 dropdown 组件中针对右键菜单提出了一个用法,即将 trigger 设置为 contextmenu ,以这种方法可以在 render 中使得其下属的 contextmenu 都变为这一下拉菜单。
import { Menu, Dropdown } from 'antd';
const menu = (
<Menu>
<Menu.Item key="1">1st menu item</Menu.Item>
<Menu.Item key="2">2nd menu item</Menu.Item>
<Menu.Item key="3">3rd menu item</Menu.Item>
</Menu>
);
ReactDOM.render(
<Dropdown overlay={menu} trigger={['contextMenu']}>
<div
className="site-dropdown-context-menu"
style={{
textAlign: 'center',
height: 200,
lineHeight: '200px',
}}
>
Right Click on here
</div>
</Dropdown>,
mountNode,
);
但是在d3中,元素是动态生成的,已知的只有svg画布,如何使只有在点击到元素的时候右键菜单才会出现,并且匹配当前选中元素的属性->是问题提出的背景。
d3中针对鼠标事件,存在许多的回调函数,其中 .on('contextmenu',function) 这一回调是针对右键菜单的。即点击鼠标右键会调用该函数。
Ant-design 的 dropdown 可以设置 visible 数值。因此,我们的 d3 回调函数可以这样安排:设置右键菜单对应的元素属性->将右键菜单的 visible 设为 true。
右键菜单的元素属性和 visible 都可以存在组件的 state 里。这样就能实现右键元件时菜单才出现的效果。另外还需要添加菜单消失的效果,在点击菜单中的动作结束时、鼠标移出该区域时、鼠标点击其他区域时加入回调 this.setState({menuVisible:false}) 即可。
render部分:
render() {
const self = this;
const menu = (
<Menu onClick={self.handleMenuClick}>
<Menu.Item key="1">跳转</Menu.Item>
<Menu.Item key="2">修改检查状态</Menu.Item>
<Menu.Item key="3">以该顶点为根重置</Menu.Item>
</Menu>
);
return (
<>
<div>
<Collapse defaultActiveKey={['1']}>
<Panel header="二维可视化" key="1">
<Row>
<Col>
选择端点Index: <InputNumber defaultValue={this.props.data.selectedVertexIndex} onChange={(v)=>this.onChange(v)} />
</Col>
</Row>
<Dropdown overlay={menu} trigger={['contextMenu']} visible={self.state.menuVisible}>
<div className="Rectangle" id="Rectangle" ref="Rectangle" onClick={()=>self.setState({menuVisible:false})}>
<div className="wuliwala">
<svg></svg>
</div>
</div>
</Dropdown>
</Panel>
</Collapse>
</div>
</>
);
}
d3.node部分:
var nodeEnter = node.enter().append('g')
.attr('class', 'node')
.attr("transform", function(d) {
return "translate(" + source.y0 + "," + source.x0 + ")";
})
.on('click', click)
.on('dblclick',onClickJump)
.on("mouseover", mouseover)
.on("mousemove", function(event, d){
mousemove(event, d);})
.on("mouseout", mouseout)
.on("contextmenu", menu)
var menu = (e,i) =>{
console.log(e);
console.log(i);
self.setState({menuIndex:i.data.name,menuVisible:true,checked:i.data.checked});
}
this.state部分:
this.state = {
menuIndex:-1,
menuVisible: false,
checked:false,
};
也可以在这里直接存储全部的 data 而不是单属性存储,不过暂时懒得改了)
然后再写一个 handleMenuClick 回调即可,就是菜单中选择不同选项之后的操作,记得在这个里面加上一句 this.setState({menuVisible:false}); 。下面是本人不酷的效果展示:
0 条评论