jquery animate for element attributes not style
Asked Answered
T

5

10

ASAIK jquery animate function accepts style properties only. but i want to animate the attributes of an element. consider a SVG element rectangle

<svg>
<rect id="rect1" x=10 y=20 width="100px" height="100px">
</svg>

i want to animate the rectangle element attribute "x" and "y" something like below

$("#rect1").animate({
    x: 30,
    y: 40
  }, 1500 );

but it is not correct way because animate function affects style not attribute of an element.

i knew so many custom plugin is there like raphel.js.

http://raphaeljs.com/

but i don't want to use custom plugin to do this. i want to do this simply in jquery.animate function.

is this possible ?

Thanks,

Siva

Tameika answered 28/6, 2013 at 8:47 Comment(3)
is x and y the position of the element?Brittani
@Brittani yes.it is position of rectangle elementTameika
possible duplicate of jquery animation of specific attributesFriedly
P
6

just animate the old fashioned way:

you can call animate in a jquery like fashion.

http://jsfiddle.net/wVv9P/7/

function animate($el, attrs, speed) {

    // duration in ms
    speed = speed || 400;

    var start = {}, // object to store initial state of attributes
        timeout = 20, // interval between rendering loop in ms
        steps = Math.floor(speed/timeout), // number of cycles required
        cycles = steps; // counter for cycles left

    // populate the object with the initial state
    $.each(attrs, function(k,v) {
        start[k] = $el.attr(k);
    });

    (function loop() {
        $.each(attrs, function(k,v) {  // cycle each attribute
            var pst = (v - start[k])/steps;  // how much to add at each step
            $el.attr(k, function(i, old) {
                return +old + pst;  // add value do the old one
            });
        });

        if (--cycles) // call the loop if counter is not exhausted
            setTimeout(loop, timeout);
        else // otherwise set final state to avoid floating point values
            $el.attr(attrs);

    })(); // start the loop
}

$('button').on('click', function() {       
    animate(
        $('#rect1'), // target jQuery element
        { x:100, y:300, width:50, height:100 }, // target attributes
        2000 // optional duration in ms, defaults to 400
    );
});
Peddada answered 28/6, 2013 at 9:19 Comment(1)
can you please explain more in details. what is steps,speed and timeout function ? what is st here ? could you please more specificTameika
B
1

I would try something like this

<svg>
    <rect class="myElement" id="rect1" x="10" y="20" width="100px" height="100px">
</svg>

in the script :

var myElemX = $('.myElement').attr('x');
var myElemY = $('.myElement').attr('y');
$("#rect1").animate({
    left: myElemX+'px',
    top:  myElemY+'px'
}, 1500 );
Brittani answered 28/6, 2013 at 8:59 Comment(1)
thanks. if am using left and top means there is still x and y attribute is there in element. then what position element takes ?Tameika
T
1

Alright all answers here are either specific to SVG or reimplement the .animate() jQuery call, I found a way to use the jQuery call without running into the problem that the attribute gets reset to 0 when the animation starts:

Lets say we want to animate the width and height attribute of an img tag element with id image. To animate it from its current value to 300 we could do this:

var animationDiv= $("<div></div>"); //we don't add this div to the DOM
var image= $("img#image");
//could use any property besides "top" and "left", but the value must be valid, that means concatenating a "px" to numerical attributes if they don't have it already (and removing them in the step callback if they do)
animationDiv.css("left", image.attr("width")); 
animationDiv.css("top", image.attr("height")); 
animationDiv.animate(
    {
        left: 300,
        top: 300
    },
    {
        duration: 2500,
        step: function(value, properties) {
            if (properties.prop == "left")
                 image.attr("width", value + "px")
            else
                 image.attr("height", value + "px")
        }
    }
)

In this approach we use a div that is not inside the DOM and animate values in it, we then use the div CSS values to animate our element. Not very pretty but gets the job done, if you need to stop the animation you can call .stop() on animationDiv.

jsfiddle

Thermal answered 31/12, 2014 at 10:28 Comment(1)
Wouldn't it have been better just to vote to close the question as a duplicate of the other question you just answered with this answer?Friedly
A
0

I like the Hoffmann approach, but i think is more elegant without creating a virtual dom object.

This is my coffeescript snippet

$rects.each ->
  that = @
  $({width: 0}).animate
  width: parseInt($(@).attr('width'))
  ,
  duration: 2000
  easing: 'easeIn'
  step: ->
    $(that).attr 'width', Math.round(@.width)
  done: ->
    console.log 'Done'

which compiles into

return $rects.each(function() {
  var that;
  that = this;
  return $({
    width: 0
  }).animate({
    width: parseInt($(this).attr('width'))
  }, {
    duration: 1000,
    easing: 'easeIn',
    step: function() {
      return $(that).attr('width', Math.round(this.width));
    },
    done: function() {
      return console.log('Done');
    }
  });
});
Accountant answered 7/5, 2015 at 10:28 Comment(0)
L
-1

this may fits you simple

$("your div id").css("position", "absolute").animate({
    left: 159,
    top:  430
});
Lunar answered 22/12, 2013 at 12:31 Comment(1)
As far as I know that way "top" and "left" will be css attributes. The question explicitly say «element attributes not style». If I'm wrong I'll remove the down-voteAccountant

© 2022 - 2024 — McMap. All rights reserved.