如何在Raphael元素上添加上下文菜单? [英] How to add context menu on Raphael element?

查看:108
本文介绍了如何在Raphael元素上添加上下文菜单?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 ExtJS 4 框架,并且还在主应用程序面板中使用了 Raphael.js

I am working with ExtJS 4 framework and also using Raphael.js in my main application panel.

首先,我试图防止显示常规上下文菜单,但发现了非常简单的解决方案。

First I was trying to prevent the regular context menu from showing, and I found out very easy solution.

raphael_element.node.oncontextmenu = function()
{
    return false;
} 

这很好,但是在返回false之前我想添加一些代码显示我自己的自定义菜单。
有人知道怎么做吗?

This is working great, but before returning false I want to add some code to show my own custom menu.
Does anyone know how to do that?

我在html中有一些东西想在菜单中使用:

I have something in html, that was thinking to use in the menu:

<ul id="rect_menu" class="contextMenu">
    <li><a href="call_to_js_function">Set aaa</a></li>
    <li><a href="call_to_js_function">Set xxx</a></li>
    <li><a href="call_to_js_function">Set ccc</a></li>
</ul>

如您所见,我有 css类(样式不是这里的代码,无关紧要)进行样式设置,当用户右键单击 ie时显示 id = rect_menu 拉斐尔矩形对象。

As you can see, I have css class (code is not here, it irrelevant) for styling and id=rect_menu to show up when user right clicks on the i.e. Raphael rectangle object.

任何人都可以展示一种方式,也许是不涉及jQuery的小型演示吗? Thnaks

Can anyone show a way, maybe small demo that does not involve jquery? Thnaks

推荐答案

您可以使用Ext在浮动组件:

You can use Ext to display your custom HTML in a floating component:

var menu = Ext.create('Ext.Component', {
    floating: true
    ,html: ['<ul id="rect_menu" class="contextMenu">',
        '<li><a href="call_to_js_function">Set aaa</a></li>',
        '<li><a href="call_to_js_function">Set xxx</a></li>',
        '<li><a href="call_to_js_function">Set ccc</a></li>',
        '</ul>'].join('')
});

Ext.get(raphael_element.node).on({
    contextmenu: function(e) {
        menu.showAt(e.getXY());
        e.preventDefault();
    }
});

但是,显示菜单并不是棘手的部分。当用户在菜单外单击或按ESC键时,隐藏菜单的逻辑涉及很多。这就是为什么我会使用常规的 Menu 让Ext为我们完成繁重的工作。

However, showing the menu is not the tricky part. The logic to have your menu hidden, either when the user click outside of it, or when the ESC key is pressed is a lot more involved. That's why I would use a regular Menu to let Ext do the heavy lifting for us.

var menu = Ext.create('Ext.menu.Menu', {
    items: [{
        text: 'Set aaa'
        ,handler: function() {
            // logic for aaa
        }
    }, {
        text: 'Set bbb'
        ,handler: function() {
            // logic for bbb
        }
    }]
});

Ext.get(raphael_element.node).on({
    contextmenu: function(e) {
        menu.showAt(e.getXY());
        e.preventDefault();
    }
});

现在,如果您不希望使用所有菜单系统以及Ext菜单项等,而您确实要呈现自己的HTML,您仍然可以利用Ext菜单来受益于其隐藏机制:

Now, if you're not interested in using all the menu system, with Ext menu items, etc., and you really want to render your own HTML, you can still leverage Ext menu to benefit from its hiding mechanics:

var menu = Ext.create('Ext.menu.Menu', {
    // This will prevent the icon gutter from showing, and your component from
    // being left padded
    plain: true
    ,items: [{
        xtype: 'component'
        ,html: ['<ul id="rect_menu" class="contextMenu">',
            '<li><a href="call_to_js_function">Set aaa</a></li>',
            '<li><a href="call_to_js_function">Set xxx</a></li>',
            '<li><a href="call_to_js_function">Set ccc</a></li>',
            '</ul>'].join('')
    }]
});

Ext.get(raphael_element.node).on({
    contextmenu: function(e) {
        menu.showAt(e.getXY());
        e.preventDefault();
    }
});

这里是小提琴,使用最后一个示例。它不使用Raphael,但是从您获得的DOM元素开始就没有任何意义。

Here's a fiddle using that last example. It doesn't use Raphael, but from the moment you get a DOM element that won't bear any importance.

编辑实际示例拉斐尔元素

我已经更新了我的小提琴与实际的Raphael元素。它确实按预期工作。

I've updated my fiddle with actual Raphael elements. It does work exactly as intended.

最酷的是,元素的click事件完全遵循矢量路径范围,这意味着您可以精确地确定菜单将在何处弹出。较不酷的是,例如,著名的 tiger 意味着240个事件处理程序。您可以始终将处理程序添加到SVG元素中,而不是将单个形状元素添加到SVG元素中,但是菜单将绑定到整个绘图矩形,而不是绑定到单个部分。

What is cool is that the click event of the element totally respects the vectorial path bounds, meaning you can precisely decide where your menu will pop or not. What is less cool is that with, for example, the famous tiger, that would mean 240 event handlers... Kinda ouch performance-wise.... You can always add the handler to the SVG element instead of individual shape elements, but the menu will be bound to the whole drawing rectangle instead of individual parts of course.

// --- Creating a ball (see http://raphaeljs.com/ball.html)
Raphael.fn.ball = function (x, y, r, hue) {
    hue = hue || 0;
    return this.set(
        this.ellipse(x, y + r - r / 5, r, r / 2).attr({fill: "rhsb(" + hue + ", 1, .25)-hsb(" + hue + ", 1, .25)", stroke: "none", opacity: 0}),
        this.ellipse(x, y, r, r).attr({fill: "r(.5,.9)hsb(" + hue + ", 1, .75)-hsb(" + hue + ", .5, .25)", stroke: "none"}),
        this.ellipse(x, y, r - r / 5, r - r / 20).attr({stroke: "none", fill: "r(.5,.1)#ccc-#ccc", opacity: 0})
    );
};

var R = Raphael("holder"), x = 310, y = 180, r = 150;
var ball = R.ball(x, y, r, Math.random());

// --- Creatin a custom menu
var menu = Ext.create('Ext.menu.Menu', {
    plain: true
    ,cls: 'myContextMenu'
    ,items: [{
        xtype: 'component'
        ,html: ['<ul id="rect_menu" class="contextMenu">',
            '<li><a href="call_to_js_function">Set aaa</a></li>',
            '<li><a href="call_to_js_function">Set xxx</a></li>',
            '<li><a href="call_to_js_function">Set ccc</a></li>',
            '</ul>'].join('')
    }]
});

// --- Adding menu handler to all ball's elements

var contextMenuHandler = function(e) {
    menu.showAt(e.getXY());
    e.preventDefault();
};

Ext.each(ball, function(raphaelElement) {
    Ext.fly(raphaelElement.node).on({
        contextmenu: contextMenuHandler
    });
});

这篇关于如何在Raphael元素上添加上下文菜单?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