JavaScript-слайд без JQuery - PullRequest
       25

JavaScript-слайд без JQuery

44 голосов
/ 26 сентября 2010

Я хотел бы иметь эффект, аналогичный jQuery slidingown, но без с использованием jQuery или любого другого библиотеки.Я знаю, что это «возможно», так как все, что в jQuery, можно сделать в простом JavaScript.Просто сложнее.

Я не могу использовать jQuery, поскольку все должно быть написано в моем собственном коде без использования каких-либо библиотек.

Кто-нибудь делал что-то подобное или какие-либо эффекты, просто используя простой JavaScript?

Ответы [ 10 ]

29 голосов
/ 26 сентября 2010

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

var minheight = 20;
var maxheight = 100;
var time = 1000;
var timer = null;
var toggled = false;

window.onload = function() {
    var controller = document.getElementById('slide');
    var slider = document.getElementById('slider');
    slider.style.height = minheight + 'px'; //not so imp,just for my example
    controller.onclick = function() {  
        clearInterval(timer);
        var instanceheight = parseInt(slider.style.height);  // Current height
        var init = (new Date()).getTime(); //start time
        var height = (toggled = !toggled) ? maxheight: minheight; //if toggled

        var disp = height - parseInt(slider.style.height);
        timer = setInterval(function() {
            var instance = (new Date()).getTime() - init; //animating time
            if(instance <= time ) { //0 -> time seconds
                var pos = instanceheight + Math.floor(disp * instance / time);
                slider.style.height =  pos + 'px';
            }else {
                slider.style.height = height + 'px'; //safety side ^^
                clearInterval(timer);
            }
        },1);
    };
};

Проверьте это здесь: http://jsbin.com/azewi5/5

26 голосов
/ 14 марта 2015

В качестве улучшения решения @Ruben Serrate, в котором отсутствует сценарий использования для неизвестной высоты, Я создал это, используя CSS3 и javascript (без jQuery):

/**
* getHeight - for elements with display:none
 */
getHeight = function(el) {
    var el_style      = window.getComputedStyle(el),
        el_display    = el_style.display,
        el_position   = el_style.position,
        el_visibility = el_style.visibility,
        el_max_height = el_style.maxHeight.replace('px', '').replace('%', ''),

        wanted_height = 0;


    // if its not hidden we just return normal height
    if(el_display !== 'none' && el_max_height !== '0') {
        return el.offsetHeight;
    }

    // the element is hidden so:
    // making the el block so we can meassure its height but still be hidden
    el.style.position   = 'absolute';
    el.style.visibility = 'hidden';
    el.style.display    = 'block';

    wanted_height     = el.offsetHeight;

    // reverting to the original values
    el.style.display    = el_display;
    el.style.position   = el_position;
    el.style.visibility = el_visibility;

    return wanted_height;
};


/**
* toggleSlide mimics the jQuery version of slideDown and slideUp
* all in one function comparing the max-heigth to 0
 */
toggleSlide = function(el) {
    var el_max_height = 0;

    if(el.getAttribute('data-max-height')) {
        // we've already used this before, so everything is setup
        if(el.style.maxHeight.replace('px', '').replace('%', '') === '0') {
            el.style.maxHeight = el.getAttribute('data-max-height');
        } else {
            el.style.maxHeight = '0';
        }
    } else {
        el_max_height                  = getHeight(el) + 'px';
        el.style['transition']         = 'max-height 0.5s ease-in-out';
        el.style.overflowY             = 'hidden';
        el.style.maxHeight             = '0';
        el.setAttribute('data-max-height', el_max_height);
        el.style.display               = 'block';

        // we use setTimeout to modify maxHeight later than display (to we have the transition effect)
        setTimeout(function() {
            el.style.maxHeight = el_max_height;
        }, 10);
    }
}

Вот демо: http://jsfiddle.net/pgfk2mvo/

Пожалуйста, дайте мне знать, если вы можете найти какие-либо улучшения в этом, поскольку я всегда стараюсь улучшить свой код. Удачного кодирования! : D

21 голосов
/ 06 октября 2014

Поскольку мы находимся в 2014 году, почему бы не использовать CSS-переходы и просто изменить свойство высоты элемента? Fiddle

CSS:

.wrapper {
    transition:height 1s ease-out;
    height:0;
    overflow:hidden;
}

HTML:

<div id="wrapper">
//content
</div>

JAVASCRIPT:

document.getElementById("wrapper").style.height = //content height +"px";
16 голосов
/ 26 сентября 2010

можно сделать простым JavaScript. Просто сложнее.

