Updating attribute value in Loop - Reactjs - javascript

I am trying to make a image slide from left to write and right to left infinitely in a loop in my react component.
I am not able to change the left property of the style attribute.
Here is the relevant piece of code
let lastRight = 0;
let multiplier = 1;
const images = [One, Two, Three, Four];
class ImageStream extends Component {
state = {
position: [0, 640, 1280, 1920]
};
changeLeft() {
if (lastRight > 2000) {
multiplier = -1;
} else if (lastRight < -600) {
multiplier = 1;
}
for (let i = 0; i < this.state.position.length; i++) {
this.state.position[i] = (this.state.position[i] + (multiplier * 1));
lastRight = this.state.position[i];
}
}
componentDidMount() {
this.intervalID = setInterval(this.changeLeft.bind(this), 200);
}
componentWillUnmount() {
// use intervalId from the state to clear the interval
clearInterval(this.intervalId);
}
renderImage(imageUrl, index) {
return (
<img
src={imageUrl}
style={{ left: this.state.position[index] }}
key={index + "_image"}
/>
);
}
render() {
return (
<div id="image-scroll" className="mt-4">
{images.map((imageUrl, index) => this.renderImage(imageUrl, index))}
</div>
);
}
}
export default ImageStream;
What I am expecting is that the left property of the style attribute of the image changes because the position arrays is changing regularly.
I am fairly new to React and would love to know if I am doing this wrong/right.
Thank you in advance for looking into it.

You were not using setState to change the state, also tweaked a few numbers and CSS to get the things running. Do check it out
let lastRight = 0;
let multiplier = 1;
const images = ["One", "Two", "Three", "Four"];
class ImageStream extends React.Component {
state = {
position: [0, 640, 1280, 1920]
};
changeLeft() {
if (lastRight > 2000) {
multiplier = -1;
} else if (lastRight < -600) {
multiplier = 1;
}
let posArr = [...this.state.position]
for (let i = 0; i < posArr.length; i++) {
let pos = posArr[i]
, newPos = pos + (multiplier * 10)
posArr[i] = newPos
this.setState({ position: posArr })
lastRight = newPos
}
}
componentDidMount() {
this.changeLeft = this.changeLeft.bind(this)
this.intervalID = setInterval(this.changeLeft, 10);
}
componentWillUnmount() {
// use intervalId from the state to clear the interval
clearInterval(this.intervalId);
}
renderImage(imageUrl, index) {
return (
<img
src={imageUrl}
style={{ left: this.state.position[index] }}
key={index + "_image"}
/>
);
}
render() {
return (
<div id="image-scroll" className="mt-4">
{images.map((imageUrl, index) => this.renderImage(imageUrl, index))}
</div>
);
}
}
// Render it
ReactDOM.render(
<ImageStream />,
document.getElementById("react")
);
img{ position: relative; width: 100px; height: 100px; outline: 1px solid blue;}
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Related

How to re-render the DOM quickest in react

