最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

html - Change text color of H1 using setTimeout function in Javascript - Stack Overflow

programmeradmin2浏览0评论

I have three headings in my html. On page load I want to change the color of these headings one by one and it should start again with the first one after the last heading. I have tried setTimeout function of JS but cant get the result which I want.

It should work like this:

  • "Text 1" – Green color for 10 seconds
  • "Text 2" – Green color for 15 Seconds
  • "Text 3" – Green color for 18 seconds

After "Text 3", it should again start with "Text 1"

Below is my code.

<body onload="startAuto()">
    <h1 id="first">Text 1</h1>
    <h1 id="second">Text 2</h1>
    <h1 id="third">Text 3</h1>
</body>

I have used the following JavaScript its working first time but when it reaches to Text 3 it doesn't go back to Text 1.

function startAuto() {
  function first() {
    document.getElementById('first').style.color = "#32A067";
  }

  function second() {
    setTimeout(function() {
      document.getElementById('first').style.color = "#333";
      document.getElementById('second').style.color = "#32A067";
    }, 13000);
  }

  second();

  function third() {
    setTimeout(function() {
      document.getElementById('first').style.color = "#333";
      document.getElementById('second').style.color = "#333";
      document.getElementById('third').style.color = "#32A067";
    }, 26000);
  }

  third();
}

I have three headings in my html. On page load I want to change the color of these headings one by one and it should start again with the first one after the last heading. I have tried setTimeout function of JS but cant get the result which I want.

It should work like this:

  • "Text 1" – Green color for 10 seconds
  • "Text 2" – Green color for 15 Seconds
  • "Text 3" – Green color for 18 seconds

After "Text 3", it should again start with "Text 1"

Below is my code.

<body onload="startAuto()">
    <h1 id="first">Text 1</h1>
    <h1 id="second">Text 2</h1>
    <h1 id="third">Text 3</h1>
</body>

I have used the following JavaScript its working first time but when it reaches to Text 3 it doesn't go back to Text 1.

function startAuto() {
  function first() {
    document.getElementById('first').style.color = "#32A067";
  }

  function second() {
    setTimeout(function() {
      document.getElementById('first').style.color = "#333";
      document.getElementById('second').style.color = "#32A067";
    }, 13000);
  }

  second();

  function third() {
    setTimeout(function() {
      document.getElementById('first').style.color = "#333";
      document.getElementById('second').style.color = "#333";
      document.getElementById('third').style.color = "#32A067";
    }, 26000);
  }

  third();
}
Share Improve this question edited Apr 9, 2020 at 14:08 Mr. Polywhirl 48.9k12 gold badges94 silver badges145 bronze badges asked Apr 9, 2020 at 13:27 Faisal ShaniFaisal Shani 8201 gold badge23 silver badges52 bronze badges 3
  • if you need any more explanation about my answer, don't hesitate – Quantumass Commented Apr 9, 2020 at 14:10
  • Check out my solution, Im sure, you will like it ;) – Elman Huseynov Commented Apr 9, 2020 at 14:42
  • thanks all. I have also posted my own version of solution. – Faisal Shani Commented Apr 9, 2020 at 15:32
Add a ment  | 

4 Answers 4

Reset to default 3

Thanks for all these answers but I have found the easiest and cleanest solution myself. Just settimeout function in the previous one, in a circular fashion. Its more nicer and clear. Below is the code snippet.

<body>
    <h1 id="first">Text 1</h1>
    <h1 id="second">Text 2</h1>
    <h1 id="third">Text 3</h1>
</body>


<script>
first();

function first()
{

document.getElementById('third').style.color="#333";

document.getElementById('first').style.color="#32A067";

setTimeout(second,10000);

}


function second()
{

document.getElementById('first').style.color="#333";
document.getElementById('second').style.color="#32A067";

setTimeout(third,15000);

}



function third()
{

document.getElementById('second').style.color="#333";
document.getElementById('first').style.color="#32A067";

setTimeout(first,18000);


}
</script>

You have to use a circular array and timeout to sleep and recall the function

listElements contains all the elements you want to highlight and their highlight time

startAutoIndex will be increment each time the function is called so it will start with element id first

var startAutoIndex = 0

function startAuto() {

    let listElements = [
        {id: "first", timer: 10000}, 
        {id: "second", timer: 13000}, 
        {id: "third", timer: 26000}
    ]

    function colorHeader(currentIndex) {
        for (let index = 0; index < listElements.length; index++) {
            const element = listElements[index]
            if (currentIndex != index)
                document.getElementById(element.id).style.color = '#333'
            else {
                document.getElementById(element.id).style.color = '#32A067'
            }
        }
    }

    let currentIndex =
        ((startAutoIndex % listElements.length) + listElements.length) %
        listElements.length

    colorHeader(currentIndex)

    setTimeout(startAuto, listElements[currentIndex].timer)

    startAutoIndex = currentIndex + 1

}

You can use setTimeout together with promises to achive result you want. Check out my snippet:

var first = document.getElementById('first');
		var second = document.getElementById('second');
		var third = document.getElementById('third');



	const promiseTimeout = (delay, element, newColor) =>
	  {
	  	return new Promise((resolve, reject) => {
		    setTimeout(() => {
		    	
		      element.style.color = newColor;
		      resolve() // when this fires, .then gets called
		      
		    }, delay)
		  });
	  }

	function start(){

		first.style.color = "green";

		promiseTimeout(10000, first, "#333")
		.then(() => {
			return second.style.color = "green";
		})
		.then(() => {
			return promiseTimeout(15000, second, "#333")
		})
		.then(() => {
			third.style.color = "green";
			return promiseTimeout(18000, third, "#333")
		})
		.then(() => start());
	}

	start();