На самом деле это не так уж сложно. Вам просто нужно освоиться с setTimeout() (что в любом случае является хорошей идеей, так как учит вас стилю программирования для node.js). Самая простая реализация (не имеет всех функций jQuery, оставленных читателем в качестве домашней работы):

function slideDown (element, duration, finalheight, callback) {
    var s = element.style;
    s.height = '0px';

    var y = 0;
    var framerate = 10;
    var one_second = 1000;
    var interval = one_second*duration/framerate;
    var totalframes = one_second*duration/interval;
    var heightincrement = finalheight/totalframes;
    var tween = function () {
        y += heightincrement;
        s.height = y+'px';
        if (y<finalheight) {
            setTimeout(tween,interval);
        }
    }
    tween();
}

Конечно, это не самый короткий способ написать это, и вам не нужно объявлять все эти переменные, такие как one_second и т. Д. Я просто сделал это так, чтобы было ясно, что происходит.

Этот пример также короче и проще для понимания, чем попытка прочитать исходный код jQuery.


Кто-нибудь делал что-то подобное или какие-либо эффекты, просто используя простой JavaScript?

О да, конечно, я так делаю для развлечения по выходным:

6 голосов
/ 12 августа 2017

Вот решение для использования slideDown, слайд-анимации с неизвестной высотой содержимого элемента. https://jsfiddle.net/gebpjo1L/18/

Он основан на анимации высоты CSS 3, но для анимации требуется указанная высота содержимого, поэтому вам необходимо получить высоту содержимого с помощью JavaScript, прежде чем расширять его.

var container = document.querySelector('div')
var button    = document.querySelector('button')

button.addEventListener('click', () => {
    /** Slide down. */
    if(!container.classList.contains('active')) {
        /** Show the container. */
    	container.classList.add('active')
        container.style.height = "auto"
        
        /** Get the computed height of the container. */
    	var height = container.clientHeight + "px"

        /** Set the height of the content as 0px, */
        /** so we can trigger the slide down animation. */
        container.style.height = "0px"

        /** Do this after the 0px has applied. */
        /** It's like a delay or something. MAGIC! */
        setTimeout(() => {
            container.style.height = height
        }, 0) 
    
	/** Slide up. */
    } else {
    	/** Set the height as 0px to trigger the slide up animation. */
    	container.style.height = "0px"
        
        /** Remove the `active` class when the animation ends. */
    	container.addEventListener('transitionend', () => {
        	container.classList.remove('active')
        }, {once: true})
    }
})
div {
    transition: height .5s ease;
    overflow  : hidden;
}

div:not(.active) {
    display: none;
}
<div>
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
</div>
<button>Slide Toggle</button>
5 голосов
/ 17 июня 2014

Проблема с более ранними ответами заключается в том, что вам нужно знать высоту, прежде чем начать. Много раз нет. Я построил слайд вниз, когда вы вначале строите div-элемент держателя, поместите объект, чтобы скользить вниз, установите отображение объекта, который нужно заблокировать, и получите высоту и используйте это для синдрома. Когда сторона готова, держатель снимается, а затем сдвиньте вниз. ниже приведен пример.

<!DOCTYPE html>
<html>
    <head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        <div >
            <div id="test" style="height: 150px; width: 100px; background-color: yellowgreen; display:none">block</div>
        </div>
        <div>&nbsp;</div>
        <div onclick="slideUp(document.getElementById('test'));">slide Up</div>
        <div>&nbsp;</div>
        <div onclick="slideDown(document.getElementById('test'))">slide down</div>
        <script>
            function slideDown(obj, speed) {
                var mySpeed = speed || 300;
                var intervals = mySpeed / 30; // we are using 30 ms intervals
                alert('intervals = ' + intervals);
                var holder = document.createElement('div');//
                var parent = obj.parentNode;
                holder.setAttribute('style', 'height: 0px; overflow:hidden');
                parent.insertBefore(holder, obj);
                parent.removeChild(obj);
                holder.appendChild(obj);
                obj.style.display = obj.getAttribute("data-original-display") || "";
                var height = obj.offsetHeight;
                var sepHeight = height / intervals;
                //  alert(sepHeight)
                var timer = setInterval(function() {
                    var holderHeight = holder.offsetHeight;
                    if (holderHeight + sepHeight < height) {
                        holder.style.height = (holderHeight + sepHeight) + 'px';
                    } else {
                        // clean up
                        holder.removeChild(obj);
                        parent.insertBefore(obj, holder);
                        parent.removeChild(holder);
                        clearInterval(timer);
                    }
                }, 30);
            }

            function slideUp(obj, speed) {
                var mySpeed = speed || 300;
                var intervals = mySpeed / 30; // we are using 30 ms intervals
                var height = obj.offsetHeight;
                var holder = document.createElement('div');//
                var parent = obj.parentNode;
                holder.setAttribute('style', 'height: ' + height + 'px; overflow:hidden');
                parent.insertBefore(holder, obj);
                parent.removeChild(obj);
                holder.appendChild(obj);
                var originalDisplay = (obj.style.display !== 'none') ? obj.style.display : '';
                obj.setAttribute("data-original-display", originalDisplay);
                var sepHeight = height / intervals;
                //  alert(sepHeight)
                var timer = setInterval(function() {
                    var holderHeight = holder.offsetHeight;
                    console.log(holderHeight);
                    if (holderHeight - sepHeight > 0) {
                        holder.style.height = (holderHeight - sepHeight) + 'px';
                    } else {
                        // clean up
                        obj.style.display = 'none';
                        holder.removeChild(obj);
                        parent.insertBefore(obj, holder);
                        parent.removeChild(holder);
                        clearInterval(timer);
                    }
                }
                , 30);
            }

        </script>
    </body>
