Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Вопрос каруселяписателям (https://javascript.ru/forum/dom-window/55796-vopros-karuselyapisatelyam.html)

kostyanet 14.05.2015 16:45

Вопрос каруселяписателям
 
Это вторая попытка, теперь покороче, но остается надежда что есть научный способ, функция, а не функционал.

Надо чтобы анимация дойдя до последней картинки пошла вспять. То есть 1 2 3 4 3 2 1 2 3 4... и так далее.

Перематывать с конца до начала портянку в несколько экранов - полная лажа, поэтому хочу сделать туда-сюда.

Код (основная часть). Подвижный элемент - m

total=items.length,
	max=total-1,
	curr=0,
	step=500,
	to,
	delay=3000,
	
	move=function(c){
		m.style.top=(-c*step)+'px';
	},
	move_n=function(e){
		if(curr<max)
			move(++curr);
		if(curr>=max)
			f=move_p;
	},
	move_p=function(e){
		if(curr>0)
			move(--curr);
		if(curr<=0)
			f=move_n;
	},
	go=function(e){
		to=W.setTimeout(f,delay);
	},
	f=move_n;
	
	m.addEventListener('transitionend',go);

	go();


Суть как видите такова: я заменяю функцию в зависимости от достижений. Иначе никак не получается, или получаются несусветные проверки и куча лишних переменных.

Есть более научный способ?

рони 14.05.2015 17:09

kostyanet,
где-то на форуме делал по иному но суть таже
<script>
function foo(a) {
    var b = Array(a + 1).join("1").split("").map(function(b, a) {
            return a + 1
        }),
        b = b.concat(b.slice(1, a - 1).reverse());
    return function() {
        var a = b.shift();
        b.push(a);
        return a
    }
};
var x = foo(5)
for (var i=0; i<50; i++)  {document.write(x()+ ' ')}
</script>

рони 14.05.2015 17:32

:write: вариант по короче )))
<script>
function foo(c) {
    var a = 2,
        b = !1;
    return function() {
        b ? a++ : a--;
        if (a == c || 1 == a) b = !b;
        return a
    }
};
var x = foo(5)
for (var i=0; i<50; i++)  {document.write(x()+ ' ')}
</script>

laimas 14.05.2015 17:40

Можно сдвигать элементы массива по кольцу, а сдвигаемые изображения определяются всегда его первыми двумя элементами.

kostyanet 14.05.2015 18:38

Логику я понял, доходим до конца, переходим на начало, прежде развернув массив наоборот. Не могу применить к геометрии смещения опупенного блока на Х пикселов по вертикали.

kostyanet 14.05.2015 18:41

Цитата:

Сообщение от laimas
Можно сдвигать элементы массива по кольцу,

Это как? Смотрите, там портянка высотой с десятиэтажный дом. На каждом клике-шаге она просто перемещается на Х пикселов под действием силы css. Внутри портянки - блоки с версткой, то есть картинки и хтмл и все такое.

Доходим до конца - дальше просто пусто. Надо или втыкать 0 - и значит вся эта башня кааак рухнет вниз перед лицом товарищей, или просто опускать ее по этажам в обратном порядке.

kostyanet 14.05.2015 18:44

Теоретически можно отключить transition на время падения, но я не знаю как это сделать в js. А без транзишна таскать js'ом черевато. Но главное что это все - баян, там ничего такого сложного не должно быть, тупая витрина.

Вообще все крутилки тупейшая хрень. Нормальный человек и сам полистает если там реально ему интересно и есть нормальные кнопки.

К тому же ручная листалка может вообще не иметь конца-края. Так например сделано на сайте houzz.com - я как-то задался целью домотать до конца - минут 5 щелкал - не видать. Оно просто грузится и грузится с хвоста анонсов, которых за годы там небось уже вагонами.

laimas 14.05.2015 19:16

<script>
var a = [0, 1, 2, 3, 4, 5];
function sdir(d) {
    d==1 ? a.unshift(a.pop()) :  a.push(a.shift());
    document.getElementById('s').innerHTML = a.join(', ');
}
</script>
<button onclick="sdir(1)">&laquo;</button> <button onclick="sdir(-1)">&raquo;</button>
<div id="s">0, 1, 2, 3, 4, 5</div>

Умножая аргумент переданный в функцию на известную ширину окна слайдера, можно просто получать как параметр для анимации, так и смещение соседнего изображения, которое также анимируется.

kostyanet 15.05.2015 20:12

Ниче не могу понять. Когда нажимаются кнопки там просто - дошел до максимума или 0 - соответствующая не нажимается, действие пропускается.

Но когда работает анимация, она умеет "нажимать" только одну кнопку, например "вперед". Потому что вместо 2-х действий - остается 1 - по событию таймера.

