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 条评论