JavaScript没有jQuery的滑动

我希望对jQuery滑动类似的效果,但使用jQuery或任何其他库。 我知道这是“可能的”,因为jQuery中的任何东西都可以用普通的JavaScript来完成。 更难。

我不能使用jQuery,因为一切都必须写在我自己的代码没有任何使用的库。

有没有人做过这样的事情或任何使用普通JavaScript的影响?

这是我从头开始编写的一小段代码,这完全是基于时间的

var minheight = 20; var maxheight = 100; var time = 1000; var timer = null; var toggled = false; window.onload = function() { var controler = document.getElementById('slide'); var slider = document.getElementById('slider'); slider.style.height = minheight + 'px'; //not so imp,just for my example controler.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); }; }; 

在这里testing: http : //jsbin.com/azewi5/5

作为@Ruben Serrate解决scheme的一个改进,它忽略了未知高度的用例,我使用CSS3和javascript(没有jQuery)创build了这个:

 /** * 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/

请让我知道,如果你能find任何改善,因为我总是试图改善我的代码。 快乐的编码! :d

可以用普通的JavaScript来完成。 更难。

其实这并不难 你只需要熟悉setTimeout() (无论如何,这是一个好主意,因为它会教你node.js的编程风格)。 最简单的实现(并不具备jQuery的所有function,这是留给读者的功课):

 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那样声明所有这些variables。为了清楚起见,我只是这样做了。

这个例子比试图阅读jQuery的源代码更短,更容易理解。


有没有人做过这样的事情或任何使用普通JavaScript的影响?

噢,当然,这是我周末为了娱乐而做的事情:

因为我们在2014年,为什么不使用CSS转换,只是改变元素的高度属性? 小提琴

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"; 

以前的答案的问题是你需要知道高度,然后再开始。 很多时候你不知道。 我build立了一个滑下你首先build立一个持有人的div,把对象ge滑下来里面设置对象的显示屏蔽和获取高度,并使用这个信号。 当侧面完成后,移动支架,完成后将其滑下。 下面是例子。

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

这个纯粹的js解决scheme并不需要事先知道最大高度,并使用css转换。

它将在转换期间将最大高度设置为2x浏览器窗口的高度,然后在转换完成后移除最大高度。

完整的slideDown,slideUp演示@ 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); }; 

在用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函数; 因为这看到他的答案。

我花了很多时间来开发这些函数,并使它们与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> 

以下是使用slideDown,slideUpanimation和未知内容高度元素的解决scheme。 https://jsfiddle.net/gebpjo1L/18/

它基于CSS 3高度animation,但animation需要指定的内容高度,因此您需要通过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> 

看看这个效果的jQuery源代码 ( slideDown calls show )。