Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Нужна помощь с формулой для анимации (https://javascript.ru/forum/dom-window/67975-nuzhna-pomoshh-s-formulojj-dlya-animacii.html)

Diphenyl Oxalate 18.03.2017 14:16

Нужна помощь с формулой для анимации
 
Надо разрезать картинку на NxN ячеек, и у каждой ячейки изменять opacity. Причём чем ближе к нижнему правому углу, тем сильнее изменять. Получается такой эффект, будто картинка сворачивается в угол.

Скрытие работает нормально, а вот с раскрытием какая-то дичь.
Помогите сообразить, какая формула нужна для opacity!

<img height="341" width="512" id="main" src="http://farm9.staticflickr.com/8228/8503485139_0b55e2a857_b.jpg" />

<script type="text/javascript">

(function () {

"use strict";

function dissolve(elem, options) {
	options = options || {};
	options.duration = options.duration || 500;
	options.tiles = options.tiles || 10;

	var pos = elem.getBoundingClientRect();
	var top = pos.top;
	var left = pos.left;
	var tileWidth = Math.round(elem.clientWidth / options.tiles);
	var tileHeight = Math.round(elem.clientHeight / options.tiles);
	var allTiles = [];
	var show = options.action == "show";

	for (var i = j = 0; i < options.tiles; i++) {
		for (var j = 0; j < options.tiles; j++) {
			var tile = document.createElement("DIV");
			document.body.appendChild(tile);
			tile.style.position = "absolute";
			tile.style.overflow = "hidden";
			tile.style.width = tileWidth + "px";
			tile.style.height = tileHeight + "px";
			tile.style.top = (top + i * tileHeight) + "px"; 
			tile.style.left = (left + j * tileWidth) + "px";
			tile.style.opacity = show ? 0 : 1;

			var tileContent = elem.cloneNode(true);
			tileContent.style.position = "static";
			tile.appendChild(tileContent);
			tileContent.style.marginLeft = (-j * tileWidth) + "px";
			tileContent.style.marginTop = (-i * tileHeight) + "px";
			tileContent.style.visibility = "visible";

			j == 0 ? allTiles.push([tile]) : allTiles[i].push(tile);
		}
	}

	var start = +new Date();
	fx();
	function fx() {
		var m = (+new Date() - start) / options.duration;
		if (m > 1) m = 1;
		if (m < 1) setTimeout(fx, 17);
		for (var i = j = 0; i < options.tiles; i++) {
			for (var j = 0; j < options.tiles; j++) {
				var d =  m * options.tiles / Math.min(i + 1, j + 1);
				if (d < 0) d = 0; if (d > 1) d = 1;
				allTiles[i][j].style.opacity = show ? d : 1 - d;
			}
		}
	}

	setTimeout(function () {
		for (var i = j = 0; i < options.tiles; i++) {
			for (var j = 0; j < options.tiles; j++) {
				document.body.removeChild(allTiles[i][j]);
			}
		}
	}, options.duration);

	if (show) {
		setTimeout(function () {
			elem.style.visibility = "visible";
		}, options.duration);
	} else {
		elem.style.visibility = "hidden";
	}
}

window.Dissolve = {
	show : function (elem, tiles, duration) {
		dissolve(elem, {
			duration : duration, tiles : tiles, action : "show"
		});
	},
	hide : function (elem, tiles, duration) {
		dissolve(elem, {
			duration : duration, tiles : tiles, action : "hide"
		});
	}
};

})();

var toggler = true;
document.onclick = function () {
	Dissolve[toggler ? "hide" : "show"]( document.getElementById("main") );
	toggler = !toggler;
};
		</script>


Сама формула в 53 и 55 строчках, проблема именно там.

рони 18.03.2017 17:53

алгоритм волна
 
Diphenyl Oxalate,
может чем поможет, кликнуть по любой ячейке, дождаться конца анимации, затем снова кликнуть по любой ячейке.
<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  *{
    padding: 0;
    margin: 0;
  }

  .cell {
    text-align: center;
     float: left;
     height: 23px;
     width: 23px;
     border: #0000CD 1px solid;
     background-color: #FFEBCD;
     font-size: 12px;
     -webkit-transition: all .5s ease-in-out;
     -moz-transition: all .5s ease-in-out;
     -o-transition: all .5s ease-in-out;
     transition: all .5s ease-in-out;
  }
  #matrix{
    display: inline-block;
    margin: 50px auto;
  }
  .red{
    border-radius: 4px;
    background:  #FF0F0F;
  }
 .yellow{
     background: #FFFF00;
   }
  .green{
    background: #008000;
  }
  .blue{
    background: #0000FF
  }
  </style>

  <script>