Попытка проверить докуда дошла анимация и перейти на другую ветку проверки не увенчается, просто потому что с другой ветки анимация сразу же попадает на предыдщую, поскольку следующая поменяла условие и оно теперь удовлетворяет предыдущую. Выглядит так: дошлепали до края, вернулись назад и начали туда-сюда мотать 1 кадр.

То есть если моделировать, то должна быть 1 кнопка, каждое нажатие на которую дает инкремент до максимума, а потом декремент до 0. Так можно без подмены функций?

kostyanet 15.05.2015 20:18

Например вот тут две такие хреновины http://interior-exclusive.ru/ которые запускаются микроскопической кнопочкой посредине. Но там глючит и я даже смотреть не хочу как сделал, для другого сайта надо по-другому, и чтоб не глючило. То есть я написал, все работает без глюков, но коды смешные.

Например произвольный доступ (с пуговиц) вот такой

go_to=function(e){
		if(e.target.nodeName='I'){
			curr=parseInt(e.target.getAttribute('data-index'));
			if(f===move_p)
				++curr;
			else
				--curr;
			f();
		}
	};


потому что все идет через те функции, а они сами инкре-декрементируют и я ничего лучше не придумал как ввести предыскажения.

Там же еще такая задача, что кнопка которую уже нельзя нажать - должна исчезнуть. А чтобы она исчезла после последнего возможного нажатия, а не когда по ней щелкнули и выяснилось уже некуда - надо сразу проверять после смещения еще раз.

kostyanet 15.05.2015 20:30

Кстати, как осто3.14здел этот NaN, просто капец. Когда на php я пишу if($v = (int)$v) то просто спокойно иду спать, а если на жисе написать if(v=parseInt(v)) то присняся кошмары. Зацените мля:

v={o:5};

parseInt(('n' in v));
/*
NaN
*/


Почему мля нельзя выдать 0 на фолс и 1 на тру?

Это я вспомнил когда увидел получение индекса из элемента в куске выше.

ЗЫ Ну то есть когда числа пришедшие с клиента типируем мы же так и пишем (int)$_GET['num'], да? Прикольно было бы получить тру и одновременно вместо числа - целое слово из трех букаф, блеать.

kostyanet 15.05.2015 20:39

А, блин, почему вспомнил, фильтры так устроены - включенные имеют минус id. То есть в одном параметре передается что включено и что не включено. Элементарная вещь, а на жисе геморрой. Написал-стер написал-стер, жопа какая-то, потом думаю да идите вы нахер со своими числами и написал унцию кода вычисления абсолютной величины:

abs=function(el){
		var v = atv(el);
		if(v)
			return v.replace('-','');
	},


Вот так нах, без Math'а :)

Vlasenko Fedor 15.05.2015 23:31

Туда сюда обратно :haha:
это я учился
<style>
input {
  float: left;
  width:120px;
}
#result {
  width: 240px;
  height: 90px;
  background-color: red;
  color: #fff;
  font-size: 80px;
  text-align: center;
}
#buttons {
  width:240px;
}
</style>
<div id="result"></div>
<div id="buttons">
    <input type="button" value="Previous" id="prev" />
      <input type="button" value="Next" id="next" />
      <input type="button" value="Play" id="play" />
      <input type="button" value="Pause" id="pause" />
</div>
<script>
function nav(max) {
  this.max = max;
  this.current = this.current || -1;
  this.next = function () {
    this.current = this.current < this.max - 1 ? this.current + 1 : 0;
    return this.current;
  };
  this.prev = function () {
    this.current = this.current > 0 ? this.current - 1 : this.max - 1;
    return this.current;
  };
};
 
var animTimer, slider = new nav(8);
function sliderPlay() {
  animTimer = setInterval(function () {
    result.innerHTML = slider.next();
  }, 1000);
};
next.onclick = function () {
  result.innerHTML = slider.next();
};
prev.onclick = function () {
  result.innerHTML = slider.prev();
};
play.onclick = function () {
  if (animTimer) return;
  sliderPlay();
};
pause.onclick = function () {
  clearInterval(animTimer);
  animTimer = 0;
};
window.onload = function () {
  sliderPlay();
};
</script>

kostyanet 16.05.2015 06:31

Так у вас после 7 - идет 0 в режиме play

kostyanet 16.05.2015 06:34

Вообще можно без ++инкрементов и проверок if else прибавлять и вычитать в заданном диапазоне, но для данной задачи ничего оно не дает

var max = 10, curr =0;

В кнопке далее

curr = Math.max(curr+1,max);

назад

curr = Math.max(curr-1,0);

Сформулирую задачу предельно конкретно. По одному событию колебаться от 0 до Х и обратно.

