Подтвердить что ты не робот

JavaScript slidedown без jQuery

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

В качестве улучшения для решения @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

Ответ 3

Так как мы в 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";

Ответ 4

можно сделать в простом 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?

О да, конечно, это то, что я делаю для удовольствия по выходным:

Ответ 5

Здесь решение использовать slideDown, анимацию slideUp с неизвестным элементом высоты содержимого. 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 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>

Ответ 6

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

<!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>

Ответ 7

После небольшого поворота с помощью ответа Symba я придумал это, чтобы учитывать отступы и границы:

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);
    }
}

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

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

Ответ 8

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

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

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

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);
};

Ответ 9

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

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>

Ответ 10

Сделать его короче:

<button onclick="slide()"></button>

<div id="box"></div>

JS:

slide(){document.getElementById("box").classList.toggle('hide');}

#box {
  overflow: hidden;
  transition: all .5s ease-in-out;
  -webkit-transition: all 0.5s ease-in-out;
  -moz-transition: all 0.5s ease-in-out;
  -ms-transition: all 0.5s ease-in-out;
  -o-transition: all 0.5s ease-in-out;
}
.hide {
  height: 0px !important;
}