</html>
3 голосов
/ 08 мая 2016

это чистое решение js не требует предварительного знания максимальной высоты и использует css-переходы.

установит max-height в 2 раза больше высоты окна браузера во время перехода, а затем уберет max-height после перехода.

полное понижение слайда, демонстрация слайда @ https://kaizhu256.github.io/node-swagger-lite/build..alpha..travis-ci.org/app/index.html

1008 * CSS *

.swggAnimateSlide {
    overflow-y: hidden;
    transition: all 500ms linear;
}
.swggAnimateSlideUp {
    border-bottom: 0 !important;
    border-top: 0 !important;
    margin-bottom: 0 !important;
    margin-top: 0 !important;
    max-height: 0 !important;
    padding-bottom: 0 !important;
    padding-top: 0 !important;
}

JS

domAnimateSlideDown = function (element) {
/*
 * this function will slideDown the dom-element
 */
    if (element.style.maxHeight || element.style.display !== 'none') {
        return;
    }
    element.classList.add('swggAnimateSlideUp');
    element.classList.add('swggAnimateSlide');
    element.style.display = '';
    setTimeout(function () {
        element.style.maxHeight = 2 * window.innerHeight + 'px';
        element.classList.remove('swggAnimateSlideUp');
    }, 50);
    setTimeout(function () {
        element.style.maxHeight = '';
        element.classList.remove('swggAnimateSlide');
    }, 500);
};


domAnimateSlideUp = function (element) {
/*
 * this function will slideUp the dom-element
 */
    if (element.style.maxHeight || element.style.display === 'none') {
        return;
    }
    element.style.maxHeight = 2 * window.innerHeight + 'px';
    element.classList.add('swggAnimateSlide');
    setTimeout(function () {
        element.classList.add('swggAnimateSlideUp');
        element.style.maxHeight = '0px';
    }, 50);
    setTimeout(function () {
        element.style.display = 'none';
        element.style.maxHeight = '';
        element.classList.remove('swggAnimateSlide');
        element.classList.remove('swggAnimateSlideUp');
    }, 500);
};
3 голосов
/ 28 марта 2016

Немного повозившись с Ответом Симбы Я придумал это, чтобы учесть отступы и границы:

toggleSlide = function (el) {
    var el_max_height = 0;
    if (el.getAttribute('data-max-height')) {
        if (el.style.maxHeight.replace('px', '').replace('%', '') === '0') {
            el.style.maxHeight = el.getAttribute('data-max-height');
            el.style.paddingTop = el.getAttribute('data-pad-top');
            el.style.paddingBottom = el.getAttribute('data-pad-bottom');
            el.style.borderTop = el.getAttribute('data-border-top');
            el.style.borderBottom = el.getAttribute('data-border-bottom');
        } else {
            el.style.maxHeight = '0';
            el.style.paddingTop = '0';
            el.style.paddingBottom = '0';
            el.style.borderBottom = '0';
            el.style.borderTop = '0';
        }
    } else {
        el_max_height = getHeight(el) + 'px';
        el.style['transition-property'] = 'max-height, padding-top, padding-bottom, border-bottom, border-top';
        el.style['transition-duration'] = '0.5s';
        el.style['transition-timing-function'] = 'ease-in-out';
        el.style.overflowY = 'hidden';
        el.style.maxHeight = '0';
        el.setAttribute('data-max-height', el_max_height);
        el.setAttribute('data-pad-top', el.style.paddingTop);
        el.setAttribute('data-pad-bottom', el.style.paddingBottom);
        el.setAttribute('data-border-top', el.style.borderTop);
        el.setAttribute('data-border-bottom', el.style.borderBottom);
        el.style.display = 'block';
        setTimeout(function () { el.style.maxHeight = el_max_height; }, 10);
    }
}