рони 16.05.2015 12:21

Цитата:

Сообщение от kostyanet
По одному событию колебаться от 0 до Х и обратно

а чем например 3 пост неустраивает x() выдаёт как раз от 0 и обратно

Vlasenko Fedor 16.05.2015 13:55

Цитата:

Сообщение от kostyanet
Сформулирую задачу предельно конкретно

var obj = {
    min: 0,
    max: 0,
    __reverce: 1,
    __position: 0,
    get cur() {
        this.__position += this.__reverce
        if (this.__position == this.max || this.__position == this.min) this.__reverce *= -1;
        return this.__position;

    },
    set cur(arg) {
        this.__position = arg;
    }
};
obj.max = 10, obj.cur = 8;
console.log(obj.cur);
console.log(obj.cur);
console.log(obj.cur);

kostyanet 17.05.2015 16:57

Цитата:

Сообщение от рони
а чем например 3 пост неустраивает x() выдаёт как раз от 0 и обратно

Да, просмотрел, перед ним был про массивы, я подумал следующий "по проще" просто попроще. Щас попробую понять как прикрутить. Это вообще второе больное место после регов - циклы - у меня. Еще с бейсика каждый раз задумывался что поставить в for > = или Length-1.

kostyanet 17.05.2015 17:23

Точно, я так и думал, что нужно просто менять знак у инкремента, но не догонял что нужны обе проверки одновременно, а знак просто переключается по тру в обоих. Ну то есть когда написал их обе, то получилось что и там и там i=-i Причем начал с примера Рони с третьего поста, а товарищ Poznakomlus то самое и предложил. В общем спасибо господа, получается все очень просто (на что я и надеялся размещая тему)

var curr=0, max=5,i=-1;

function next(){

  if(curr==max || curr==0)
    i=-i;

  curr+=i;
  
  console.log( curr);

}

for(var j=0;j<20;j++)
  next();


И выдает 0 1 2 3 4 5 4 3 2 1 0 ...

kostyanet 18.05.2015 16:35

Готовый кусок действующего вещества

/* calc curr and move block */
	move=function(j){
		i=j||i;
		curr+=i;

		if(curr==max || curr==0)
			i=-i;

		render();
		m.style.top=(curr*-step)+'px';
	},
	/* next - previous click */
	move_n=function(e){
		move(1);
	},
	move_p=function(e){
		move(-1);
	},
	/* animation */
	stop=function(e){
		if(to){
			W.clearTimeout(to);
			to=false;
		}
	},
	go=function(e){
		to=W.setTimeout(move,delay);
	},
	go_n=function(e){
		if(to!==false)
			go(e);
	},
	/* direct click */
	go_to=function(e){
		if(e.target.nodeName='I'){

			curr=parseInt(e.target.getAttribute('data-index'))-i;
			
			move();
			
			if(curr==max)
				i=-1;
			else if(curr==0)
				i=1;


		}
	};

	
	if(total>1){
		btn_n.addEventListener('click',move_n);
		btn_p.addEventListener('click',move_p);
		btn_b.addEventListener('click',go_to);
		p.addEventListener('mouseenter',stop);
		p.addEventListener('mouseleave',go);
		m.addEventListener('transitionend',go_n);
		W.addEventListener('focus',go);
		W.addEventListener('blur',stop);
	}


Щелчок с пуговиц - ну это знаете такие кнопки произвольного доступа к блокам - меня достал. Как только щелкаешь по крайним, индикатор i инвертируется и анимация тупо шарашит в заданном направлении, то есть показывает то, чего уже нет. Пришлось ввести дополнительную проверку, не считая предыскажения, чтоб посылать все на один и тот же move.

Второй вопрос. Похоже что когда окно свернуто, браузер, по крайней мере ФФ, лепит там таймаут на таймаут почем зря, в результате чего когда окно распахиваешь, происходит легкая паника среди блоков и движение приобретает калечный характер. Я добавил парочку событий на фокус-размытие окна, но эти штуки заведомо не везде работают и вообще работают неуверенно.

Как сделать анимацию чтоб он четко отрабатывала, не допуская ингресса таймаутов? Я видел где-то пример, там надо дату вводить, потом считать, поскольку тема есть, попробую на халяву получить ответ, спасибо.

kostyanet 18.05.2015 16:41

Упс, а зашибись я придумал: e.target.nodeName='I'

Только сейчас заметил, надо проверить что будет если правильно написать.

Ничего не поменялось, ну там и сделано так, что мимо не ткнешь.

kostyanet 21.05.2015 20:57

Ладно, никто не знает как правильно, оставил как было, если кому интересно посмотреть как получилось смотрите тут http://mebmoll.ru


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