window.addEventListener('DOMContentLoaded', function() {
       var matrix = document.getElementById('matrix'),
            l = (Math.random()*15|0) + 10 //ширина  можно менять
            t = (Math.random()*10|0) + 10, //высота
            n = l * t;

        function createMatrix() {
            var w;
            for (var i = 0; i < n; i++) {
                var div = document.createElement('div');
                div.className = 'cell';
                div.dataset.index = i;
                matrix.appendChild(div);
                if (i == l - 1) {
                    w = matrix.offsetWidth + 1;
                }
            }
            matrix.style.width = w + 'px';
            matrix.style.display = 'block'
        }

        function chec(indx, size) {
            var s = [], m = [],
                x = indx % l,
                y = indx / l | 0;
            size = size || 1;
            for (var i = y - size; i <= y + size; i++) {
                for (var k = x - size; k <= x + size; k++) {
                    var num = k + i * l, max = Math.max(Math.abs(i-y),Math.abs(k-x));
                    i > -1 && i < t && k > -1 && k < l && num < (i * l + l) && (s.push(num),m.push(max) )

                }
            }
            return {s : s, m : m}
        }

     createMatrix(); //создание поля игры
     var divs = [].slice.call(document.querySelectorAll('.cell'),0); //массив клеток с которым будем работать

     matrix.addEventListener('click', function (event) {
     var el = event.target, cls = el.classList;
    if(cls && cls.contains('cell')) {
       var index = el.dataset.index;
       var arr = chec(index, Math.max(t,l));
       divs.forEach(function(el,i) {
       var k = arr.s.indexOf(i);
       var m = arr.m[k];
           m *= .25;
           el.style.transitionDelay = m + "s";
           el.classList.contains('red') ? el.classList.remove('red'): el.classList.add('red')
       });
     }

  });

    });
  </script>
</head>

<body>
<div id="matrix" ></div>

</body>
</html>


другой пример использования

Diphenyl Oxalate 18.03.2017 21:23

рони, спасибо, попробую применить.

Тут ещё один проблемный скрипт.
Демо
Сворачивает элемент в угол и потом разворачивает его, если нужно.
Схема работы: оборачиваем картинку в див с overflow:hidden, меняем его размеры, координаты, сдвигаем картинку маргинами.

Проблемы две:

1) При движении вниз (corner = 3, 4, 5) картинка заметно дёргается. Хотя принцип вычислений один и тот же, хз откуда эти лишние пиксели берутся. Причём только при движении вниз!
Сначала картинка просто опускалась ниже и ниже, кое-что изменил в коде - добавил unwrapping, т.е. при окончании анимации выкидываем картинку из div-обёртки, а сам див удаляем. Таким образом, картинка встаёт на изначальное место, сдвиги не накапливаются, но картинку всё равно заметно дёргает.

2) Если картинке поставить margin, top, left, то скрипт ломается по понятным причинам.
Пробовал делать переменные типа offsetTop и offsetLeft, суммировать туда значения margin и top/left, и прибавлять всё это к координатам div-обёртки, но это не помогло.

рони 18.03.2017 22:05

Цитата:

Сообщение от Diphenyl Oxalate
картинка заметно дёргается

<style type="text/css">
    p{
      margin: 0;
      padding: 0;
    }
   div img{
      display: block;
   }

    </style>


Часовой пояс GMT +3, время: 02:46.