Delegating drag function in Raphael

别来无恙 提交于 2020-01-11 07:54:09

问题


Using Raphael, I wish to be able to drag a shape (an ellipse in the example below) containing a text object, dragging either the shape or the text. I hoped to do this by setting the functions passed to the text element's drag() method to delegate to the associated shape (trying a more polymorphic approach to this other one). However, this results in an error "obj.addEventListener is not a function" when text.drag(...) is called.

I'm new to javascript, so I've probably made a really obvious blunder, but I can't spot it. Have I misused call() in my delegating functions moveText, dragText, and upText? Or is this a Raphael thing? Any help would be greatly appreciated.

<html>
<head>
<title>Raphael delegated drag test</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="js/raphael.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<script type="text/javascript">
window.onload = function initPage() {
    'use strict';
    var paper = Raphael("holder", 640, 480);
    var shape = paper.ellipse(190,100,30, 20).attr({
            fill: "green", 
            stroke: "green", 
            "fill-opacity": 0, 
            "stroke-width": 2, 
            cursor: "move"
        });
    var text = paper.text(190,100,"Ellipse").attr({
            fill: "green", 
            stroke: "none", 
            cursor: "move"
        });

    // Associate the shape and text elements with each other
    shape.text = text;
    text.shape = shape;

    // Drag start
    var dragShape = function () {
        this.ox = this.attr("cx");
        this.oy = this.attr("cy");
    } 
    var dragText = function () {
        dragShape.call(this.shape);
    }

    // Drag move
    var moveShape = function (dx, dy) {
        this.attr({cx: this.ox + dx, cy: this.oy + dy});
        this.text.attr({x: this.ox + dx, y: this.oy + dy});
    }
    var moveText = function (dx,dy) {
        moveShape.call(this.shape,dx,dy);
    }

    // Drag release
    var upShape = function () {
    }       
    var upText = function () {
        upShape.call(this.shape);
    }

    shape.drag(moveShape, dragShape, upShape);
    text.drag(moveText, dragText, upText);
};
</script> 
    <div id="holder"></div>
</body>
</html>

Solution

As pointed out in this answer, the problem arises from the choice of the attribute names:

// Associate the shape and text elements with each other
shape.text = text;
text.shape = shape;

Changing these to more verbose names (and less likely to conflict with Raphael) makes the problem go away, but it's safer to set them as data attributes :

// Associate the shape and text elements with each other
shape.data("enclosedText",text);
text.data("parentShape",shape);

// Drag start
var dragShape = function () {
    this.ox = this.attr("cx");
    this.oy = this.attr("cy");
} 
var dragText = function () {
    dragShape.call(this.data("parentShape"));
}

// Drag move
var moveShape = function (dx, dy) {
    this.attr({cx: this.ox + dx, cy: this.oy + dy});
    this.data("enclosedText").attr({x: this.ox + dx, y: this.oy + dy});
}
var moveText = function (dx,dy) {
    moveShape.call(this.data("parentShape"),dx,dy);
}

回答1:


// Associate the shape and text elements with each other
shape.text = text;
text.shape = shape;

You are adding attributes to Raphael objects. Without knowing how Raphael works (or will work in the future) this is dangerous and apparently also what's causing the problem. If you really want to associate them i recommend using Raphaels Element.data: http://raphaeljs.com/reference.html#Element.data



来源:https://stackoverflow.com/questions/8830330/delegating-drag-function-in-raphael

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!