使文字脉动并随意改变地方

时间:2015-05-21 02:25:29

标签: javascript jquery html

我正在使用这个插件来获取单词并使它们在屏幕上形成脉动:

首先它们出现并成长,然后它们消失,改变位置并再次出现

工作插件:

+ function($) {

  var Pulsate = function(element) {
    var self = this;
    
    self.element = element;
    self.max = 70;
    self.min = 0;
    self.speed = 500;
    self.first = true;
    self.currentPlace;
    self.possiblePlaces = [
      {
        id: 0,
        top: 150,
        left: 150,
      },
      {
        id: 1,
        top: 250,
        left: 250,
      },
      {
        id: 2,
        top: 350,
        left: 350,
      },
      {
        id: 3,
        top: 250,
        left: 750,
      },
      {
        id: 4,
        top: 450,
        left: 950,
      }
    ];
    
  };
  
  Pulsate.prototype.defineRandomPlace = function() {
    var self = this;
    self.currentPlace = self.possiblePlaces[Math.floor(Math.random() * self.possiblePlaces.length)];
    
    if(!self.possiblePlaces) self.defineRandomPlace;
    
    
    
    self.element.css('top', self.currentPlace.top + 'px');
    self.element.css('left', self.currentPlace.left + 'px');
  };
  
  Pulsate.prototype.animateToZero = function() {
    var self = this;
    
    self.element.animate({
      'fontSize': 0,
      'queue': true
    }, self.speed, function() {
      self.defineRandomPlace();
    });
    
  };
  
  Pulsate.prototype.animateToRandomNumber = function() {
    var self = this;
    
    self.element.animate({
      'fontSize': Math.floor(Math.random() * (70 - 50 + 1) + 50),
      'queue': true
    }, self.speed, function() {
      self.first = false;
      self.start();
    });
  };
  
  Pulsate.prototype.start = function() {
    var self = this;
    
    if (self.first) self.defineRandomPlace();
    if (!self.first) self.animateToZero();
    
    self.animateToRandomNumber();
  };


  $(window).on('load', function() {
    $('[data-pulsate]').each(function() {
      var element = $(this).data('pulsate') || false;
      
      if (element) {
        element = new Pulsate($(this));
        element.start();
      }

    });

  });

}(jQuery);
body {
  background: black;
  color: white;
}

.word {
  position: absolute;
  text-shadow: 0 0 5px rgba(255, 255, 255, 0.9);
  font-size: 0px;
}


.two {
  position: absolute;
  color: white;
  left: 50px;
  top: 50px;
}
div {
  margin-left: 0px;
}
<span class="word" data-pulsate="true">Love</span>
<span class="word" data-pulsate="true">Enjoy</span>
<span class="word" data-pulsate="true">Huggs</span>





<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

如果您注意到我在self.possiblePlaces中定义了单词可以增长的位置,并且如果您注意到动画,有时候一个单词可以在一个地方生长,我的目标就是寻求帮助。我怎么能说两个字永远不会在同一个地方长大?

我试图这样做:

在defineRandomPlace中,我在possiblePlaces数组中选择一个随机对象:

  Pulsate.prototype.defineRandomPlace = function() {
    var self = this;
    self.currentPlace = self.possiblePlaces[Math.floor(Math.random() * self.possiblePlaces.length)];

    if(!self.possiblePlaces) self.defineRandomPlace;


    delete self.possiblePlaces[self.currentPlace.id];
    self.element.css('top', self.currentPlace.top + 'px');
    self.element.css('left', self.currentPlace.left + 'px');
  };

注意删除,首先我克隆所选对象,在我删除它之后但保留在数组中的位置。