I am Trying to move a text across the screen on a fixed amount of time and for that I have come up with the following code
import React, { Component, useState, useEffect, useRef } from "react";
import { PrismCode } from "react-prism";
import { Player, ControlBar } from "video-react";
import { Button } from "reactstrap";
import { getSub_Millis } from "../../services/srtreader";
export default function Rythmoband(props) {
const initialPosition = useRef(
props.rythmoPosition === undefined ? "30%" : props.rythmoPosition
);
const [number, setnumber] = useState(
props.dialogueNumber === undefined ? 0 : props.dialogueNumber
);
const [timerCheck, setTimerCheck] = useState(true);
const [moverNumber, setMoverNumber] = useState(0.001);
const [currentTime, setCurrentTime] = useState(0);
const textMover = () => {
let x = parseFloat(initialPosition.current);
let start = getSub_Millis(props.time[number][0]);
let end = getSub_Millis(props.time[number][1]);
let timeToMove = start - end;
setMoverNumber((timeToMove / 2500) * props.player.playbackRate);
setCurrentTime(props.time.currentTime);
x = x + moverNumber;
let y = `${x}%`;
initialPosition.current = y;
};
setTimeout(() => {
textMover();
timercheck();
backChecker();
}, 0.1);
const timercheck = () => {
if (
getSub_Millis(props.time[number][1]) - props.player.currentTime * 1000 <
1
) {
initialPosition.current = "30%";
setnumber(number + 1);
}
};
const backChecker = () => {
for (let index = 0; index < props.time.length; index++) {
if (
getSub_Millis(props.time[index][1]) > props.player.currentTime * 1000 &&
getSub_Millis(props.time[index][0]) < props.player.currentTime * 1000
) {
setnumber(index);
}
}
};
return (
<>
<div
style={{
width: window.innerWidth,
background: "#FF8232",
marginTop: "20px",
height: "75px",
position: "relative",
border: "5px solid black",
}}
>
<div
style={{
width: "5px",
background: "red",
marginTop: "20px",
height: "75px",
position: "absolute",
top: "-25%",
left: "25%",
}}
></div>
<strong
style={{
position: "absolute",
left: initialPosition.current,
top: "25%",
fontSize: "2rem",
}}
>
{props.dialogue[number]}
</strong>
</div>
</>
);
}
In the above code setTimeout is responsible for calling the same functions repeatedly after a set time which in turn moves the text across the screen in a calculated manner. Now the problem is that the text element's movement is blocky rather then smooth although I have tried altering the time intervals and the movement speeds as well. I would appreciate if some one could help me figure out a better way to make the text move smoother.
For performance, avoid updating state everytime
The setTimeout accepts milliseconds, means 0.1milliseconds is very hard for performance, maybe 0.1 seconds.
There are lot of animation packages on React, this one is very mechanic
The solution: Use css transition instead

Is there a way to make a big loop work in react?

