Как я могу использовать z-index для симуляции выпадения чипа через плату подключения четырех, чтобы придать ему эффект 3d? - PullRequest
1 голос
/ 10 мая 2019

Я делаю игру «соединяй четыре», и сейчас я могу поставить фишку в соответствующий слот, а также перейти с красной фишки на желтую.Однако, когда вы бросаете чип, он не входит в плату.Это слоистый за пределами доски.Мне бы хотелось, чтобы выпавший чип падал на темно-синий круг внутри каждого слота и попадал под сам слот.Так будет выглядеть реалистично и в 3d.

Я думал, что смогу сделать это с z-index, но у меня есть 2 проблемы.1-й Когда я установил для слотов div значение z-index, равное 3, хотя у падающего чипа z-index равен 2;чип все еще падает на слот?Во-вторых, даже если бы это работало, синий круг в каждом слоте теперь будет скрыт, потому что у div есть более высокий z-индекс, они должны быть одинаковыми, чтобы они оба были видны.Но если они одинаковые, то чип не может попасть в плату?

Есть идеи, как сделать этот эффект?

//grab all slot positions on the board
const slots = document.querySelectorAll('.board div');
let player = 'p1';
let board = [ 
	0, 1, 2, 3, 4, 5, 6,
	7, 8, 9, 10, 11, 12, 13,
	14, 15, 16, 17, 18, 19, 20,
	21, 22, 23, 24, 25, 26, 27,
	28, 29, 30, 31, 32, 33, 34,
	35, 36, 37, 38, 39, 40, 41,
]

//assign a class to each slot to represent its position
for(let i = 0; i < slots.length; i++) {
	//add class to each div
	slots[i].classList.add('c' + i);
	//add the slot to each div
	let slot = document.createElement('span');
	slots[i].appendChild(slot);
	//add the function with the game logic to each slot
	slots[i].addEventListener('click', runGame); 
}

function runGame() {
	//figure out which column the selected slot sits in
	const slotColumn = (Number(this.className.slice(1, 3)) % 7);
	//create an array to store all the slots that share the above column
	const columnArray = [];

	//grab all the slots that sit in that column
	for(let i = 0; i < board.length; i++) {
		if(board[i] % 7 === slotColumn) columnArray.push(board[i]);
	}

	//drop chip in the chosen column
	dropChip(columnArray);

	function dropChip(column) {
		//select bottom most slot that's available in the column
		for(let i = column.length - 1; i >= 0; i--) {
			if(column[i] !== 'p1' || column[i] !== 'p2') {
				board[column[i]] = player;
				slots[column[i]].classList.add(player);
				switchPlayer(player);
				break;
			}	
		}

		function switchPlayer(currentPlayer) {
			if(currentPlayer === 'p1') player = 'p2';
			else if(currentPlayer ==='p2') player = 'p1';
		}
	}
}
/** {
	outline: 1px solid red;
}*/

*, *:before, *:after {
	box-sizing: inherit;
}

html {
	box-sizing: border-box;
}

html, body {
	margin: 0;
	padding: 0;
	background-color: #e5e6e8;
}

body {
	display: flex;
	justify-content: center;
	min-height: 100vh;
}

.board-wrapper {
	padding-top: 100px;
	display: flex;
	justify-content: center;
	margin: auto auto 0 auto; /*ask why this is needed*/
	position: relative;
	overflow: hidden;
}

.board {
	display: flex;
	flex-wrap: wrap;
	max-width: 706px;
	background-color: #00c;
	padding: 3px;
}

.board div {
	width: 100px;
	height: 100px;
	background-color: blue;
	border: 3px solid #00c;
	position: relative;
	z-index: 3;
}

.board div span {
	display: inline-block;
	width: 80px;
	height: 80px;
	border-radius: 50%;
	background-color: #00c;
	position: absolute;
	left: 0;
	top: 0;
	right: 0;
	bottom: 0;
	margin: auto;
	box-shadow: inset 0px 0px 13px #0606aa;
}

.board .chip {
	display: block;
	position: absolute;
	background-color: transparent;
	top: 0;
	left: 0;
	right: 0;
	height: 100px;
}

.board .chip:after {
	content: "";
	width: 80px;
	height: 80px;
	border-radius: 50%;
	background-color: red;
	position: absolute;
	left: 3px;
	top: 0;
	opacity: 0;
	transition: all .5s ease;
}

.board .chip:before {
	content: "";
	width: 50px;
	height: 50px;
	border-radius: 50%;
	background-color: red;
	position: absolute;
	left: 18px;
	top: 15px;
	z-index: 1;
	box-shadow: inset 0px 0px 20px #cc0000;
	opacity: 0;
	transition: all .5s ease;	
}