На верхней границе немного мерцает, когда начинается расширение перехода, и я пока не знаю, как это исправить.

Я не модифицировал функцию getHeight в Symba; см. его ответ.

2 голосов
/ 21 июня 2016

Я потратил много времени на разработку этих функций и на то, чтобы сделать их максимально похожими на функции JQuery, я думаю, что они являются некоторыми деталями, которые нужно оптимизировать в функции morph, в основном по длине

function morph( element, options, animationTime, callback ) { 
// options is an array with the same structural of Properties and DiffValues and which contains the properties values we want the animation make
	var ComputedElementStyle = window.getComputedStyle(element,null);
	var AttrElementStyle = element.style;
	var Properties = { // the actuals computed properties
		width: 		parseInt( ComputedElementStyle.getPropertyValue("width")),
		height: 	parseInt( ComputedElementStyle.getPropertyValue("height")),
		padding: {
			top: 	parseInt(ComputedElementStyle.getPropertyValue("padding-top")),
			right: 	parseInt(ComputedElementStyle.getPropertyValue("padding-right")),
			bot: 	parseInt(ComputedElementStyle.getPropertyValue("padding-bottom")),
			left:	parseInt(ComputedElementStyle.getPropertyValue("padding-left"))
			},
		margin:{
			top: 	parseInt(ComputedElementStyle.getPropertyValue("margin-top")),
			right: 	parseInt(ComputedElementStyle.getPropertyValue("margin-right")),
			bot: 	parseInt(ComputedElementStyle.getPropertyValue("margin-bottom")),
			left:	parseInt(ComputedElementStyle.getPropertyValue("margin-left"))
			} 
	};
	var DiffValues = { // the differences between actual properties values and values we want to
		width:		(options['width']!=null) ? (options['width'] - Properties['width']) : 0,
		height:		(options['height']!=null) ? (options['height'] - Properties['height']) : 0,
		padding: {
			top: 	(options['padding']&&options['padding']['top']!=null) ? options['padding']['top'] - Properties['padding']['top'] : 0,
			right: 	(options['padding']&&options['padding']['right']!=null) ? options['padding']['right'] - Properties['padding']['right'] : 0,
			bot: 	(options['padding']&&options['padding']['bot']!=null) ? options['padding']['bot'] - Properties['padding']['bot'] : 0,
			left: 	(options['padding']&&options['padding']['left']!=null) ? options['padding']['left'] - Properties['padding']['left'] : 0
			},
		margin:{
			top: 	(options['margin']&&options['margin']['top']!=null) ? options['margin']['top'] - Properties['margin']['top'] : 0,
			right: 	(options['margin']&&options['margin']['right']!=null) ? options['margin']['right'] - Properties['margin']['right'] : 0,
			bot: 	(options['margin']&&options['margin']['bot']!=null) ? options['margin']['bot'] - Properties['margin']['bot'] : 0,
			left: 	(options['margin']&&options['margin']['left']!=null) ? options['margin']['left'] - Properties['margin']['left'] : 0
			}
	};
	var beginTime = new Date().getTime(); // time at begining of animation
	animationTime = (animationTime!=null) ? animationTime : 250;
	AttrElementStyle.overflow = "hidden"; // disable the potentials scrollbars
	
	var sinceBeginTime; // time since the begining
	var progressFactor; // coeficient that correspond to the advancement of the animation
	
	timer = setInterval(function() { // begin of the animation
		sinceBeginTime = new Date().getTime() - beginTime;
		if( sinceBeginTime < animationTime ) {
			progressFactor = sinceBeginTime / animationTime;
			AttrElementStyle.width=(Properties['width'] + DiffValues['width'] * progressFactor)		+"px";
			AttrElementStyle.height=(Properties['height'] + DiffValues['height'] * progressFactor)	+"px";
			AttrElementStyle.padding=
				(Properties['padding']['top'] + DiffValues['padding']['top'] * progressFactor)		+"px "+
				(Properties['padding']['right'] + DiffValues['padding']['right'] * progressFactor)	+"px "+
				(Properties['padding']['bot'] + DiffValues['padding']['bot'] * progressFactor)		+"px "+
				(Properties['padding']['left'] + DiffValues['padding']['left'] * progressFactor)	+"px";
			AttrElementStyle.margin=
				(Properties['margin']['top'] + DiffValues['margin']['top'] * progressFactor)		+"px "+
				(Properties['margin']['right'] + DiffValues['margin']['right'] * progressFactor)	+"px "+
				(Properties['margin']['bot'] + DiffValues['margin']['bot'] * progressFactor)		+"px "+
				(Properties['margin']['left'] + DiffValues['margin']['left'] * progressFactor)		+"px";
		}else {
			AttrElementStyle.width=options['width']		+"px";
			AttrElementStyle.height=options['height']	+"px";
			AttrElementStyle.padding=
				(Properties['padding']['top'] + DiffValues['padding']['top'])		+"px "+
				(Properties['padding']['right'] + DiffValues['padding']['right'])	+"px "+
				(Properties['padding']['bot'] + DiffValues['padding']['bot'])		+"px "+
				(Properties['padding']['left'] + DiffValues['padding']['left'])		+"px";
			AttrElementStyle.margin=
				(Properties['margin']['top'] + DiffValues['margin']['top'])			+"px "+
				(Properties['margin']['right'] + DiffValues['margin']['right'])		+"px "+
				(Properties['margin']['bot'] + DiffValues['margin']['bot'])			+"px "+
				(Properties['margin']['left'] + DiffValues['margin']['left'])		+"px";
			clearInterval( timer ); // end of the animation
			if( callback!=null ) // if there is a CALLBACK then call it
				callback(Properties);
		}
	},15);
}
function slideUp( element, animationTime , callback) {
	morph( element, {
			height:0,
			padding:{
				top:0,
				bot:0
			},
			margin:{
				top:0,
				bot:0
			} },  animationTime, function(Properties) {
			// at the end of the slideUp we display: none the element and clean the other properties from style attribute
			var AttrElementStyle = element.style;
			AttrElementStyle.width="";
			AttrElementStyle.height="";
			AttrElementStyle.padding="";
			AttrElementStyle.margin="";
			element.style.display = 'none';
			if(callback)
				callback();
	});
}

