I am currently working on a text slider using jquery.
The code relies on slide toggle and fade working together.
The sample code is here https://codepen.io/fja3omega/pen/GwVYXM
My jQuery is:
jQuery( document ).ready(function() {
jQuery.fn.slideFadeToggle = function(speed, easing, callback) {
return this.animate({opacity: 'toggle', height: 'toggle'}, speed, easing, callback);
};
var counted = 1;
jQuery(".slidem").find( "#rotate1" ).slideFadeToggle();
setInterval(function(){
counted = counted + 1;
torotate = "#rotate" + counted;
if(counted!=5) {
jQuery(".slidem").find( torotate ).slideFadeToggle();
} else {
counted = 1;
jQuery(".slidem .rotater" ).show();
jQuery(".slidem").find( "#rotate1" ).slideFadeToggle();
jQuery(".slidem").find( "#rotate5" ).show();
}
}, 3000);
});
I was wondering if there was a way to shorten or simplify the jQuery.
Yes, you can simplify and improve your code removing all the unnecessary id and class attributes. Also you might make your code more abstract to support any number of "slides" not only 5.
See the snippet below:
jQuery(document).ready(function() {
jQuery.fn.slideFadeToggle = function(speed, easing, callback) {
return this.animate({opacity: 'toggle', height: 'toggle'}, speed, easing, callback);
};
var n = 0, slides = jQuery('.slidem > div');
(function slide() {
n = n * (n < slides.length) || +!slides.show();
slides.eq(n++).slideFadeToggle();
setTimeout(slide, 1000);
})()
});
.irotate {
text-align: center;
margin: 0 auto;
padding: 10% 0;
display: block;
}
.thisis {
display: inline-block;
vertical-align: middle;
height: 20px;
}
.slidem {
overflow: hidden;
text-align: center;
min-width: 90px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="irotate">
<div class="thisis">This is a </div>
<div class="thisis slidem">
<div> </div>
<div>simple</div>
<div>super easy</div>
<div>fun</div>
<div>working</div>
</div>
<div class="thisis"> Text Slider</div>
</div>
Related
I need everyone's help. I currently need to implement a marquee effect. The yellow box needs to be scrolled up to show the name. Every time I scroll, I have to stay in the middle of the box for 1 second before continuing to scroll. I can find such an example on the Internet. , but the logic of this program is a bit difficult for me to understand for urban beginners. I wonder if anyone would like to provide a simpler and easier-to-understand writing method if I want to achieve this marquee effect?
Sorry, I am a beginner in the program, the current logic More complex programs are more difficult to understand.
function slideLine(box, stf, delay, speed, h) {
var slideBox = document.getElementById(box);
var delay = delay || 1000,
speed = speed || 20,
h = h || 40;
var tid = null,
pause = false;
var s = function() {
tid = setInterval(slide, speed);
};
var slide = function() {
if (pause) return;
slideBox.scrollTop += 1;
if (slideBox.scrollTop % h == 0) {
clearInterval(tid);
slideBox.appendChild(slideBox.getElementsByTagName(stf)[0]);
slideBox.scrollTop = 0;
setTimeout(s, delay);
}
};
setTimeout(s, delay);
}
slideLine("kanban_info", "p", 1000, 25, 40);
.kanban {
position: absolute;
margin: 0 auto;
width: 278px;
height: 50px;
background-color: yellow;
left: 50%;
transform: translate(-50%);
text-align: center;
line-height: 6;
}
.kanban .kenban_wrap {
height: 38px;
transform: translateY(28px);
overflow: hidden;
}
.kanban .kenban_wrap .kanban_info {
line-height: 38px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="kanban">
<div class="kenban_wrap" id='kanban_info'>
<p class="kanban_info">Allen</p>
<p class="kanban_info">james</p>
<p class="kanban_info">jack</p>
</div>
</div>
By combining scroll-behavior with anchor tags that are programmatically clicked you can simplify it. This should be easier to understand and you can go from there, even if it might not be the best solution.
let links = document.querySelectorAll("a"); // List of links
let div = document.querySelector("div");
let index = 0;
let t = 2000; // setTimeout duration
// Change Scroll behavior to prevent the animation from the last to first list item
function scrollBeh() {
if(index == 1) {
div.style.scrollBehavior = "auto";
t = 0; // Timeout duration to 0 to prevent `1` being shown longer than other list items
} else {
div.style.scrollBehavior = "smooth";
t = 2000;
}
}
// Loop through list items
function resetInd() {
if(index < 3) {
index++;
} else {
index = 0;
}
}
function clickLinks() {
links[index].click();
resetInd();
scrollBeh();
setTimeout(clickLinks, t);
}
setTimeout(clickLinks, t);
div {
width: 200px;
height: 100px;
background-color: darkblue;
overflow: hidden;
scroll-behavior: smooth;
}
li {
height: 100px;
list-style: none;
}
a {
text-decoration: none;
color: #FFF;
font-size: 50px;
}
<div>
<ul>
<li id="one">1</li>
<li id="two">2</li>
<li id="three">3</li>
<li id="one_loop">1</li>
</ul>
</div>
For demonstration purposes provided example I tried to implement animation in which one div follows actual scrollbar in order to get as many changes as possible.
However, animation works really nice on Chrome, pretty well even in IE but it is extremely laggy in Firefox.
I tried with some hardware acceleration tricks like translateZ(0), etc, but with no success for Firefox.
Instead of top I tried to use transform, again, no luck.
Can I expect better performance if I try canvas?
(function () {
var scrollerElement = document.getElementById('scroller');
var elementToMove = document.getElementById('toMove');
var scrollerSize = scrollerElement.clientHeight;
var maxScroll = scrollerElement.scrollHeight - scrollerSize;
var whileAnimate;
var timeout;
var delay = 200;
scrollerElement.addEventListener('scroll', function (event) {
clearTimeout(timeout);
timeout = setTimeout(cancelAnimation, delay);
if (whileAnimate) {
return;
}
startAnimation();
});
function cancelAnimation() {
whileAnimate = false;
}
function startAnimation() {
var animationFrame;
whileAnimate = true;
animate();
function animate() {
if (!whileAnimate) {
cancelAnimationFrame(animationFrame);
return;
}
elementToMove.style.top = (scrollerElement.scrollTop / maxScroll * scrollerSize) + 'px';
animationFrame = requestAnimationFrame(animate);
}
}
})();
body {
margin: 0;
padding: 0;
}
#scroller {
width: 500px;
height: 500px;
border: 1px solid black;
overflow: auto;
}
#content {
width: 500px;
height: 20000px;
}
#toMove {
position: absolute;
top: 0;
width: 20px;
height: 20px;
background: red;
}
<div id="scroller">
<div id="toMove"></div>
<div id="content"></div>
</div>
I have the code below where I'd like to the numbers count back to 0% once hover the object out. Also I can't figure our how to make the value disappear again as it was on load. Could you please help me solve this.
Thanks in advance.
HTML
<div class="container">
<div class="fill" data-width="80%"></div>
</div>
<div class="container">
<div class="fill" data-width="50%"></div>
</div>
CSS
.container {
position: relative;
width: 300px;
height: 30px;
background-color: blue;
margin: 10px auto;
}
.fill {
height: 100%;
width: 0;
background-color: red;
line-height: 30px;
text-align: left;
z-index: 1;
text-align: right;
}
JQuery
$(function() {
$('.container').hover( function(){
var width=$(this).find(".fill").data('width');
$(this).find(".fill").animate({ width: width }, {
duration:800,
step: function(now, fx) {
$(this).html(Math.round(now) + '%');
}
});
},
function(){
$(this).find(".fill").animate({ "width": "0px" }, 800);
});
});
jsFiddle http://jsfiddle.net/zp8pe069/
jsBin demo
CSS: set overflow: hidden to .fill to prevent the text being visible after the animation ends.
HTML: remove % from the data attribute
JS and here you go. all you need:
$('.container').hover(function( e ){
var $fill = $(this).find(".fill");
var width = $fill.data('width');
$fill.stop().animate({width: e.type=="mouseenter" ? width+"%" : "0%" }, {
duration : 800,
step : function(now) {
$(this).html(Math.round(now) + '%') ;
}
});
});
Note also the use of the .stop() method, if you hover multiple time hysterically :) it'll prevent endless animations.
I am trying to create a music player/centre online.
I have a player that plays the music and displays the current track:
As you can see from th title of the song it is too long for the div. What i would like to do is scroll the text and reset it an rescroll etc.
I have attempted this with the below code:
html:
<div id="top-bar">
<div id="player-container">
<div id="player">
<div id="level1">
<div class="current-track"><h1><span id="title">Party All Night (Sleep All Day) -</span> Sean Kingston</h1></div>
<div class="add-to-playlist"></div>
<div class="share"></div>
</div>
<div class="clearfix"></div>
<div id="level2">
<div class="current-time">0:00</div>
<div class="progress"><span id="slider"></span></div>
<div class="total-time">3:43</div>
</div>
</div>
</div>
</div>
Jquery:
$(function() {
var scroll_text;
$('div.current-track').hover(
function() {
var $elmt = $(this);
scroll_text = setInterval(function() {
scrollText($elmt);
}, 5);
}, function() {
clearInterval(scroll_text);
$(this).find('div.current-track h1').css({
left: 0
});
});
var scrollText = function($elmt) {
var left = $elmt.find('div.current-track h1').position().left - 1;
left = -left > $elmt.find('div.current-track h1').width() ? $elmt.find('div.current-track').width() : left;
$elmt.find('div.current-track h1').css({
left: left
});
};
});
Any pointer would be appriciated
Here is a jsfiddle for you guys: JSfiddle
UPDATE
Could anybody tell me:
How to make this happen automatically? Done
How to slow the scrolling? Done
Here is the updated jsfiddle for you guys: JSfiddle
I think you are misunderstanding how jquery .find() works:
$elmt.find('div.current-track h1')
should be:
$elmt.find('h1')
http://jsfiddle.net/Dn6jx/5/
edit: updated fiddle for comments
http://jsfiddle.net/Dn6jx/15/
Added check to see if text is long enough to require scrolling, removed the clear interval, and wrapped in plugin.
JSFiddle update
$.fn.scrolltxt = function() {
var options = $.extend({
speed : 28
}, arguments[0] || {});
return this.each(function() {
var el = $(this);
if( el.find('span').width() > el.parent().width() ) {
var scroll_text = setInterval(function() {
scrollText();
}, options.speed);
};
var scrollText = function() {
var width = el.width(),
left = el.position().left - 1;
left = -left > width ? width : left;
el.css({left: left});
};
}); };
$('.current-track h1').scrolltxt();
A better way to animate the text (when the text is fully read => re-animate) :
JSFiddle update
$.fn.scrolltxt = function() {
var options = $.extend({
speed : 28
}, arguments[0] || {});
return this.each(function() {
var el = $(this);
if( el.find('span').width() > el.parent().width() ) {
var scroll_text = setInterval(function() {
scrollText();
}, options.speed);
};
var scrollText = function() {
var width = el.find('span').width(),
left = el.position().left - 1;
left = -left > width ? el.width() : left;
el.css({left: left});
};
});
};
$(function() {
$('.current-track h1').scrolltxt();
});
I improved the answer of Holiday Mat a bit.
If you want to replace the text with other text dynamically (which is not too long), the scrolling will still keeps place. You have to reset the interval somehow.
Another problem you might run into is, too many intervals are set and the text scrolls faster and faster.
Here a snippet which shows how I handled this. (I used h5 instead of h1, which you probably use somewhere else.) :
$.fn.scrolltxt = function() {
var options = $.extend({
speed: 28
}, arguments[0] || {});
return this.each(function() {
var $h5 = $(this);
var containerWidth = $h5.parent().width();
var textWidth = $h5.find('span').width();
var refreshIntervalId;
if (textWidth > containerWidth) {
refreshIntervalId = setInterval(function() {
scrollText();
}, options.speed);
$h5.data('refreshIntervalId', refreshIntervalId);
} else {
refreshIntervalId = $h5.data('refreshIntervalId');
if (refreshIntervalId != undefined) {
window.clearInterval(refreshIntervalId);
$h5.removeData('refreshIntervalId');
}
}
var scrollText = function() {
var textWidth = $h5.find('span').width();
var left = $h5.position().left - 1;
left = -left > textWidth ? $h5.width() : left;
$h5.css({
left: left
});
};
});
};
$('h5.scroll').scrolltxt();
#player {
width: 500px;
background: #000;
border: 1px solid #1f1f1f;
border-radius: 10px;
margin: 10px;
padding: 10px 20px;
}
.current-track {
height: 100%;
background: #333;
color: #FFF;
margin-right: 5px;
width: 100%;
font-size: 150%;
border-radius: 5px;
line-height: 30px;
overflow: hidden;
position: relative;
}
.current-track h5 {
position: relative;
white-space: nowrap;
line-height: 1.5em;
font-size: 1.5em;
}
* {
margin: 0;
padding: 0;
}
body {
font-family: Arial, Helvetica, sans-serif;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="player">
<div id="level1">
<div class="current-track">
<h5 class="scroll"><span><strong>KAFKA (The artist formerly known as Prince)</strong></span></h5>
</div>
<br /><br /><br />
<div class="current-track">
<h5 class="scroll"><span>The Most Beautiful Girl In The World (original 1995 version)</span></h5>
</div>
</div>
</div>
Or see the CodePen: https://codepen.io/r-w-c/pen/dyKoKQX
I am adapting the Coverflow technique to work with a div. Following is the html:
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<style type="text/css" media="screen">
body,html {
margin: 0;
padding: 0;
background: #000;
height: 100%;
color: #eee;
font-family: Arial;
font-size: 10px;
}
div.magnifyme {
height: 80px;
padding: 80px;
position: absolute;
top: 0px;
left: 0px;
width: 2000px;
}
div.wrapper {
margin: 0px;
height: 470px;
/*border: 2px solid #999;*/
overflow: hidden;
padding-left: 40px;
right: 1px;
width: 824px;
position: relative;
}
div.container {position: relative; width: 854px; height: 480px; background: #000; margin: auto;}
div.nav {position: absolute; top: 10px; width: 20%; height: 10%; right: 1px; }
div.magnifyme div {
position: absolute;
width: 300px;
height: 280px;
float: left;
margin: 5px;
position: relative;
border: 2px solid #999;
background: #500;
}
</style>
<script type="text/javascript" src="jquery-1.3.2.js"></script>
<script type="text/javascript" src="ui.coverflow.js"></script>
<script type="text/javascript" src="ui.core.js"></script>
<script type="text/javascript">
$(function() {
$("div.magnifyme").coverflow();
$("#add").click(function() {
$(".magnifyme").append("<div id=\"div5\">hello world</div>");
$("div.magnifyme").coverflow();
});
});
</script>
</head>
<body>
<div class="container">
<div class="wrapper">
<div class="magnifyme">
<div id="div0">This is div 0</div>
<div id="div1">This is div 1</div>
<div id="div2">This is div 2</div>
<div id="div3">This is div 3</div>
<div id="div4">This is div 4</div>
</div>
</div>
<div class="nav">
<button type="button" id="add">Add to Deck</button>
</div>
</div>
</body>
</html>
The coverflow function (included as a js file in the head section) is here. When I click the button, I was expecting it to add a DIV to the already present deck. For some reason, it doesn't show the newly added DIV. I tried calling the coverflow() function after I added the new element but that didn't work either. The modified coverflow function is given here:
;(function($){
$.widget("ui.coverflow", {
init: function() {
var self = this;
this.items = $(this.options.items, this.element).bind("click", function() {
self.moveTo(this);
//$("div.slider").slider("moveTo", self.current, null, true);
});
this.itemWidth = this.items.outerWidth(true);
this.current = 0; //Start item
this.refresh(1, 0, this.current);
this.element.css("left",
(-this.current * this.itemWidth/2)
+ (this.element.parent()[0].offsetWidth/2 - this.itemWidth/2) //Center the items container
- (parseInt(this.element.css("paddingLeft")) || 0) //Subtract the padding of the items container
);
},
moveTo: function(item) {
this.previous = this.current;
this.current = !isNaN(parseInt(item)) ? parseInt(item) : this.items.index(item);
if(this.previous == this.current) return false; //Don't animate when clicking on the same item
var self = this, to = Math.abs(self.previous-self.current) <=1 ? self.previous : self.current+(self.previous < self.current ? -1 : 1);
$.fx.step.coverflow = function(fx) {
self.refresh(fx.now, to, self.current);
};
this.element.stop().animate({
coverflow: 1,
left: (
(-this.current * this.itemWidth/2)
+ (this.element.parent()[0].offsetWidth/2 - this.itemWidth/2) //Center the items container
- (parseInt(this.element.css("paddingLeft")) || 0) //Subtract the padding of the items container
)
}, {
duration: 1000,
easing: "easeOutQuint"
});
/*current = this.current;
$("[id^=div]").each(function() {
if(this.id != "div"+current) {
console.info(this.id + " Current: " + current);
$(this).fadeTo( 'slow', 0.1);
}
});*/
},
refresh: function(state,from,to) {
var self = this, offset = null;
this.items.each(function(i) {
var side = (i == to && from-to < 0 ) || i-to > 0 ? "left" : "right";
var mod = i == to ? (1-state) : ( i == from ? state : 1 );
var before = (i > from && i != to);
$(this).css({
webkitTransform: "matrix(1,"+(mod * (side == "right" ? -0.5 : 0.5))+",0,1,0,0) scale("+(1+((1-mod)*0.5))+")",
left: (
(-i * (self.itemWidth/2))
+ (side == "right"? -self.itemWidth/2 : self.itemWidth/2) * mod //For the space in the middle
),
zIndex: self.items.length + (side == "left" ? to-i : i-to)
});
if(!$.browser.msie)
$(this).css("opacity", 1 - Math.abs((side == "left" ? to-i : i-to))/2);
});
}
});
$.extend($.ui.coverflow, {
defaults: {
items: "> *"
}
});
})(jQuery);
One thing I did notice is that after clicking the button for about 5-10 times, the elements show up but not along with the already present divs but rather below them. I am guessing that this has something to do with the CSS of the magnifyme class (2000px), but I am not sure what it is. Is there any way I can make this work?
You need to write an additional function for the coverflow widget:
add: function(el) {
var self = this;
this.element.append(el)
this.options.items = $('> *', this.element);
this.items = $(this.options.items, this.element).bind("click", function() {
self.moveTo(this);
});
this.itemWidth = this.items.outerWidth(true);
this.moveTo(this.items.length-1);
},
and then call it like so:
$("#add").click(function() {
$("div.magnifyme").coverflow('add', "<div></div>");
});
First, you need to add a references to the jQuery UI core, and it also appears that it requires the jQuery slider plugin.
Second, in your click event you're doing a location.reload, which is refreshing the page from the server, resetting any changes you had made to the page. (if you make the DIVs much smaller you can see one flash in before the page is reloaded).
You are getting a js error on the page -- "$.widget is not a function" because you didn't include the jqueryUI library. http://jqueryui.com/
Also if you remove the location.reload line, your code will work, however, I would rewrite that script block like this, so that everything clearly runs when the document is ready:
<script type="text/javascript">
$(document).ready(function() {
$("div.magnifyme").coverflow();
$("#add").click(function() {
$(".magnifyme").append("<div id=\"div5\">hello world</div>");
$("div.magnifyme").coverflow();
});
});
</script>