I'm trying to build a 10x10 grid with a for loop in React. But React doesn't let me perform this function because it says that it exceed the maximum of actions performed. Is there a way to generate this 10x10 grid without the use of the loop?
Any help I would really appreciate it. I'm building the battleship project.
import React, {useEffect ,useState} from 'react'
import Ship from '../components/ShipGenerate.js'
import '../style/style.css'
function Grid(props) {
const [grid, setGrid] = useState([])
console.log(grid)
useEffect(() => {
// Here we push the result boxes to random generated arrays in different positions. We put it inside a useEffect so it only changes the array once
for (i = 0; i < props.data[0].size; i++) {
let result = randomNumberArray.map(function(val){return ++val;})
let finalResult = randomNumberArray.push(result[i])
}
for (i = 0; i < props.data[1].size; i++) {
let result2 = randomNumberArray2.map(function(val) {return ++val})
let secondResult = randomNumberArray2.push(result2[i])
}
for (i = 0; i < props.data[2].size; i++) {
let result = randomNumberArray3.map(function(val){return ++val;})
let finalResult = randomNumberArray3.push(result[i])
}
for (i = 0; i < props.data[3].size; i++) {
let result2 = randomNumberArray4.map(function(val) {return ++val})
let secondResult = randomNumberArray4.push(result2[i])
}
for (i = 0; i < props.data[4].size; i++) {
let result2 = randomNumberArray5.map(function(val) {return ++val})
let secondResult = randomNumberArray5.push(result2[i])
}
}, [])
let randomNumberArray = [...Array(1)].map(()=>(Math.random() * 7 | 0) + 11 * (Math.random() * 10 | 0))
let randomNumberArray2 = [...Array(1)].map(()=>(Math.random() * 7 | 0) + 11 * (Math.random() * 10 | 0))
let randomNumberArray3 = [...Array(1)].map(()=>(Math.random() * 7 | 0) + 11 * (Math.random() * 10 | 0))
let randomNumberArray4 = [...Array(1)].map(()=>(Math.random() * 7 | 0) + 11 * (Math.random() * 10 | 0))
let randomNumberArray5 = [...Array(1)].map(()=>(Math.random() * 7 | 0) + 11 * (Math.random() * 10 | 0))
// We generate the 10x10 grid
for (var i = 0; i < 110; i++) {
if (randomNumberArray.includes(i)) { // ---> checking with this condition if the index in the random array to give it a different className
setGrid([...grid,<button className="hello"></button>])
}
else if (randomNumberArray2.includes(i)) {
setGrid([...grid,<button className="hello"></button>])
}
else if (randomNumberArray3.includes(i)) {
setGrid([...grid,<button className="hello"></button>])
}
else if (randomNumberArray4.includes(i)) {
setGrid([...grid,<button className="hello"></button>])
}
else if (randomNumberArray5.includes(i)) {
setGrid([...grid,<button className="hello"></button>])
}
else {
setGrid([...grid,<button className="boxGrid"></button>])
}
}
const onClick = (e) => {
e.preventDefault()
e.target.textContent = "x"
props.setTurn(false)
}
return (
<div>
<div onClick={onClick} className="box">
{grid}
</div>
</div>
)
}
export default Grid
Trying to figure out how your trying to create the game, and correct it.
I thought it might be easier to create a simple example that you could use as a starting point.
Below is a 10x10 grid, I've randomly created ships, I'll leave it to you to update to create proper ships etc, and handle players & game logic.
const {useState} = React;
let board;
function createBoard() {
//create battlefield board
board = new Array(10);
for (let i=0; i<board.length; i+=1)
board[i] = new Array(10).fill(0);
const rnd = r => Math.trunc(Math.random() * r);
//board values
//0 = empty
//1 = ship
//2 = empty missed shot
//3 = ship hit
//fill some random ship
for (let l=0; l<40;l +=1) {
board[rnd(10)][rnd(10)] = 1;
}
}
createBoard();
function Piece(p) {
const [value, setValue] = useState(board[p.y][p.x]);
const cls = ['piece'];
let txt = '.';
if (value === 2) cls.push('empty-shot');
if (value === 3) { cls.push('boom'); txt = '*' }
return <div
onClick={() => {
let c = board[p.y][p.x];
if (c > 1) return;
if (c === 0) c = 2;
else if (c === 1) c = 3;
board[p.y][p.x] = c;
setValue(c);
}}
className={cls.join(' ')}>
{txt}
</div>
}
function Board() {
return <div className="board">{
board.map((b,iy) =>
<div key={iy}>
{b.map((a,ix) => <Piece key={ix} x={ix} y={iy}/>)}
</div>
)}</div>
}
function Game() {
const [gameCount, setGameCount] = useState(1);
return <div>
<div style={{marginBottom: "1rem"}}><button onClick={() => {
createBoard();
setGameCount(c => c + 1);
}}>Clear</button></div>
<Board key={gameCount}/>
</div>
}
ReactDOM.render(<Game/>, document.querySelector('#mount'));
.board {
display: inline-block;
background-color: black;
border: 0.3em solid black;
}
.piece {
display: inline-grid;
width: 30px;
height: 30px;
background-color: cyan;
border: 0.2em solid black;
align-content: center;
justify-items: center;
cursor: pointer;
user-select: none;
}
.piece.empty-shot {
color: white;
background-color: navy;
}
.piece.boom {
background-color: red;
color: white;
}
<script crossorigin src="https://unpkg.com/react#17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.development.js"></script>
<div id="mount"></div>

Jquery UI Dragabble is not enabled