动画结束后,我再次将对象放入数组中,然后重新开始:

  Pulsate.prototype.animateToZero = function() {
    var self = this;

    self.element.animate({
      'fontSize': 0,
      'queue': true
    }, self.speed, function() {
      self.possiblePlaces[self.currentPlace.id] = self.currentPlace;
      self.defineRandomPlace();
    });

但它没有任何区别。

谢谢!

笔:http://codepen.io/anon/pen/waooQB

4 个答案:

答案 0 :(得分:8)

在您的示例中,您是从具有五个成员的列表中随机选择的,并且您可以显示三个单独的单词,从而使重叠的可能性相当高。

一种简单的解决方法是选择列表中的第一项,将其从列表中删除,然后每次追加到列表的末尾。由于您在列表中的位置多于从中选择的项目,因此您可以保证不会发生冲突。

  1. 在所有实例之间共享相同的列表3214
  2. 将第一项移出队列,并在每次完成时将其推到最后,而不是在possiblePlaces中随机选择。
  3. 突出显示片段#2:

    defineRandomPlace

    如果你想让它真正随机,你需要从数组中随机选择和删除一个项目,并且在它被使用之前不要将它放回到数组中。您还需要始终确保您拥有的// shift a position off the front self.currentPlace = possiblePlaces.shift(); self.element.css('top', self.currentPlace.top + 'px'); self.element.css('left', self.currentPlace.left + 'px'); // push it back on the end possiblePlaces.push(self.currentPlace); 比您在页面上放置的dom元素多。{1}}。

    像这样:

    possiblePlaces

    请参阅http://codepen.io/anon/pen/bdBBPE

答案 1 :(得分:4)

我的决定是将页面划分为虚数行并禁止同一行中的多个单词。请检查一下。

注意:由于代码当前不支持重新计算文档大小调整的行数,因此无法正确显示整页视图。点击“重新加载框架”或尝试JSFiddle或smth。

var pulsar = {
  // Delay between words appearance
  delay: 400,
  // Word animation do not really depend on pulsar.delay,
  // but if you set pulsar.delay small and wordAnimationDuration long
  // some words will skip their turns. Try 1, 2, 3...
  wordAnimationDuration: 400 * 3,
  // Depending on maximum font size of words we calculate the number of rows
  // to which the window can be divided
  maxFontSize: 40,
  start: function () {
    this.computeRows();
    this.fillWords();
    this.animate();
  },
  // Calculate the height or row and store each row's properties in pulsar.rows
  computeRows: function () {
    var height = document.body.parentNode.clientHeight;
    var rowsCount = Math.floor(height/this.maxFontSize);
    this.rows = [];
    for (var i = 0; i < rowsCount; i++) {
      this.rows.push({
        index: i,
        isBusy: false
      });   
    }
  },
  // Store Word instances in pulsar.words
  fillWords: function () {
    this.words = [];
    var words = document.querySelectorAll('[data-pulsate="true"]');
    for (var i = 0; i < words.length; i++) {
      this.words.push(new Word(words[i], this.wordAnimationDuration, this.maxFontSize));
    }
  },
  // When it comes time to  animate another word we need to know which row to move it in
  // this random row should be empty at the moment
  getAnyEmptyRowIndex: function () {
    var emptyRows = this.rows.filter(function(row) {
      return !row.isBusy;
    });
    if (emptyRows.length == 0) {
      return -1;
    }
    var index = emptyRows[Math.floor(Math.random() * emptyRows.length)].index;
    this.rows[index].isBusy = true;
    return index;
  },
  // Here we manipulate words in order of pulsar.words array
  animate: function () {
    var self = this;
    this.interval = setInterval(function() {
      var ri = self.getAnyEmptyRowIndex();
      if (ri >= 0) {
        self.words.push(self.words.shift());
        self.words[0].animate(ri, function () {
          self.rows[ri].isBusy = false;
        });
      }
    }, this.delay);
  }
}

function Word (span, duration, maxFontSize) {
  this.span = span;
  this.inAction = false;
  this.duration = duration;
  this.maxFontSize = maxFontSize;
}

/** 
  * @row {Numer} is a number of imaginary row to place the word into
  * @callback {Function} to call on animation end
  */
Word.prototype.animate = function (row, callback) {
  var self = this;
  // Skip turn if the word is still busy in previous animation
  if (self.inAction) {
    return;   
  }
  var start = null,
      dur = self.duration,
      mfs = self.maxFontSize,
      top = row * mfs,
      // Random left offset (in %)
      left = Math.floor(Math.random() * 90),
      // Vary then font size within half-max size and max size
      fs = mfs - Math.floor(Math.random() * mfs / 2);

  self.inAction = true;
  self.span.style.top = top + 'px';
  self.span.style.left = left + '%';

  function step (timestamp) {
    if (!start) start = timestamp;
    var progress = timestamp - start;
    // Calculate the factor that will change from 0 to 1, then from 1 to 0 during the animation process
    var factor = 1 - Math.sqrt(Math.pow(2 * Math.min(progress, dur) / dur - 1, 2));
    self.span.style.fontSize = fs * factor + 'px';
    if (progress < dur) {
      window.requestAnimationFrame(step);
    }
    else {
      self.inAction = false;
      callback();
    }
  }
  window.requestAnimationFrame(step);
}

pulsar.start();
body {
    background: black;
    color: white;
}

.word {
    position: absolute;
    text-shadow: 0 0 5px rgba(255, 255, 255, 0.9);
    font-size: 0px;
    /* To make height of the .word to equal it's font size */
    line-height: 1;
}
<span class="word" data-pulsate="true">Love</span>
<span class="word" data-pulsate="true">Enjoy</span>
<span class="word" data-pulsate="true">Huggs</span>
<span class="word" data-pulsate="true">Peace</span>

答案 2 :(得分:2)

我更新了你的插件构造函数。注意变量Pulsate.possiblePlaces,我已经通过这种方式更改了变量声明,以便能够为插件的所有Object实例共享变量数据。

var Pulsate = function(element) {
    var self = this;

    self.element = element;
    self.max = 70;
    self.min = 0;
    self.speed = 500;
    self.first = true;
    self.currentPlace;
    Pulsate.possiblePlaces = [
        {
            id: 0,
            top: 150,
            left: 150,
        },
        {
            id: 1,
            top: 250,
            left: 250,
        },
        {
            id: 2,
            top: 350,
            left: 350,
        },
        {
            id: 3,
            top: 250,
            left: 750,
        },
        {
            id: 4,
            top: 450,
            left: 950,
        }
    ];

};

我将occupied属性添加到可能的位置以识别已经占用的属性。如果randomed currentPlace已被占用,请再次搜索随机位置。

Pulsate.prototype.defineRandomPlace = function() {
    var self = this;
    self.currentPlace = Pulsate.possiblePlaces[Math.floor(Math.random() * Pulsate.possiblePlaces.length)];

    if(!Pulsate.possiblePlaces) self.defineRandomPlace;


    if (!self.currentPlace.occupied) {
        self.currentPlace.occupied = true;
        self.element.css('top', self.currentPlace.top + 'px');
        self.element.css('left', self.currentPlace.left + 'px');
    } else {
        self.defineRandomPlace();
    }
};

每次隐藏元素时,请将occupied属性设置为false

Pulsate.prototype.animateToZero = function() {
    var self = this;

    self.element.animate({
        'fontSize': 0,
        'queue': true
    }, self.speed, function() {
        self.currentPlace.occupied = false;
        self.defineRandomPlace();
    });

 };

答案 3 :(得分:2)

小提示f = 0.5px x = 100px t = 0.5s

x / f = 200
200/2 * t * 0.5 = f(shrink->expand until 100px square) per 0.5 seconds