<h1 id="first">Text 1</h1>

<h1 id="second">Text 2</h1>

<h1 id="third">Text 3</h1>

<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.3.1/jquery.min.js"></script>

You can wrap the main timer inside an interval, and each highlight event as a separate timeout.

I would also add a class to the elements you want to query for, or just select all h1 elements.

You could also provided a fixed timeout, and it will calculate the timeouts between elements for you.

window.startAuto = () => {
  start({
    selector : '.highlighter',
    timeouts : [ 1000, 2000, 1000 ], // or, for a fixed timout: 1000
    callback : (el, index, activeIndex) => {
      el.classList.toggle('active', index === activeIndex);
    }
  });
};

const defaultOptions = {
  selector : '',
  timeouts : [],
  initialDelay : 0
};

const start = (options) => {
  let opts = Object.assign({}, defaultOptions, options);
  opts.elements = Array.from(document.querySelectorAll(opts.selector));
  let interval = 0;
  if (!Array.isArray(opts.timeouts)) {
    opts.timeouts = fillArray(opts.timeouts, opts.elements.length);
  }
  interval = opts.timeouts.reduce((t, x) => t + x, 0);
  opts.timeouts = normalizeTimeouts(opts.timeouts);
  setTimeout(() => {
    update(opts);
    setInterval(update, interval, opts);
  }, opts.initialDelay);
};

const normalizeTimeouts = (timeouts) => {
  return timeouts.reduce((results, timeout, index, all) => {
    return results.concat(timeout + all.slice(0, index).reduce((t, x) => t + x, 0));
  }, [0]);
};

const update = (opts) => {
  opts.timeouts.slice(0, opts.timeouts.length -1).forEach((timeout, index) => {
    setTimeout(() => {
      opts.elements.forEach((element, i) => {
        return opts.callback.call(element, element, i, index);
      });
    }, timeout);
  })
};

const fillArray = (value, count) => new Array(count).fill(value);
.active {
  color: green;
}
<body onload="startAuto()">
  <h1 class="highlighter" id="first">Text 1</h1>
  <h1 class="highlighter" id="second">Text 2</h1>
  <h1 class="highlighter" id="third">Text 3</h1>
</body>


Here is a super-dynamic; reusable class.

document.addEventListener('DOMContentLoaded', () => main());

const main = () => {
  let looper = new Looper({
    selector : '.highlighter',
    timeouts : [ 1000, 2000, 1000 ], // or, for a fixed timout: 1000
    callback : (el, index, activeIndex) => {
      el.classList.toggle('active', index === activeIndex);
    },
    initialDelay : 1000,
    autoStart : true
  })
  
  document.querySelector('#stop-btn').addEventListener('click', (e) => {
    looper.stop();
  });
  
  document.querySelector('#restart-btn').addEventListener('click', (e) => {
    looper.stop();
    looper.start();
  });
}

class Looper {
  constructor(options) {
    let opts = Object.assign({}, Looper.defaultOptions, options);
    this.elements = Array.from(document.querySelectorAll(opts.selector));
    if (!Array.isArray(opts.timeouts)) {
      opts.timeouts = this.__fillArray(opts.timeouts, this.elements.length);
    }
    this.interval = opts.timeouts.reduce((t, x) => t + x, 0);
    this.timeouts = this.__normalizeTimeouts(opts.timeouts);
    this.initialDelay = opts.initialDelay;
    this.autoStart = opts.autoStart;
    this.callback = opts.callback;
    this.__startupId = null;
    this.__processId = null;
    this.__subprocessIds = this.__fillArray(null, this.elements.length);
    
    if (this.autoStart === true) this.start();
  }
  
  start() {
    if (this.callback == null) {
      throw new Error('callback function is undefined');
    }
    if (this.__processId == null) {
      this.__startupId = setTimeout(() => {
        this.__update();
        this.__processId = setInterval(() => {
          this.__update();
        }, this.interval);
      }, this.initialDelay);
    }
  }

  stop() {
    this.__subprocessIds.forEach((id, index) => {
      if (id != null) {
        clearTimeout(id);
        this.__subprocessIds[index] = null;
      }
    });
    if (this.__processId != null) {
      clearInterval(this.__processId);
      this.__processId = null;
    }
    if (this.__startupId != null) {
      clearTimeout(this.__startupId);
      this.__startupId = null;
    }
  }

  __update() {
    let self = this;
    self.timeouts.slice(0, this.timeouts.length -1).forEach((timeout, index) => {
      self.__subprocessIds[index] = setTimeout(() => {
        self.elements.forEach((element, i) => {
          return self.callback.call(element, element, i, index);
        });
      }, timeout);
    })
  }

  __normalizeTimeouts(timeouts) {
    return timeouts.reduce((results, timeout, index, all) => {
      return results.concat(timeout + all.slice(0, index).reduce((t, x) => t + x, 0));
    }, [0]);
  }

  __fillArray(value, count) {
    return new Array(count).fill(value);
  }
}

Looper.defaultOptions = {
  selector : '',
  timeouts : [],
  initialDelay : 0,
  autoStart : false
}
.active {
  color: green;
}
<div>
  <h2 class="highlighter" id="first">Text 1</h2>
  <h2 class="highlighter" id="second">Text 2</h2>
  <h2 class="highlighter" id="third">Text 3</h2>
</div>

<button id="stop-btn">Stop</button>
<button id="restart-btn">Restart</button>

发布评论

评论列表(0)

  1. 暂无评论