class Cell {
constructor(game, index) {
this.isEmpty = false;
this.game = game;
this.index = index;
this.height = (game.height / game.dimension);
this.width = (game.width / game.dimension);
this.id = "cell-" + index;
this.cell = this.createCell();
$("#content").append(this.cell);
if (this.index === this.game.dimension * this.game.dimension - 1) {
this.isEmpty = true;
return;
}
this.setImage();
this.setPosition(this.index)
}
createCell() {
const cell = document.createElement("div");
$(cell).css({
"width": this.height + "px",
"height": this.width + "px",
"position": "absolute",
"border": "1px solid #fff"
})
$(cell).attr("id", this.id);
//On click Move to the Empty Space
$(cell).on("click", () => {
if (this.game.gameStarted) {
let validCells = this.game.checkValidCells();
let compareCells = [];
if (validCells.right) {
compareCells.push(this.game.cells[validCells.right].cell);
}
if (validCells.left || validCells.left === 0) {
compareCells.push(this.game.cells[validCells.left].cell);
}
if (validCells.top || validCells.top === 0) {
compareCells.push(this.game.cells[validCells.top].cell);
}
if (validCells.bottom) {
compareCells.push(this.game.cells[validCells.bottom].cell);
}
let i = this.game.cells.findIndex(item => item.cell === cell);
let j = this.game.findEmptyCell();
if (compareCells.indexOf(cell) != -1) {
[this.game.cells[i], this.game.cells[j]] = [this.game.cells[j], this.game.cells[i]];
this.game.cells[i].setPosition(i);
this.game.cells[j].setPosition(j);
if (this.game.checkWin()) {
alert("you won the game!!");
this.game.numberOfMoves = 0;
this.game.gameStarted = false;
}
this.game.numberOfMoves++;
$("#moves").html("Moves: " + this.game.numberOfMoves);
}
this.game.dragTheTile();
}
})
return cell;
}
setImage() {
const left = this.width * (this.index % this.game.dimension);
const top = this.height * Math.floor(this.index / this.game.dimension);
const bgPosition = -left + "px" + " " + -top + "px";
const bgSize = this.game.width + "px " + this.game.height + "px"
$(this.cell).css({
"background": 'url(' + this.game.imageSrc + ')',
"background-position" : bgPosition,
"background-size": bgSize
})
}
setPosition(index) {
const {left, top} = this.getPosition(index);
$(this.cell).css({
"left": left + "px",
"top": top + "px"
})
}
makeDraggable(index) {
let emptyCellIndex = this.game.findEmptyCell();
$(this.cell).draggable({
containment: "parent",
snap: this.game.cells[emptyCellIndex],
cursor: "move",
snapMode: "inner",
snapTolerance: 20,
helper: "clone",
opacity: 0.5
})
}
makeDroppable(index) {
$(this.cell).droppable({
drop: (event, ui) => {
let draggedCell;
draggedCell = ui.draggable;
let i = this.game.cells.findIndex(item => item.cell === draggedCell[0]);
let j = this.game.findEmptyCell();
[this.game.cells[i], this.game.cells[j]] = [this.game.cells[j], this.game.cells[i]];
this.game.cells[i].setPosition(i);
this.game.cells[j].setPosition(j);
this.game.clearDrag();
this.game.numberOfMoves++;
$("#moves").html("Moves: " + this.game.numberOfMoves);
if (this.game.checkWin()) {
alert("you won the game!!");
this.game.numberOfMoves = 0;
this.game.gameStarted = false;
} else {
this.game.dragTheTile();
}
}
})
}
getPosition(index) {
return {
left: this.width * (index % this.game.dimension),
top: this.height * Math.floor(index / this.game.dimension)
}
}
}
class GameBoard {
constructor(dimension){
this.dimension = dimension;
this.imageSrc = 'https://i.ibb.co/1XfXq6S/image.jpg'
this.cells = [];
let length = Math.min(window.innerHeight, window.innerWidth);
this.width = length - 100;
this.height = length - 100;
this.setup();
this.gameStarted = false;
this.numberOfMoves = 0;
}
setup() {
for(let i = 0;i < this.dimension * this.dimension; i++) {
this.cells.push(new Cell(this, i));
}
}
shuffle() {
for (let i = this.cells.length -1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[this.cells[i], this.cells[j]] = [this.cells[j], this.cells[i]];
this.cells[i].setPosition(i);
this.cells[j].setPosition(j);
}
}
findEmptyCell() {
return this.cells.findIndex(cell => cell.isEmpty)
}
checkValidCells() {
const emptyCell = this.findEmptyCell(),
topCell = emptyCell - this.dimension,
leftCell = emptyCell - 1,
rightCell = emptyCell + 1,
bottomCell = emptyCell + this.dimension;
const mod = emptyCell % this.dimension;
let left, right, top, bottom;
if (mod != 0) {
left = leftCell;
}
if (mod != this.dimension -1) {
right = rightCell;
}
if (emptyCell >= this.dimension) {
top = topCell;
}
if (emptyCell < this.dimension * (this.dimension - 1)) {
bottom = bottomCell
}
return {right: right, left: left, top: top, bottom: bottom};
}
findPosition(index) {
return this.cells.findIndex(cell => cell.index === index);
}
checkWin() {
for (let i = 0; i < this.cells.length; i++) {
if (i != this.cells[i].index) {
return false;
}
}
return true;
}
clearDrag() {
this.cells.forEach(cell => {
if($(cell.cell).data('ui-draggable')) $(cell.cell).draggable("destroy");
})
}
dragTheTile() {
this.clearDrag();
const validCells = this.checkValidCells();
let availableCells = [];
if (validCells.right) {
availableCells.push(this.cells[this.findPosition(validCells.right)].index);
}
if (validCells.left || validCells.left === 0) {
availableCells.push(this.cells[this.findPosition(validCells.left)].index);
}
if (validCells.top || validCells.top === 0) {
availableCells.push(this.cells[this.findPosition(validCells.top)].index);
}
if (validCells.bottom) {
availableCells.push(this.cells[this.findPosition(validCells.bottom)].index);
}
let emptyCellIndex = this.findEmptyCell();
availableCells.forEach(cell => {
this.cells[cell].makeDraggable(cell);
this.cells[emptyCellIndex].makeDroppable(cell);
})
}
solve() {
let i;
for (i = 0; i < this.cells.length; i++) {
let j = this.cells[i].index;
if (i != j) {
[this.cells[i], this.cells[j]] = [this.cells[j], this.cells[i]];
this.cells[i].setPosition(i);
this.cells[j].setPosition(j);
i--;
}
if (i === this.cells.length - 1) {
[this.cells[i], this.cells[i - 1]] = [this.cells[i - 1], this.cells[i]];
this.cells[i].setPosition(i);
this.cells[i - 1].setPosition(i - 1);
}
}
}
}
$(document).ready(() => {
let gb;
$("#startGame").on("click", () => {
gb.gameStarted = true;
gb.shuffle();
gb.numberOfMoves = 0;
$("#moves").html("Moves: " + gb.numberOfMoves);
gb.clearDrag();
gb.dragTheTile();
})
$("#solve").on("click", () => {
if (gb.gameStarted) {
gb.solve();
gb.clearDrag();
gb.dragTheTile();
}
})
$("#generate-puzzle").on("click", () => {
let number = parseInt($("#dimension").val());
if(number >= 3 && Number.isInteger(number)) {
gb = new GameBoard(number);
$("#content").css("display", "block");
$("#solve").css("display", "block");
$("#startGame").css("display", "block");
$("#enter-dimension").css("display", "none");
$("#content").css({
width: gb.width + "px",
height : gb.height + "px"
})
} else {
$("#alert").css("display", "block");
}
})
})
body {
background-color: #3d3d3d;
}
#content {
width: 400px;
height : 400px;
background-color: #fff;
margin: auto;
position: relative;
display: none;
}
#startGame {
margin: auto;
display: none;
}
#solve {
margin: auto;
display: none;
}
#alert {
display: none;
}
#moves {
margin: auto;
padding: 5px;
text-align: center;
color: #FFFF00;
}
#enter-dimension {
margin: auto;
}
#label-dimension {
color: #ddd;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- JQuery -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<!-- Bootstrap -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js" integrity="sha512-uto9mlQzrs59VwILcLiRYeLKPPbS/bT71da/OEBYEwcdNUk8jYIy+D176RYoop1Da+f9mvkYrmj5MCLZWEtQuA==" crossorigin="anonymous"></script>
<title>Image Puzzle</title>
</head>
<body>
<div class="container col-md-6">
<div id="moves">
Moves : 0
</div>
<div class="d-flex justify-content-center row">
<div class="col-md-6">
<div class="mt-5" id="enter-dimension">
<form>
<div class="form-group">
<label id="label-dimension" for="dimension">Enter the Dimension of the puzzle</label>
<input type="number" class="form-control" id="dimension">
</div>
<div class="alert alert-danger" id="alert" role="alert">
Enter a Valid Positive Integer Greater than or Equal to 3
</div>
<button type="button" class="btn btn-primary" id="generate-puzzle">Generate the Puzzle</button>
</form>
</div>
</div>
</div>
<div class="row">
<!--The GRid Layout and the tiles -->
<div class="mt-3" id="content">
</div>
</div>
<!--Button to Start the Game -->
<div class="row buttons">
<button type="button" class="btn btn-info mt-2" id="startGame">Start Game</button>
<button type="button" class="btn btn-success mt-2" id="solve">Solve This!</button>
</div>
</div>
</body>
</html>
The puzzle works perfectly but with one issue. If I drag-drop a cell to an empty cell I am unable to drag and drop that tile again to its previous position which is the current empty cell. The way I see it there is a problem somewhere in makeDraggable() and dragTheTile() functions.
When I move a cell with a mouse click I can drag and drop that same cell to its previous position (which is the current empty cell) or If I drag and drop a cell to an empty space I can move it to its previous position (which is the current empty cell) with mouse click. But after dragging the same cell cannot be dragged again. looks like draggable() is disabled for that particular cell.
Once a cell is dragged, The next move it should be a draggable cell (since it is a neighbour cell to the empty cell) When I make it draggable the "ui-draggable" class is added to it but "ui-draggable-handle" class is missing.
The problem was with the function where I cleared the draggable property:
clearDrag() {
this.cells.forEach(cell => {
if($(cell.cell).data('ui-draggable')) $(cell.cell).draggable("destroy");
})
}
The "destroy" method gives some conflicts.
The alternative method I found was to first initialize all the cells with draggable property but disable it in the beginning and enabling it again when I need.
the property used here was "disabled: true" and "disabled: false".
Instead of the dragTheTile() function I wrote a new function called dragTile() as follows:
dragTile() {
this.cells.forEach(cell => {
cell.makeDraggable();
})
const validCells = this.checkValidCells();
let availableCells = [];
if (validCells.right) {
availableCells.push(this.cells[this.findPosition(validCells.right)].index);
}
if (validCells.left || validCells.left === 0) {
availableCells.push(this.cells[this.findPosition(validCells.left)].index);
}
if (validCells.top || validCells.top === 0) {
availableCells.push(this.cells[this.findPosition(validCells.top)].index);
}
if (validCells.bottom) {
availableCells.push(this.cells[this.findPosition(validCells.bottom)].index);
}
let emptyCellIndex = this.findEmptyCell();
availableCells.forEach(cell => {
$(this.cells[cell].cell).draggable({disabled: false});
})
this.cells[emptyCellIndex].makeDroppable(availableCells);
}
This solved the problem very easily.

