JavaScript slidedown без jQuery
Я хочу иметь аналогичный эффект для jQuery slidedown, но без, используя jQuery или любую другую библиотеку. Я знаю, что это возможно, поскольку что-либо в jQuery может быть сделано в простом JavaScript. Просто тяжелее.
Я не могу использовать jQuery, поскольку все должно быть записано в моем собственном коде без использования каких-либо libaries.
Кто-нибудь сделал что-то подобное или какие-либо эффекты, просто используя простой JavaScript?
Ответы
Ответ 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> </div>
<div onclick="slideUp(document.getElementById('test'));">slide Up</div>
<div> </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;
}
Ответ 11
Посмотрите источник jQuery для этого эффекта (slideDown
вызывает show
).