.board div:nth-of-type(7n+1):hover ~ .chip:after{transform: translateX(10px); opacity: 1;}
.board div:nth-of-type(7n+1):hover ~ .chip:before{transform: translateX(10px); opacity: 1;}
.board div:nth-of-type(7n+2):hover ~ .chip:after{transform: translateX(110px); opacity: 1;}
.board div:nth-of-type(7n+2):hover ~ .chip:before{transform: translateX(110px); opacity: 1;}
.board div:nth-of-type(7n+3):hover ~ .chip:after{transform: translateX(210px); opacity: 1;}
.board div:nth-of-type(7n+3):hover ~ .chip:before{transform: translateX(210px); opacity: 1;}
.board div:nth-of-type(7n+4):hover ~ .chip:after{transform: translateX(310px); opacity: 1;}
.board div:nth-of-type(7n+4):hover ~ .chip:before{transform: translateX(310px); opacity: 1;}
.board div:nth-of-type(7n+5):hover ~ .chip:after{transform: translateX(410px); opacity: 1;}
.board div:nth-of-type(7n+5):hover ~ .chip:before{transform: translateX(410px); opacity: 1;}
.board div:nth-of-type(7n+6):hover ~ .chip:after{transform: translateX(510px); opacity: 1;}
.board div:nth-of-type(7n+6):hover ~ .chip:before{transform: translateX(510px); opacity: 1;}
.board div:nth-of-type(7n+7):hover ~ .chip:after{transform: translateX(610px); opacity: 1;}
.board div:nth-of-type(7n+7):hover ~ .chip:before{transform: translateX(610px); opacity: 1;}

.p1:after {
	content: "";
	display: inline-block;
	width: 80px;
	height: 80px;
	border-radius: 50%;
	background-color: red;
	position: absolute;
	left: 0;
	top: 0;
	right: 0;
	bottom: 0;
	margin: auto;
	z-index: 1;
	animation-name: drop;
	animation-fill-mode: forwards;
	animation-duration: .5s;
	animation-timing-function: ease-in;
}

.p1:before {
	content: "";
	width: 50px;
	height: 50px;
	border-radius: 50%;
	background-color: red;
	position: absolute;
	left: 0;
	top: 0;
	right: 0;
	bottom: 0;
	margin: auto;
	z-index: 2;
	box-shadow: inset 0px 0px 20px #cc0000;
	animation-name: drop;
	animation-fill-mode: forwards;
	animation-duration: .5s;
	animation-timing-function: ease-in;
}

.p2:after {
	content: "";
	display: inline-block;
	width: 80px;
	height: 80px;
	border-radius: 50%;
	background-color: yellow;
	position: absolute;
	left: 0;
	top: 0;
	right: 0;
	bottom: 0;
	margin: auto;
	z-index: 1;
	animation-name: drop;
	animation-fill-mode: forwards;
	animation-duration: .5s;
	animation-timing-function: ease-in;
}

.p2:before {
	content: "";
	width: 50px;
	height: 50px;
	border-radius: 50%;
	background-color: yellow;
	position: absolute;
	left: 0;
	top: 0;
	right: 0;
	bottom: 0;
	margin: auto;
	z-index: 2;
	box-shadow: inset 0px 0px 20px #ced639;
	animation-name: drop;
	animation-fill-mode: forwards;
	animation-duration: .5s;
	animation-timing-function: ease-in;
}

@keyframes drop {
	from {top: -1500px;}
	to {top: 0;}
}
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Connect Four</title>
	<link rel="stylesheet" href="style.css">
</head>
<body>
	<div class="board-wrapper">
		<div class="board">
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<div></div>
			<span class="chip"></span>
		</div>
	</div>
	<script src="script.js"></script>
</body>
</html>

1 Ответ

1 голос
/ 10 мая 2019

Вот модифицированная версия вашего кода.Сначала я изменил элемент chip, чтобы рассмотреть только один псевдоэлемент вместо 2, и я использовал переменную CSS, чтобы легко изменить цвет.

Затем для доски я создал каждую ячейку, используя два элемента, чтобы иметь возможность получить эффект 3D.Вы увидите псевдоэлемент, в котором я применил радиальный градиент, чтобы создать отверстие, и этот слой будет сверху, за которым будет отставать чип:

//grab all slot positions on the board
const slots = document.querySelectorAll('.board div');
let player = 'p1';
let board = [
  0, 1, 2, 3, 4, 5, 6,
  7, 8, 9, 10, 11, 12, 13,
  14, 15, 16, 17, 18, 19, 20,
  21, 22, 23, 24, 25, 26, 27,
  28, 29, 30, 31, 32, 33, 34,
  35, 36, 37, 38, 39, 40, 41,
]

//assign a class to each slot to represent its position
for (let i = 0; i < slots.length; i++) {
  //add class to each div
  slots[i].classList.add('c' + i);
  //add the slot to each div
  let slot = document.createElement('span');
  slots[i].appendChild(slot);
  //add the function with the game logic to each slot
  slots[i].addEventListener('click', runGame);
}