How to add animation to photos changing every 3 seconds?

The pictures change themselves every 3 seconds.
I would like to add simple animation to the photo during the change.
Preferably in vaniilla js.
let index = 1;
const changeImg = () => {
index++;
img.setAttribute('src', `img/img${index}.png`);
if (index === 3) {
index = 0;
}
};
setInterval(changeImg, 3000);
If you use something like animate.css, or create your own animation class you could do it like this:
(Im assuming you're getting the image by a query selector/getElementById)
let index = 1;
const changeImg = () => {
index++;
img.classList.add('animate__animated');
img.classList.add('animate__bounce');
setTimeout(() => {
img.setAttribute('src', `img/img${index}.png`);
img.classList.remove('animate__animated');
img.classList.remove('animate__bounce');
}, 300); // This delay is assuming the animation duration is 300ms, you need to change this to the length of the animation
if (index === 3) {
index = 0;
}
};
setInterval(changeImg, 3000);
As you suggested an example in vanilla JavaScript (no libraries), here you go.
(function slideShow() {
let imgs = [
"https://picsum.photos/id/237/200/300",
"https://picsum.photos/id/238/200/300",
"https://picsum.photos/id/239/200/300"
];
let index = 0;
const frontImg = document.getElementById("slideshow__img--front");
const backImg = document.getElementById("slideshow__img--back");
frontImg.src = imgs[index];
const changeSlideShowImg = () => {
const currImgSrc = imgs[index];
index++;
if (index >= imgs.length) index = 0;
const newImgSrc = imgs[index];
backImg.src = newImgSrc;
frontImg.classList.add("slideshow__img--fadeout");
setTimeout(() => {
frontImg.src = newImgSrc;
frontImg.classList.remove("slideshow__img--fadeout");
}, 500);
};
setInterval(changeSlideShowImg, 3000);
})()
.slideshow {
width: 200px;
height: 300px;
position: relative;
}
.slideshow__img {
position: absolute;
left: 0;
top: 0;
opacity: 1;
}
#slideshow__img--front {
z-index: 2;
}
.slideshow__img.slideshow__img--fadeout {
transition: opacity 0.5s ease-in;
opacity: 0;
}
<div class="slideshow">
<img id="slideshow__img--front" class="slideshow__img" />
<img id="slideshow__img--back" class="slideshow__img" />
</div>