function slideDown( element, animationTime , callback) {
	var AttrElementStyle = element.style;
	var ComputedElementStyle = window.getComputedStyle(element,null);
	
	AttrElementStyle.display="block";
	
	var options = { // the computed properties when element is displayed
	width: 		parseInt( ComputedElementStyle.getPropertyValue("width")),
	height: 	parseInt( ComputedElementStyle.getPropertyValue("height")),
	padding: {
		top: 	parseInt(ComputedElementStyle.getPropertyValue("padding-top")),
		bot: 	parseInt(ComputedElementStyle.getPropertyValue("padding-bottom"))
		},
	margin:{
		top: 	parseInt(ComputedElementStyle.getPropertyValue("margin-top")),
		bot: 	parseInt(ComputedElementStyle.getPropertyValue("margin-bottom"))
		} 
	};
	// after getting the actuals properties values of the element we flatten it
	AttrElementStyle.height="0";
	AttrElementStyle.paddingTop="0";
	AttrElementStyle.paddingBottom="0";
	AttrElementStyle.marginTop="0";
	AttrElementStyle.marginBottom="0";
	
	morph( element, options , animationTime, function() { // morph the element from flat to the options properties that are right
		// at the end of slideDown we clean up the style but keep the display: block if the element is display: none in the stylesheet
		AttrElementStyle.width="";
		AttrElementStyle.height="";
		AttrElementStyle.padding="";
		AttrElementStyle.margin="";
		element.style.display = 'block';
		if(callback) // if there is a CALLBACK then call it (we are in the morph() callback)
			callback();
	})
}
p{
  width:50%;
  height:auto;
  padding:40px 0 10px;
  margin: 10px 0 40px;
  border:2px solid red
}
div{
  border:1px solid blue;
  padding:10px
}
<div>
  <p id='p'>loiloilozoifboiygdouhbodihfgsd</br>rihgdggisbifghbsoifnsf</br>giodsbgsigfbsjgsgs</p>
</div>

<button onClick="slideUp( document.getElementById('p') ,500)">testUp</button>
<button onClick="slideDown( document.getElementById('p') ,500)">testDown</button>

<button id='btn1' onClick="morph( document.getElementById('btn1'),{ width: 120,height:130,padding:{top:70,left:50},margin:{right:40}} ,1000)">morphIt</button>
<button onClick="document.getElementById('btn1').style=''">reset btn1</button>
0 голосов
/ 26 сентября 2010

Посмотрите на источник jQuery для этого эффекта (slideDown вызывает show).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...