获取 CSS 中指定的对象位置以在 jQuery 中修改

get object position as specified in CSS to modify in jQuery

第一个问题,如果我 could/should 想问更多 succinctly/clearly...

,请告诉我

我正在研究一个实验脚本,该脚本使具有给定 class 的物体随着时间的推移振动强度增加。我正在使用 jRumble 作为基础。我的脚本需要获取要振动的对象的初始 CSS 位置,然后添加修改变量。我一开始是这样设置的:

$this.animate({
    'left': parseFloat($this.css( "left" )) + rx + 'px',

在 Chrome 中效果很好,但 Safari 和 iOS return 的值不同。这解释了问题:jquery $('selector').css('top') returns different values for IE, firefox and Chrome,所以我改用 .offset:

offset = $(".offreg").offset();

...

'left': offset.left + rx + 'px', 

但这是有问题的,因为脚本迭代-- .offset return每次都是当前位置而不是初始位置。我尝试将 var 放在迭代部分之外,但这(显然)不起作用,因为它不再与 rumble 脚本的 "this" 相关联。然后将 var 设置为第一个元素的值 class .offreg.

页面本身在这里:http://sallymaier.github.io/off-register/ 我将恢复到在 Chrome 中运行的最后一个版本。我的 github 是公开的,所以你可以看到我在那里制造的混乱。

下面Chrome中的完整脚本:

var offRegister = function() {

    if (!($ = window.jQuery)) { // see if jQuery is already called, if not, calling script
      script = document.createElement( 'script' );
      script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js'; 
      script.onload=runRumbler;
      document.body.appendChild(script);
    } 
    else {
      runRumbler();
    }

    function runRumbler() {      
        $(document).ready(function(){

            var count = 0;

            $(function addone(){
                count = count+1;

                (function($) {
                  $.fn.jrumble = function(options){  // jRumble by Jack Rugile. http://jackrugile.com/jrumble/

                    /*========================================================*/
                    /* Options
                    /*========================================================*/
                    var defaults = {
                      x: count/5,
                      y: count/5,
                      rotation: 0,
                      speed: 200,
                      opacity: false,
                      opacityMin: .5
                    },
                    opt = $.extend(defaults, options);  

                    return this.each(function(){

                      /*========================================================*/
                      /* Variables
                      /*========================================================*/
                      var $this = $(this),        
                        x = opt.x*2,
                        y = opt.y*2,
                        rot = opt.rotation*2,
                        speed = (opt.speed === 0) ? 1 : opt.speed,      
                        opac = opt.opacity,
                        opacm = opt.opacityMin,
                        inline,
                        interval;

                      /*========================================================*/
                      /* Rumble Function
                      /*========================================================*/    
                      var rumbler = function(){       
                        var rx = Math.floor(Math.random() * (x+1)) -x/2,
                            ry = Math.floor(Math.random() * (y+1)) -y/2,
                            rrot = Math.floor(Math.random() * (rot+1)) -rot/2,
                            ropac = opac ? Math.random() + opacm : 1;

                        /*========================================================*/
                        /* Ensure Movement From Original Position
                        /*========================================================*/        
                        rx = (rx === 0 && x !== 0) ? ((Math.random() < .5) ? 1 : -1) : rx;
                        ry = (ry === 0 && y !== 0) ? ((Math.random() < .5) ? 1 : -1) : ry;  

                        /*========================================================*/
                        /* Check Inline
                        /*========================================================*/
                        if($this.css('display') === 'inline'){
                          inline = true;
                          $this.css('display', 'inline-block');
                        }

                        /*========================================================*/
                        /* Rumble Element
                        /*========================================================*/      
                        $this.animate({
                          'left': parseFloat($this.css( "left" )) + rx + 'px', // move from declared position
                          'top': parseFloat($this.css( "top" )) + ry+'px',
                          '-ms-filter':'progid:DXImageTransform.Microsoft.Alpha(Opacity='+ropac*100+')',
                          'filter':'alpha(opacity='+ropac*100+')',          
                          '-moz-opacity':ropac,         
                          '-khtml-opacity':ropac,         
                          'opacity':ropac,
                          '-webkit-transform':'rotate('+rrot+'deg)', 
                          '-moz-transform':'rotate('+rrot+'deg)', 
                          '-ms-transform':'rotate('+rrot+'deg)',
                          '-o-transform':'rotate('+rrot+'deg)', 
                          'transform':'rotate('+rrot+'deg)'
                        });

                      }; /* close rumble function */

                      /*========================================================*/
                      /* Rumble CSS Reset
                      /*========================================================*/
                      var reset = {
                        'left':0,
                        'top':0,
                        '-ms-filter':'progid:DXImageTransform.Microsoft.Alpha(Opacity=100)',
                        'filter':'alpha(opacity=100)',          
                        '-moz-opacity':1,         
                        '-khtml-opacity':1,         
                        'opacity':1,
                        '-webkit-transform':'rotate(0deg)',
                        '-moz-transform':'rotate(0deg)',
                        '-ms-transform':'rotate(0deg)',
                        '-o-transform':'rotate(0deg)',
                        'transform':'rotate(0deg)'
                      };

                      /*========================================================*/
                      /* Rumble Start/Stop Trigger
                      /*========================================================*/
                        $this.bind({
                        'startRumble': function(e){
                          e.stopPropagation();
                          clearInterval(interval);
                          interval = setInterval(rumbler, speed)
                        },
                        'stopRumble': function(e){
                          e.stopPropagation();
                          clearInterval(interval);
                          if(inline){
                            $this.css('display', 'inline');
                          }
                          $this.css(reset);
                        }
                      });   

                    });// End return this.each
                  };// End $.fn.jrumble

                })(jQuery);

                /*===============================================================*/
                /* Specify selector to vibrate below. 
                /* For bookmarklet, 'div' will vibrate all elements, 
                /* in plugin this can be specifically targeted to a class or id.
                /*===============================================================*/

                $('.offreg').jrumble();    
                $('.offreg').trigger('startRumble');

             setTimeout(addone, 1000); // how many seconds to wait before adding to count, increasing vibration

            }); // end addone()

         });
    };
  };

offRegister();

最近几分钟我一直在研究这个源代码,在我看来问题源于对隆隆声元素本身使用 position: absolute。在 jRumble 文档中 http://jackrugile.com/jrumble/#documentation 它说 'For rumble elements that are position fixed/absolute, they should instead be wrapped in an element that is fixed/absolute'.

因此,如果您将容器元素设置为 position: absolute,然后将所有内部 div 相对于容器定位,您将不再需要更改 jRumble 源代码并在每次迭代时重新定义插件以进行更改默认位置或计算每个元素的偏移量 - 您所要做的就是在 jRumble 调用本身中增加 xy 值。

下面的代码是未经测试的,但我想你想要更接近这个的东西(同样,这一切都取决于 .offreg 元素是 position: relative):

$(document).ready(function(){
  var count = 0;

  function addone(){
    count++;
    $('.offreg').jrumble({
      x: count,
      y: count,
      rotation: 1
    });
    $('.offreg').trigger('startRumble');

    setTimeout(addone, 1000);
  }
});

我喜欢 Sean 的回避需要添加代码来覆盖 $.fn.jrumble 的回答,这会创建一个脆弱的维护点并使 $.fn.jrumble 在该代码块之外无法使用(因为它取决于在变量 "count").

对于变量范围的直接问题,如果您仍然需要解决该问题,我建议将 $.fn.jrumble 的重新定义移出 addone(),然后确定一个变量的范围, "offset",在所说的重定义之外。然后在调用 $this.animate() 时引用该变量。代码在下面,但同样,肖恩的回答应该使这不必要。

var offRegister = function() {
    if (!($ = window.jQuery)) { // see if jQuery is already called, if not, calling script
        script = document.createElement( 'script' );
        script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js'; 
        script.onload=runRumbler;
        document.body.appendChild(script);
    } 
    else {
        runRumbler();
    }
};
function runRumbler() {
    $(document).ready(function(){
        var count = 0;
        var offset;
        function addone() {
            ...
            $('.offreg').jrumble();    
            $('.offreg').trigger('startRumble');
            offset = $('.offreg').offset();
            setTimeout(addone, 1000); // how many seconds to wait before adding to 
        }
        (function($){
            $.fn.jrumble = function(options){
                ...
                $this.animate({
                      'left': parseFloat(offset) + rx + 'px',
                      ...
                });
                ...
            };
        )(jQuery);
        ...

}
offRegister();

另一个建议:让整个事情成为一个匿名函数。而不是:

var offRegister = function() {
    ...
}
offRegister();

尝试:

(function(){
    ...
})();

这样您就不会在全局命名空间中粘贴变量 "offRegister"。在这种情况下,这样做不是问题,但如果不引入新的全局变量,您想要在别处重用的一般代码会更干净。