I'm having problems with a functionality that I have to implement, I'm looking to do this (check the second section) -> https://www.jacquemus.com/fr/simon
The letters need to fade in and fade out, based on the scroll, this is what I got so far
<div class="ml3">
<h1>THIS IS MY TEXT THAT IT'S GOING TO SHOW IN SCROLL</h1>
</div>
:root {
--percentage: 0;
}
body {
background-color: #000;
margin: 0;
height: 120vh;
}
.ml3 {
position: sticky;
top: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
span {
font-family: Helvetica;
margin: 0;
padding: 0;
font-size: 48px;
color: #fff;
letter-spacing: -0.3px;
}
.ml3 span{
opacity: var(--percentage);
}
var textWrapper = document.querySelector('.ml3');
textWrapper.innerHTML = textWrapper.textContent.replace(/\S/g, "<span class='letter'>$&</span>");
var letter = document.querySelectorAll('.letter');
var i = 0;
var currentID = 0;
var slideCount = letter.length;
document.addEventListener('scroll', (e) => {
let scrolled = document.documentElement.scrollTop / (document.documentElement.scrollHeight - document.documentElement.clientHeight);
var nextID = currentID + 1;
if(nextID < slideCount){
letter[nextID].style.setProperty('--percentage', `${scrolled / 1}` * nextID);
}
currentID = nextID;
});
https://codepen.io/federicomartin/pen/eYdBbQm
As you can see, it's no near what I want, but I really don't know how to do it, if someone could help me, would be awesome! Thanks!
I like that effect a lot!! Thank for submitting that question! ;)
So here is a something to help you continue on this challenge.
In the scroll handler, I replaced:
var nextID = currentID + 1;
if(nextID < slideCount){
letter[nextID].style.setProperty('--percentage', `${scrolled / 1}` * nextID);
}
currentID = nextID;
with:
letter.forEach(function (l, i) {
if (i / letter.length < scrolled) {
l.style.setProperty("--percentage", 1);
}else{
l.style.setProperty("--percentage", 0);
}
});
It compares the scrolled percentage you calculated with the letter index "percentage" in the letter collection to set it's opacity to 0 or 1.
I would then adjust the scrollHeight of the body with the real text to reveal... Below, I used height: 600vh; and may be a bit too much. ;)
var textWrapper = document.querySelector(".ml3");
textWrapper.innerHTML = textWrapper.textContent.replace(
/\S/g,
"<span class='letter'>$&</span>"
);
var letter = document.querySelectorAll(".letter");
var i = 0;
var currentID = 0;
var slideCount = letter.length;
document.addEventListener("scroll", (e) => {
let scrolled =
document.documentElement.scrollTop /
(document.documentElement.scrollHeight -
document.documentElement.clientHeight);
// var nextID = currentID + 1;
// if (nextID < slideCount) {
// letter[nextID].style.setProperty(
// "--percentage",
// `${scrolled / 1}` * nextID
// );
// }
// currentID = nextID;
letter.forEach(function (l, i) {
// console.log("====",i / letter.length, i, letter.length)
if (i / letter.length < scrolled) {
l.style.setProperty("--percentage", 1);
} else {
l.style.setProperty("--percentage", 0);
}
});
});
:root {
--percentage: 0;
}
body {
background-color: #000;
margin: 0;
height: 1120vh;
}
.ml3 {
position: sticky;
top: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
span {
font-family: Helvetica;
margin: 0;
padding: 0;
font-size: 48px;
color: #fff;
letter-spacing: -0.3px;
}
.ml3 span {
opacity: var(--percentage);
}
<div class="ml3">
<h1>THIS IS MY TEXT THAT IT'S GOING TO SHOW IN SCROLL</h1>
</div>
CodePen
Related
I want to add a timer which decrease Automatically (like 10 seconds, 9 seconds... till 0 seconds) but the progress bar will increase. And I am new to javascript, and the below code also copied from another site , so please help me in adding timer inside the progress bar
Till now I did this code
I want to make like this
Demo
<div class="progress"></div>
<style>
.progress-bar {
height: 20px;
background: #1da1f2;
box-shadow: 2px 14px 15px -7px rgba(30, 166, 250, 0.36);
border-radius: 50px;
transition: all 0.5s;
}
.progress {
width: 100%;
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: start;
background: #e6e9ff;
border-radius: 20px;
box-shadow: 0px 10px 50px #abb7e9;
}
</style>
<script>
/*
* (class)Progress<nowValue, minValue, maxValue>
*/
//helper function-> return <DOMelement>
function elt(type, prop, ...childrens) {
let elem = document.createElement(type);
if (prop) Object.assign(elem, prop);
for (let child of childrens) {
if (typeof child == "string") elem.appendChild(document.createTextNode(child));
else elem.appendChild(elem);
}
return elem;
}
//Progress class
class Progress {
constructor(now, min, max, options) {
this.dom = elt("div", {
className: "progress-bar"
});
this.min = min;
this.max = max;
this.intervalCode = 0;
this.now = now;
this.syncState();
if(options.parent){
document.querySelector(options.parent).appendChild(this.dom);
}
else document.body.appendChild(this.dom)
}
syncState() {
this.dom.style.width = this.now + "%";
}
startTo(step, time) {
if (this.intervalCode !== 0) return;
this.intervalCode = setInterval(() => {
console.log("sss")
if (this.now + step > this.max) {
this.now = this.max;
this.syncState();
clearInterval(this.interval);
this.intervalCode = 0;
return;
}
this.now += step;
this.syncState()
}, time)
}
end() {
this.now = this.max;
clearInterval(this.intervalCode);
this.intervalCode = 0;
this.syncState();
}
}
let pb = new Progress(15, 0, 100, {parent : ".progress"});
//arg1 -> step length
//arg2 -> time(ms)
pb.startTo(5, 500);
//end to progress after 5s
setTimeout( () => {
pb.end()
}, 10000)
</script>
I think the core problem is that the code you copied is overly complicated especially for beginners. What I would recommend is to start from what you know and build up.
Here is the functionality you want written using only core principles of JavaScript and CSS.
let initialTime = 10; //All time in seconds
let timeLeft = initialTime;
let interval;
let progressBarTextElement = document.getElementById('progress-bar-text');
let progressBarElement = document.getElementById('progress-bar');
function render() {
let progressPercentage = (1 - (timeLeft / initialTime) ) * 100;
progressBarElement.style.width = progressPercentage + '%';
progressBarTextElement.innerHTML = timeLeft + 's';
}
function tick() {
timeLeft = timeLeft - 1;
if(timeLeft <= 0) {
clearInterval(interval); //Stops interval
}
render(); //Updates html
}
function startProgressBar() {
interval = setInterval(tick, 1000); //Will call tick every second
render();
}
startProgressBar();
html {font-family: -apple-system,BlinkMacSystemFont,"Segoe UI","Roboto","Oxygen","Ubuntu","Cantarell","Fira Sans","Droid Sans","Helvetica Neue",sans-serif;}
.progress-bar-continer {
height: 80px;
width: 100%;
position: relative;
display: flex;
justify-content: center;
align-items: center;
background-color: #406086;
}
.progress-bar {
background-color: #1b3e80;
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 0%;
transition: width 1s; /* Makes progressBar smooth */
transition-timing-function: linear; /* Try to remove this line for more tick tock feel */
}
.progress-bar-text {
color: white;
font-size: 24px;
font-weight: 700;
position: relative;
z-index: 1;
}
<div class="progress-bar-continer">
<div class="progress-bar" id="progress-bar"></div>
<div class="progress-bar-text" id="progress-bar-text"></div>
<div>
Try to understand the code best you can and you will have no problems adding any features you want on top of it. All the fancy stuff will come later with experience.
I have a graph that is rendering its values as a div inside the body element with a class according to their number values. This is working fine. But next I need to sort the divs according to their number values or background color. BUT, it needs to start on the lower left corner of the page and fan out upwards to towards the right as the numbers increase. Basically just like a line graph.
I'd like to stay away from libraries if at all possible.
How would I approach this? Thank you all.
let interval = setInterval(makeDivs, 5);
function makeDivs(){
let cont = checkHeight();
if(cont){
let div = document.createElement('div');
let randNum = Math.random() * 100;
if(randNum < 20) { div.classList.add('blue') }
if(randNum >= 20 && randNum < 40) { div.classList.add('green') }
if(randNum >= 40 && randNum < 60) { div.classList.add('yellow') }
if(randNum >= 60 && randNum < 80) { div.classList.add('orange') }
if(randNum >= 80 && randNum < 101) { div.classList.add('red') }
div.textContent = randNum.toFixed(2);
document.querySelector('body').appendChild(div);
} else {
alert('done');
clearInterval(interval);
sortDivs(); // Begin sorting divs
}
}
function checkHeight(){
let w = window.innerHeight;
let b = document.querySelector('body').offsetHeight;
if(b < w) {
return true;
} else {
return false;
}
}
function sortDivs(){
document.querySelector("body div:last-child").remove();
alert('sorting now...')
}
* { box-sizing: border-box;}
body { width: 100vw; margin: 0; padding: 0; display: flex; flex-wrap: wrap; align-items: end;}
body div { width: calc(10% + 1px); text-align: center; border: 1px solid #ddd; margin: -1px 0 0 -1px; padding: 10px;}
body div.blue { background: aqua; }
body div.green { background: green; }
body div.yellow { background: yellow; }
body div.orange { background: orange; }
body div.red { background: red; }
UPDATE!!!
So I have this so far based on the feed back down below. The problem now is the sorting is only happening laterally and not on an angle (spreading right and to the top).
let interval = setInterval(makeDivs, 10);
function makeDivs(){
let cont = checkHeight();
if(cont){
let div = document.createElement('div');
let randNum = Math.random() * 100;
if(randNum < 20) { div.classList.add('blue') }
if(randNum >= 20 && randNum < 40) { div.classList.add('green') }
if(randNum >= 40 && randNum < 60) { div.classList.add('yellow') }
if(randNum >= 60 && randNum < 80) { div.classList.add('orange') }
if(randNum >= 80 && randNum < 101) { div.classList.add('red') }
div.textContent = randNum.toFixed(2);
document.querySelector('.outPut').appendChild(div);
} else {
clearInterval(interval);
document.querySelector(".outPut div:last-child").remove();
compileArrays(); // Begin sorting divs
}
}
function checkHeight(){
let w = window.innerHeight;
let b = document.querySelector('.outPut').offsetHeight;
if(b < w) {
return true;
} else {
return false;
}
}
function compileArrays(){
let divs = document.querySelectorAll('.outPut div');
let bArr = [], gArr = [], yArr = [], oArr = [], rArr = [];
divs.forEach( (d) => {
if( d.classList.contains('blue') ){ bArr.push(d) }
if( d.classList.contains('green') ){ gArr.push(d) }
if( d.classList.contains('yellow') ){ yArr.push(d) }
if( d.classList.contains('orange') ){ oArr.push(d) }
if( d.classList.contains('red') ){ rArr.push(d) }
});
let finalArr = sortArray(bArr).concat(sortArray(gArr)).concat(sortArray(yArr)).concat(sortArray(oArr)).concat(sortArray(rArr));
newDom(finalArr);
}
function sortArray(arr){
let newArr = arr;
newArr.sort( (a, b) => {
return a.innerText - b.innerText;
});
return newArr;
}
function newDom(arr){
let b = document.querySelector('.outPut');
b.innerHTML = '';
arr.reverse();
arr.forEach((a) => {
b.appendChild(a);
});
}
* { box-sizing: border-box;}
body { width: 100vw; height: 100vh; margin: 0; padding: 0; display: flex; align-items: flex-end;}
body .outPut { flex: 1; display: flex; flex-wrap: wrap; flex-direction:row-reverse; }
body .outPut div { width: calc(10% + 1px); text-align: center; border: 1px solid #ddd; margin: -1px 0 0 -1px; padding: 10px;}
body .outPut div.blue { background: aqua; }
body .outPut div.green { background: #44df15; }
body .outPut div.yellow { background: yellow; }
body .outPut div.orange { background: orange; }
body .outPut div.red { background: red; }
<div class="outPut"></div>
Supposed you already have a mechanism to organise such DIVs in a grid as shown, the following should give you what you are looking for:
var items = divList.filter((div) => div.nodeType == 1); // get rid of the whitespace text nodes
items.sort(function(a, b) {
return a.innerHTML == b.innerHTML
? 0
: (a.innerHTML > b.innerHTML ? 1 : -1);
});
Then, place them back in the DOM as needed, example:
for (i = 0; i < items.length; ++i) {
divList.appendChild(items[i]);
}
This worked with the first code example!!!
try this sortDivs function:
function sortDivs() {
document.querySelector("body div:last-child").remove();
alert('sorting now...')
let toSort = document.getElementsByTagName("div")
toSort = Array.prototype.slice.call(toSort, 0)
toSort.sort((a, b) => {
let aord = parseFloat(a.textContent);
let bord = parseFloat(b.textContent);
return bord - aord;
})
document.body.innerHTML = ""
for(var i = 0, l = toSort.length; i < l; i++) {
document.querySelector('body').appendChild(toSort[i]);
}
}
and in the css file set flex-wrap to wrap-reverse. Hope I could help :)
PS: please, implement some else if instead of doing only if
Here is a small fiddle with my sample code demonstrating a simple solution in pure JavaScript and absolute CSS positioning for what you are trying to achieve. Link
As some pointed out already, there might be a library, that already provides a better and complete solution for this - I did not research if it is so.
Code:
file.js
var container = document.getElementById("container")
var results = [1,2,3,4,5,6,7,8]
//you can pre-calculate the order of the distances
//here already orderdered array [distanec][X-axis][Y-axis]
var distances =[[0,0,0],
[1,1,0],
[1,0,1],
[1.414, 1,1],
[2,0,2],
[2,2,0],
[2.234, 2,1],
[2.234, 1,2]]
for (i = 0; i < results.length; i++){
var newDiv = document.createElement("div")
newDiv.className = "result"
newDiv.innerHTML = results[i]
newDiv.style.left = distances[i][1]*20 + "px"
newDiv.style.bottom = distances[i][2]*20 + "px"
container.appendChild(newDiv)
}
function setColor(element){
// set class based on value - you already have this part
}
style.css
#container {
border: 4px;
border-color: red;
border-style: solid;
height: 200px;
width: 200px;
position: relative;
}
.result{
border: 2px;
width: 20px;
height: 20px;
position: absolute;
border-color: blue;
border-style: solid;
text-align: center;
}
site.html
<div id="container">
</div>
Output:
I have a yellow box in a grid. When click button 'UP' the yellow box is going one box UP. How can I stop the yellow box when it arrives at the edge? I do not want it to go out of the grid.
let moveCounter = 0;
var grid = document.getElementById("grid-box");
for (var i = 1; i <= 100; i++) {
var square = document.createElement("div");
square.className = 'square';
square.id = 'square' + i;
grid.appendChild(square);
}
var playerTwo = [];
while (playerTwo.length < 1) {
var randomIndex = parseInt(99 * Math.random());
if (playerTwo.indexOf(randomIndex) === -1) {
playerTwo.push(randomIndex);
var drawPtwo = document.getElementById('square' + randomIndex);
$(drawPtwo).addClass("p-1")
}
};
$('#button_up').on('click', function() {
moveCounter += 1;
$pOne = $('.p-1')
var id = $pOne.attr('id')
var idNumber = +id.slice(6);
var idMove = idNumber - 10
var idUpMove = 'square' + idMove;
$pOne.removeClass('p-1');
$('#' + idUpMove).addClass('p-1');
});
#grid-box {
width: 400px;
height: 400px;
margin: 0 auto;
font-size: 0;
position: relative;
}
#grid-box>div.square {
font-size: 1rem;
vertical-align: top;
display: inline-block;
width: 10%;
height: 10%;
box-sizing: border-box;
border: 1px solid #000;
}
.p-1{
background-color: yellow;
}
<div id="grid-box"></div>
<div class="move">
<button id="button_up">UP</button>
<br>
</div>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
I am new to Javascript / jQuery. Any help will be much appreciated ! Thank you
let moveCounter = 0;
var grid = document.getElementById("grid-box");
for (var i = 1; i <= 100; i++) {
var square = document.createElement("div");
square.className = 'square';
square.id = 'square' + i;
grid.appendChild(square);
}
var playerTwo = [];
while (playerTwo.length < 1) {
var randomIndex = parseInt(99 * Math.random());
if (playerTwo.indexOf(randomIndex) === -1) {
playerTwo.push(randomIndex);
var drawPtwo = document.getElementById('square' + randomIndex);
$(drawPtwo).addClass("p-1")
}
};
$('#button_up').on('click', function() {
moveCounter += 1;
$pOne = $('.p-1')
var id = $pOne.attr('id')
var idNumber = +id.slice(6);
var idMove = idNumber - 10;
if(idMove < 0){idMove +=10;}
var idUpMove = 'square' + idMove;
$pOne.removeClass('p-1');
$('#' + idUpMove).addClass('p-1');
});
#grid-box {
width: 400px;
height: 400px;
margin: 0 auto;
font-size: 0;
position: relative;
}
#grid-box>div.square {
font-size: 1rem;
vertical-align: top;
display: inline-block;
width: 10%;
height: 10%;
box-sizing: border-box;
border: 1px solid #000;
}
.p-1{
background-color: yellow;
}
<div id="grid-box"></div>
<div class="move">
<button id="button_up">UP</button>
<br>
</div>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
Here I have added the condition which restrict box to out of the grid
if(idMove < 0){idMove +=10;}
if movable position is in the minus then it again initialise it existing position.
You can add a check to stop it from moving out of the squares
var idMove = idNumber - 10
if(idMove > 0){
// do all the moving stuffs
}
$('#button_up').on('click', function() {
moveCounter += 1;
$pOne = $('.p-1')
var id = $pOne.attr('id')
var idNumber = +id.slice(6);
var idMove = idNumber - 10;
if(idMove > 0) {
var idUpMove = 'square' + idMove;
$pOne.removeClass('p-1');
$('#' + idUpMove).addClass('p-1');
}
});
You can use an if statement to check idMove > 0) If it is, then you can move your square, if it isn't then you shouldn't move your square. it will be undefined, and so you can run your code only when pOne's id is not undefined.
See example below:
let moveCounter = 0;
var grid = document.getElementById("grid-box");
for (var i = 1; i <= 100; i++) {
var square = document.createElement("div");
square.className = 'square';
square.id = 'square' + i;
grid.appendChild(square);
}
var playerTwo = [];
while (playerTwo.length < 1) {
var randomIndex = parseInt(99 * Math.random());
if (playerTwo.indexOf(randomIndex) === -1) {
playerTwo.push(randomIndex);
var drawPtwo = document.getElementById('square' + randomIndex);
$(drawPtwo).addClass("p-1")
}
};
$('#button_up').on('click', function() {
moveCounter += 1;
$pOne = $('.p-1')
var id = $pOne.attr('id')
var idNumber = +id.slice(6);
var idMove = idNumber - 10
if (idMove > 0) {
var idUpMove = 'square' + idMove;
$pOne.removeClass('p-1');
$('#' + idUpMove).addClass('p-1');
}
});
#grid-box {
width: 400px;
height: 400px;
margin: 0 auto;
font-size: 0;
position: relative;
}
#grid-box>div.square {
font-size: 1rem;
vertical-align: top;
display: inline-block;
width: 10%;
height: 10%;
box-sizing: border-box;
border: 1px solid #000;
}
.p-1 {
background-color: yellow;
}
<div id="grid-box">
</div>
<div class="move">
<button id="button_up">UP</button><br>
</div>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
I want to have a scrolling marquee that never ends, and with that, I mean that there will never be a blank space in the marquee.
So when, for example, all text has been in the screen (viewport) and the latest words are marquee'ing, the marquee will repeat without first ending the marquee (meaning: all text has gone away into the left side [marquee: right -> left]). With repeat I mean that the text will just start over right behind where the marquee is
So when I have the marquee text " Hello poeple of the earth •", and that is here:
_ = blank
! = Char of first run of marquee
^ = char of second run of marquee
& = char of third run of marquee
________!!!!!!!!!!!!!!!!!!!!!!!!!!!!****************************^^^^^^^^^^^^^^^^^^^^^^^^^^^^&&&&&&&&
Ofcourse I need it to be smooth. Something like this answer, but without the blank spaces. The use of libraries doesn't matter.
Can anyone help me?
You can use marque plugin to achieve this
$('.marquee').marquee({
//speed in milliseconds of the marquee
duration: 5000,
//gap in pixels between the tickers
gap: 0,
//time in milliseconds before the marquee will start animating
delayBeforeStart: 0,
//'left' or 'right'
direction: 'left',
//true or false - should the marquee be duplicated to show an effect of continues flow
duplicated: false
});
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script type='text/javascript' src='//cdn.jsdelivr.net/jquery.marquee/1.3.1/jquery.marquee.min.js'></script>
<body>
<div class="marquee">stuff to say 1|</div>
<div class="marquee">stuff to say 2|</div>
<div class="marquee">stuff to say 3|</div>
<div class="marquee">stuff to say 4|</div>
<div class="marquee">stuff to say 5</div>
</body>
I think this is what you want :)))
function start() {
new mq('latest-news');
mqRotate(mqr);
}
window.onload = start;
function objWidth(obj) {
if (obj.offsetWidth) return obj.offsetWidth;
if (obj.clip) return obj.clip.width;
return 0;
}
var mqr = [];
function mq(id) {
this.mqo = document.getElementById(id);
var wid = objWidth(this.mqo.getElementsByTagName("span")[0]) + 5;
var fulwid = objWidth(this.mqo);
var txt = this.mqo.getElementsByTagName("span")[0].innerHTML;
this.mqo.innerHTML = "";
var heit = this.mqo.style.height;
this.mqo.onmouseout = function () {
mqRotate(mqr);
};
this.mqo.onmouseover = function () {
clearTimeout(mqr[0].TO);
};
this.mqo.ary = [];
var maxw = Math.ceil(fulwid / wid) + 1;
for (var i = 0; i < maxw; i++) {
this.mqo.ary[i] = document.createElement("div");
this.mqo.ary[i].innerHTML = txt;
this.mqo.ary[i].style.position = "absolute";
this.mqo.ary[i].style.left = wid * i + "px";
this.mqo.ary[i].style.width = wid + "px";
this.mqo.ary[i].style.height = heit;
this.mqo.appendChild(this.mqo.ary[i]);
}
mqr.push(this.mqo);
}
function mqRotate(mqr) {
if (!mqr) return;
for (var j = mqr.length - 1; j > -1; j--) {
maxa = mqr[j].ary.length;
for (var i = 0; i < maxa; i++) {
var x = mqr[j].ary[i].style;
x.left = parseInt(x.left, 10) - 1 + "px";
}
var y = mqr[j].ary[0].style;
if (parseInt(y.left, 10) + parseInt(y.width, 10) < 0) {
var z = mqr[j].ary.shift();
z.style.left = parseInt(z.style.left) + parseInt(z.style.width) * maxa + "px";
mqr[j].ary.push(z);
}
}
mqr[0].TO = setTimeout("mqRotate(mqr)", 20);
}
.marquee {
position: relative;
overflow: hidden;
text-align: center;
margin: 0 auto;
width: 100%;
height: 30px;
display: flex;
align-items: center;
white-space: nowrap;
}
#latest-news {
line-height: 32px;
a {
color: #555555;
font-size: 13px;
font-weight: 300;
&:hover {
color: #000000;
}
}
span {
font-size: 18px;
position: relative;
top: 4px;
color: #999999;
}
}
<div id="latest-news" class="marquee">
<span style="white-space:nowrap;">
<span> •</span>
one Lorem ipsum dolor sit amet
<span> •</span>
two In publishing and graphic design
<span> •</span>
three Lorem ipsum is a placeholder text commonly
</span>
</div>
Thank You sire.....I get it....What I need....
function start() {
new mq('latest-news');
mqRotate(mqr);
}
window.onload = start;
function objWidth(obj) {
if (obj.offsetWidth) return obj.offsetWidth;
if (obj.clip) return obj.clip.width;
return 0;
}
var mqr = [];
function mq(id) {
this.mqo = document.getElementById(id);
var wid = objWidth(this.mqo.getElementsByTagName("span")[0]) + 5;
var fulwid = objWidth(this.mqo);
var txt = this.mqo.getElementsByTagName("span")[0].innerHTML;
this.mqo.innerHTML = "";
var heit = this.mqo.style.height;
this.mqo.onmouseout = function () {
mqRotate(mqr);
};
this.mqo.onmouseover = function () {
clearTimeout(mqr[0].TO);
};
this.mqo.ary = [];
var maxw = Math.ceil(fulwid / wid) + 1;
for (var i = 0; i < maxw; i++) {
this.mqo.ary[i] = document.createElement("div");
this.mqo.ary[i].innerHTML = txt;
this.mqo.ary[i].style.position = "absolute";
this.mqo.ary[i].style.left = wid * i + "px";
this.mqo.ary[i].style.width = wid + "px";
this.mqo.ary[i].style.height = heit;
this.mqo.appendChild(this.mqo.ary[i]);
}
mqr.push(this.mqo);
}
function mqRotate(mqr) {
if (!mqr) return;
for (var j = mqr.length - 1; j > -1; j--) {
maxa = mqr[j].ary.length;
for (var i = 0; i < maxa; i++) {
var x = mqr[j].ary[i].style;
x.left = parseInt(x.left, 10) - 1 + "px";
}
var y = mqr[j].ary[0].style;
if (parseInt(y.left, 10) + parseInt(y.width, 10) < 0) {
var z = mqr[j].ary.shift();
z.style.left = parseInt(z.style.left) + parseInt(z.style.width) * maxa + "px";
mqr[j].ary.push(z);
}
}
mqr[0].TO = setTimeout("mqRotate(mqr)", 20);
}
.marquee {
position: relative;
overflow: hidden;
text-align: center;
margin: 0 auto;
width: 100%;
height: 30px;
display: flex;
align-items: center;
white-space: nowrap;
}
#latest-news {
line-height: 32px;
a {
color: #555555;
font-size: 13px;
font-weight: 300;
&:hover {
color: #000000;
}
}
span {
font-size: 18px;
position: relative;
top: 4px;
color: #999999;
}
}
<div id="latest-news" class="marquee">
<span style="white-space:nowrap;">
<span> •</span>
one Lorem ipsum dolor sit amet
<span> •</span>
two In publishing and graphic design
<span> •</span>
three Lorem ipsum is a placeholder text commonly
</span>
</div>
Title says it all really. Here is an example of what I'm trying to achieve navigation color change image based on background
The problem is that it needs to work with a site that's using a scroll-jacking parallax type effect, here is the site I'm trying to achieve this effect with demo website
Modify the scroll script a bit
Check demo here
Created the function toggleHeaderColor to check the current section. Since the scroll script is indexing each section in order 0 (i.e. section_1) ,1 (i.e. section_2),2 (i.e. section_2),3 (i.e. section_3),4 (i.e. section_2) and so on. Every time you scroll it gets updated.
In scroll script there are two function nextItem() and previousItem()form which we get the current slide index and on that we can call our function to toggle dark class on header elements.
JS:
var sectionBlock = $(".section-item");
var getCurrentSlideAttr = 0;
function toggleHeaderColor(getCurrentSlideAttr) {
if (getCurrentSlideAttr == 0) {
$(".menu-link, .menu-link-logo, .menu-link-last").removeClass("dark");
}
if (getCurrentSlideAttr == 1) {
$(".menu-link, .menu-link-logo, .menu-link-last").addClass("dark");
}
if (getCurrentSlideAttr == 2) {
$(".menu-link, .menu-link-logo, .menu-link-last").removeClass("dark");
}
if (getCurrentSlideAttr == 3) {
$(".menu-link, .menu-link-logo, .menu-link-last").removeClass("dark");
}
if (getCurrentSlideAttr == 4) {
$(".menu-link, .menu-link-logo, .menu-link-last").addClass("dark");
}
}
var ticking = false;
var isFirefox = /Firefox/i.test(navigator.userAgent);
var isIe =
/MSIE/i.test(navigator.userAgent) ||
/Trident.*rv\:11\./i.test(navigator.userAgent);
var scrollSensitivitySetting = 30;
var slideDurationSetting = 800;
var currentSlideNumber = 0;
var totalSlideNumber = $(".section-item").length;
function parallaxScroll(evt) {
if (isFirefox) {
delta = evt.detail * -120;
} else if (isIe) {
delta = -evt.deltaY;
} else {
delta = evt.wheelDelta;
}
if (ticking != true) {
if (delta <= -scrollSensitivitySetting) {
ticking = true;
if (currentSlideNumber !== totalSlideNumber - 1) {
currentSlideNumber++;
nextItem();
}
slideDurationTimeout(slideDurationSetting);
}
if (delta >= scrollSensitivitySetting) {
ticking = true;
if (currentSlideNumber !== 0) {
currentSlideNumber--;
}
previousItem();
slideDurationTimeout(slideDurationSetting);
}
}
}
function slideDurationTimeout(slideDuration) {
setTimeout(function() {
ticking = false;
}, slideDuration);
}
var mousewheelEvent = isFirefox ? "DOMMouseScroll" : "wheel";
window.addEventListener(mousewheelEvent, _.throttle(parallaxScroll, 60), false);
function nextItem() {
getCurrentSlideAttr = currentSlideNumber;
toggleHeaderColor(getCurrentSlideAttr);
var $previousSlide = $(".section-item").eq(currentSlideNumber - 1);
$previousSlide
.css("transform", "translate3d(0,-130vh,0)")
.find(".content-wrapper")
.css("transform", "translateY(40vh)");
currentSlideTransition();
}
function previousItem() {
//console.log($(".section-item").eq(currentSlideNumber).attr('id'))
getCurrentSlideAttr = currentSlideNumber;
toggleHeaderColor(getCurrentSlideAttr);
var $previousSlide = $(".section-item").eq(currentSlideNumber + 1);
$previousSlide
.css("transform", "translate3d(0,30vh,0)")
.find(".content-wrapper")
.css("transform", "translateY(30vh)");
currentSlideTransition();
}
function currentSlideTransition() {
var $currentSlide = $(".section-item").eq(currentSlideNumber);
$currentSlide
.css("transform", "translate3d(0,-15vh,0)")
.find(".content-wrapper")
.css("transform", "translateY(15vh)");
}
Update
You can actually choose a specific text color over white/black backgrounds using css blend modes.
Example with specific colors (green over white and red over black in this case):
html, body {
margin: 0;
}
h1 {
position: fixed; top: 0; left: 0;
width: 100vw;
text-align: center;
mix-blend-mode: difference;
color: white;
z-index: 1;
}
div {
position: relative;
width: 100vw;
height: 100vh;
background: white;
margin: 0;
}
div:nth-of-type(2n) {
background: black;
}
div:after {
content: '';
position: absolute; top: 0; left: 0;
width: 100%;
height: 100%;
z-index: 2;
}
div:nth-of-type(2n):after {
background: red;
mix-blend-mode: multiply;
}
div:nth-of-type(2n + 1):after {
background: green;
mix-blend-mode: screen;
}
<h1>Scroll to see effect</h1>
<div></div>
<div></div>
<div></div>
I think the only way you would be able to choose the exact partial colors using SVG text or paths.
A simple example with mix-blend-mode:
html, body {
margin: 0;
}
h1 {
position: fixed; top: 0; left: 0;
width: 100vw;
text-align: center;
mix-blend-mode: difference;
color: white;
z-index: 1;
}
div {
width: 100vw;
height: 100vh;
background: black;
}
div:nth-of-type(2n) {
background: white;
}
<h1>Scroll to see effect</h1>
<div></div>
<div></div>
<div></div>
Browser support
https://css-tricks.com/reverse-text-color-mix-blend-mode/
Try Adding mix-blend-mode property.
Add this property to your .navigation-menu class
CSS
.navigation-menu{
mix-blend-mode: difference;
}
Hope this Helps...