How to use a html5 canvas that is based on ID twice on same page

I'm working on canvas here I want to use same canvas multiple times on the same page I tried using the class name getElementsByClassName and using query selector also. but it's not working. Can anyone point me in the right direction what might be the issue here how can I achieve? in both boxes box1, box2 I want to add same canvas.
const noise = () => {
let canvas, ctx;
let wWidth, wHeight;
let noiseData = [];
let frame = 0;
let loopTimeout;
// Create Noise
const createNoise = () => {
const idata = ctx.createImageData(wWidth, wHeight);
const buffer32 = new Uint32Array(idata.data.buffer);
const len = buffer32.length;
for (let i = 0; i < len; i++) {
if (Math.random() < 0.5) {
buffer32[i] = 0xff000000;
}
}
noiseData.push(idata);
};
// Play Noise
const paintNoise = () => {
if (frame === 9) {
frame = 0;
} else {
frame++;
}
ctx.putImageData(noiseData[frame], 0, 0);
};
// Loop
const loop = () => {
paintNoise(frame);
loopTimeout = window.setTimeout(() => {
window.requestAnimationFrame(loop);
}, (1000 / 25));
};
// Setup
const setup = () => {
wWidth = window.innerWidth;
wHeight = window.innerHeight;
canvas.width = wWidth;
canvas.height = wHeight;
for (let i = 0; i < 10; i++) {
createNoise();
}
loop();
};
// Reset
let resizeThrottle;
const reset = () => {
window.addEventListener('resize', () => {
window.clearTimeout(resizeThrottle);
resizeThrottle = window.setTimeout(() => {
window.clearTimeout(loopTimeout);
setup();
}, 200);
}, false);
};
// Init
const init = (() => {
canvas = document.getElementById('noise');
//canvas = document.getElementsByClassName('noise');
ctx = canvas.getContext('2d');
setup();
})();
};
noise();
.noise {
z-index: 100;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
opacity: .5;
}
.box1, .box2 {
position: relative;
width: 300px;
height: 300px;
margin: 20px;
background: #eee;
}
<div class="box1">
<canvas id="noise" class="noise"></canvas>
</div>
<div class="box2">
<canvas id="noise" class="noise"></canvas>
</div>
Use getElementsByClassName. You will get an array then. For instance for class box:
canvas = document.getElementsByClassName("box");
for (i = 0; i < canvas.length; i++) { //...do smth here...// }

Categories

Resources