function runGame() {
  //figure out which column the selected slot sits in
  const slotColumn = (Number(this.className.slice(1, 3)) % 7);
  //create an array to store all the slots that share the above column
  const columnArray = [];

  //grab all the slots that sit in that column
  for (let i = 0; i < board.length; i++) {
    if (board[i] % 7 === slotColumn) columnArray.push(board[i]);
  }

  //drop chip in the chosen column
  dropChip(columnArray);

  function dropChip(column) {
    //select bottom most slot that's available in the column
    for (let i = column.length - 1; i >= 0; i--) {
      if (column[i] !== 'p1' || column[i] !== 'p2') {
        board[column[i]] = player;
        slots[column[i]].classList.add(player);
        switchPlayer(player);
        break;
      }
    }

    function switchPlayer(currentPlayer) {
      if (currentPlayer === 'p1') player = 'p2';
      else if (currentPlayer === 'p2') player = 'p1';
    }
  }
}
/** {
	outline: 1px solid red;
}*/

*,
*:before,
*:after {
  box-sizing: inherit;
}

html {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  background-color: #e5e6e8;
}

body {
  display: flex;
  justify-content: center;
  min-height: 100vh;
}

.board-wrapper {
  padding-top: 100px;
  display: flex;
  justify-content: center;
  margin: auto auto 0 auto; /*ask why this is needed*/
  position: relative;
  overflow: hidden;
}

.board {
  display: flex;
  flex-wrap: wrap;
  max-width: 706px;
  background-color: #00c;
  padding: 3px;
}

.board div {
  width: 100px;
  height: 100px;
  position: relative;
}

.board div span {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background-color: #00c;
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  margin: auto;
  box-shadow: inset 0px 0px 13px #0606aa;
}

.board div span:before {
  content: "";
  position: absolute;
  top: -10px;
  left: -10px;
  right: -10px;
  bottom: -10px;
  background: radial-gradient(circle, transparent 40px, blue 0);
  border: 3px solid #00c;
  z-index: 3;
}

.board .chip {
  display: block;
  position: absolute;
  background-color: transparent;
  top: 0;
  left: 0;
  right: 0;
  height: 100px;
}

.board .chip:after {
  content: "";
  width: 80px;
  height: 80px;
  border-radius: 50%;
  border: 15px solid red;
  background-color: red;
  box-shadow: inset 0px 0px 20px #cc0000;
  position: absolute;
  left: 3px;
  top: 0;
  opacity: 0;
  transition: all .5s ease;
}

.board div:nth-of-type(7n+1):hover~.chip:after {
  transform: translateX(10px);
  opacity: 1;
}

.board div:nth-of-type(7n+1):hover~.chip:before {
  transform: translateX(10px);
  opacity: 1;
}

.board div:nth-of-type(7n+2):hover~.chip:after {
  transform: translateX(110px);
  opacity: 1;
}

.board div:nth-of-type(7n+2):hover~.chip:before {
  transform: translateX(110px);
  opacity: 1;
}

.board div:nth-of-type(7n+3):hover~.chip:after {
  transform: translateX(210px);
  opacity: 1;
}

.board div:nth-of-type(7n+3):hover~.chip:before {
  transform: translateX(210px);
  opacity: 1;
}

.board div:nth-of-type(7n+4):hover~.chip:after {
  transform: translateX(310px);
  opacity: 1;
}

.board div:nth-of-type(7n+4):hover~.chip:before {
  transform: translateX(310px);
  opacity: 1;
}

.board div:nth-of-type(7n+5):hover~.chip:after {
  transform: translateX(410px);
  opacity: 1;
}

.board div:nth-of-type(7n+5):hover~.chip:before {
  transform: translateX(410px);
  opacity: 1;
}

.board div:nth-of-type(7n+6):hover~.chip:after {
  transform: translateX(510px);
  opacity: 1;
}

.board div:nth-of-type(7n+6):hover~.chip:before {
  transform: translateX(510px);
  opacity: 1;
}

.board div:nth-of-type(7n+7):hover~.chip:after {
  transform: translateX(610px);
  opacity: 1;
}

.board div:nth-of-type(7n+7):hover~.chip:before {
  transform: translateX(610px);
  opacity: 1;
}

.p1:after,
.p2:after {
  content: "";
  display: inline-block;
  width: 80px;
  height: 80px;
  border-radius: 50%;
  border: 15px solid var(--c, red);
  background-color: var(--c, red);
  box-shadow: inset 0px 0px 20px var(--s, #cc0000);
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  margin: auto;
  z-index: 1;
  animation-name: drop;
  animation-fill-mode: forwards;
  animation-duration: .5s;
  animation-timing-function: ease-in;
}

.p2 {
  --c: yellow;
  --s: #ced639;
}

@keyframes drop {
  from {
    top: -1500px;
  }
  to {
    top: 0;
  }
}
<div class="board-wrapper">
  <div class="board">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <span class="chip"></span>
  </div>
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...