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,
);

参考:下拉菜单-Ant-design

但是在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 条评论

发表评论

Avatar placeholder