Raphael.js attr function sets wrong value

前端 未结 3 1028
梦毁少年i
梦毁少年i 2021-01-21 17:40

I\'m implementing a drag and drop system with Raphael.js. For this, i\'m storing the original x and y position on mousedown, and if there is a collision on mouseup, I want to re

相关标签:
3条回答
  • 2021-01-21 17:46

    I'm not sure why this is happening. I tried even capturing the co-ordinates before onstart using onmousedown event, even that didnt work. Also different methods provided by Raphael to get the co-ordinates using getBBox(), accessing x and y directly, didnt help.

    So what I thought is, we should Maintain and Track the coordinates manually. So I have used your original_x and original_y variables which captures the position of the <path> after you create and set with some transform value. Below is the code of the same

    Here is the working fiddle.

    this.raph = R.path(svgPath).attr({
        stroke: "hsb(0, 1, 1)",
        fill: "#fff", 
        opacity: 1.0, 
        cx: 100, 
        cy: 900 
    }).transform("t" + x + "," + y); 
    
    this.raph.original_x = x;
    this.raph.original_y = y;
    
    
    //comment the lines in start method which captures original_x and original_y
    //this.original_x = Raphael.parseTransformString(this.attr("transform"))[0][1];
    //this.original_y = Raphael.parseTransformString(this.attr("transform"))[0][2];
    

    More info regarding tracking the co-ordinates:

    We will have one more coordinate say updated_x and updated_y, which will be updated in the move method. onFinish/onUp method, we can have the check whether we should update the new position or not. Here, it just asks whether new position should be updated or not and based on our input, it sets the final result.

    Check this fiddle:

    this.start = function() {
        if (this.reference.static) return;
        //this.original_x = Raphael.parseTransformString(this.attr("transform"))[0][1];
        //this.original_y = Raphael.parseTransformString(this.attr("transform"))[0][2];
        this.animate({r: 70, opacity: 0.25}, 500, ">");
        this.updated_x = this.original_x;
        this.updated_y = this.original_y;
    };
    
    this.move = function(dx, dy) {
        //var ts = Raphael.parseTransformString(this.attr("transform"));
        this.updated_x = this.original_x + dx;
        this.updated_y = this.original_y + dy;
        //ts[0][1] = this.original_x + dx; 
        //ts[0][2] = this.original_y + dy; 
        this.attr({transform: 't' + this.updated_x + ',' + this.updated_y});
    };
    
    this.up = function() {
    
        if(confirm("Shall I update the new position??")) {
            this.original_x = this.updated_x;
            this.original_y = this.updated_y;
        }
    
        var transformString = "t" + this.original_x + "," + this.original_y;
        this.attr("transform", transformString);    
        this.attr({fill: "#fff"});
        this.animate({r: 50, opacity: 1}, 500, ">");
    };
    
    0 讨论(0)
  • 2021-01-21 17:49

    I'm not quite sure why that problem happens yet, but I'm wondering if this may be a better solution anyway. Rather than parsing the strings each time, just store the transform and use that.

    I've also switched it to use the transform() method, rather than the attr(transform:..) method. Whilst I think that would normally work, its not quite right logically, as SVG attributes don't take a Raphael transform string, but I assume Raph would intercept that and deal with it (but maybe more error prone).

    Its also worth bearing in mind in a transform string that 't' is a relative transform and 'T' is an absolute transform (I don't think thats the issue as there's no preceding transform, but I was wondering if its also related).

    this.start = function() {
        if (this.reference.static) return;
        this.original_t = this.transform();
        this.animate({r: 70, opacity: 0.25}, 500, ">");
    };
    
    this.move = function(dx, dy) {
        this.transform( this.original_t + 't' + dx + ',' + dy);
    };
    
    this.up = function() {
        this.transform( this.original_t );
        console.log("transformString: " + this.original_t);
        console.log("transformAttrib: " + this.transform());
    
        this.attr({fill: "#fff"});
        this.animate({r: 50, opacity: 1}, 500, ">");
    };
    

    jsfiddle

    0 讨论(0)
  • 2021-01-21 18:08

    Found an interesting fix: you can avoid the situation if you add an epsilon to both this.original_x and this.original_y. The problem seems to disappear if this.original_x and this.original_y are not exactly the same as the starting coordinates. Check out: http://jsfiddle.net/6ozsfdaf/13/

    this.up = function() {
        var ts; 
        this.original_x += 0.0000000001;
        this.original_y += 0.0000000001;
        var transformString = "t" + this.original_x + "," + this.original_y;
        this.attr("transform", transformString);
        console.log("transformString: " + transformString);
        console.log("transformAttrib: " + this.attr("transform"));
    
        this.attr({fill: "#fff"});
        this.animate({r: 50, opacity: 1}, 500, ">");
    };
    

    EDIT Found the problem. In Raphael, Raphael.parseTransformString()'s output is cached and reused. In your move() method, you modify the output of Raphael.parseTransformString(), and Raphael tries to use your modified array when you supply it with the same string. This happens when the first drag() event is registered. You ask it to parse the current place, and then update the output array of arrays with the new location. And then, way later, when this.up() is called, you supply the Raphael.parseTransformString() with the same string. Raphael then uses your modified array of arrays. This is the fixed fiddle: http://jsfiddle.net/6ozsfdaf/16/

    And here is the code (use a new array of arrays to transform when moved each time):

    this.move = function(dx, dy) {
        var ts = [];
        ts.push(new Array('t'));
        ts[0][1] = this.original_x + dx; 
        ts[0][2] = this.original_y + dy; 
        this.attr({transform: ts.toString()});
    };
    
    0 讨论(0)
提交回复
热议问题