<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<script src="image.js"></script>
<title>Document</title>
</head>
<body>
<button class="triangle-btn">triangle</button>
<button class="sector-btn">sector</button>
<button class="pacman-btn">pacman</button>
<div class="scanimation">
<div class="image-wrapper"></div>
<div class="film-container">
<div class="film-wrapper">
<div class="film"></div>
</div>
</div>
</div>
</body>
<script src="script.js"></script>
</html>
body {
min-height: 3000px;
background-color: gray;
}
.scanimation {
display: flex;
justify-content: center;
align-items: center;
height: 700px;
position: relative;
}
.image-wrapper {
background-color: rgb(255, 131, 131);
border-radius: 10px;
}
.image-row {
width: 100%;
display: flex;
}
.image-block {
display: flex;
}
.film-container {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
overflow: auto;
}
.film-wrapper {
width: 300vw;
height: 100%;
overflow: hidden;
display: flex;
justify-content: center;
}
.film {
width: 100dvw;
height: 100%;
display: flex;
}
.bar {
background-color: black;
height: 100%;
}
function createTriangle(size, angle) {
// 角度をラジアンに変換
const radians = (angle * Math.PI) / 180;
// タンジェントを計算(0度と90度の場合は特別に処理)
const tan = angle === 0 ? 0 : (angle === 90 ? Infinity : Math.tan(radians));
// 2次元配列を初期化
const triangle = Array(size).fill().map(() => Array(size).fill(0));
for (let y = 0; y < size; y++) {
const width = Math.min(Math.round(y / tan), size);
for (let x = 0; x < width; x++) {
triangle[y][x] = 1;
}
}
return triangle;
}
function createSector(size, angle, startAngle = 0) {
// 角度をラジアンに変換
const startRad = (startAngle * Math.PI) / 180;
const endRad = ((startAngle + angle) * Math.PI) / 180;
// 2次元配列を初期化
const sector = Array(size).fill().map(() => Array(size).fill(0));
const center = Math.floor(size / 2);
const radius = center;
for (let y = 0; y < size; y++) {
for (let x = 0; x < size; x++) {
// 中心からの相対座標を計算
const dx = x - center;
const dy = center - y; // y軸は上下反転
// 点と中心の距離を計算
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= radius) {
// 点の角度を計算(アークタンジェントを使用)
let angle = Math.atan2(dy, dx);
if (angle < 0) angle += 2 * Math.PI; // 角度を0~2πの範囲に調整
// 点が扇形の範囲内にあるかチェック
if (angle >= startRad && angle <= endRad) {
sector[y][x] = 1;
}
}
}
}
return sector;
}
const numberOfBlock = 50
// 三角
const triangle = [
createTriangle(numberOfBlock, 10),
createTriangle(numberOfBlock, 20),
createTriangle(numberOfBlock, 30),
createTriangle(numberOfBlock, 40),
createTriangle(numberOfBlock, 50),
createTriangle(numberOfBlock, 60),
createTriangle(numberOfBlock, 70),
createTriangle(numberOfBlock, 80),
createTriangle(numberOfBlock, 90),
]
// 円
const sector = [
createSector(numberOfBlock, 30),
createSector(numberOfBlock, 60),
createSector(numberOfBlock, 90),
createSector(numberOfBlock, 120),
createSector(numberOfBlock, 150),
createSector(numberOfBlock, 180),
createSector(numberOfBlock, 210),
createSector(numberOfBlock, 240),
createSector(numberOfBlock, 270),
createSector(numberOfBlock, 300),
createSector(numberOfBlock, 330),
createSector(numberOfBlock, 360),
]
// パックマン
const pacman = [
createSector(numberOfBlock, 335, 15),
createSector(numberOfBlock, 315, 25),
createSector(numberOfBlock, 295, 35),
createSector(numberOfBlock, 285, 45),
createSector(numberOfBlock, 275, 55),
createSector(numberOfBlock, 285, 45),
createSector(numberOfBlock, 295, 35),
createSector(numberOfBlock, 315, 25),
createSector(numberOfBlock, 335, 15),
]
const film = document.querySelector(".film")
const showFilmBtn = document.querySelector(".show-film-btn")
const scanimation = document.querySelector(".scanimation")
const imageWrapper = document.querySelector(".image-wrapper")
const filmWrapper = document.querySelector(".film-wrapper")
let isShowFilmBtn = true
const imageMargin = 60
const barSize = 20
let numberOfImage = triangle.length
const gapSize = barSize / numberOfImage - 1
const imageSize = 800
scanimation.style.height = imageSize + "px"
const imageBlockSize = imageSize / numberOfBlock
film.style.width = imageSize * 2
film.style.height = imageSize
imageWrapper.style.height = imageSize + "px"
imageWrapper.style.width = imageSize + "px"
filmWrapper.style.width = (imageSize * 7) + "px"
// スキャニメーション生成
const createScanimation = (image) => {
imageWrapper.innerHTML = ""
const contentElWidth = (imageBlockSize / numberOfImage)
for (let i = 0; i < numberOfBlock; i++) {
const row = document.createElement("div")
row.classList.add("image-row")
row.style.height = imageBlockSize + "px"
for (let j = 0; j < numberOfBlock; j++) {
const block = document.createElement("div")
block.classList.add("image-block")
block.style.height = "100%"
// block.style.width = imageBlockSize + "px"
image.forEach(content => {
const imageContentEl = document.createElement("div")
imageContentEl.style.width = contentElWidth + "px"
imageContentEl.style.height = "100%"
if (content[i][j] === 1) {
imageContentEl.style.background = "black"
} else {
imageContentEl.style.background = "transparent"
}
block.appendChild(imageContentEl)
})
row.appendChild(block)
}
imageWrapper.appendChild(row)
}
// film追加処理
film.innerHTML = ""
for (let i = 0; i < (imageSize / imageBlockSize) * 2; i++) {
const blackBar = document.createElement("div")
const bar = document.createElement("div")
blackBar.classList.add("bar")
blackBar.style.minWidth = (imageBlockSize - contentElWidth) + "px"
blackBar.style.width = (imageBlockSize - contentElWidth) + "px"
bar.style.minWidth = contentElWidth + "px"
film.appendChild(blackBar)
film.appendChild(bar)
}
}
// showFilmBtnが押された時の処理
const handleClickShowFilmBtn = () => {
if (isShowFilmBtn) {
film.style.display = "none"
} else {
film.style.display = "flex"
}
isShowFilmBtn = !isShowFilmBtn
}
createScanimation(triangle)
const triangleBtn = document.querySelector(".triangle-btn")
const sectorBtn = document.querySelector(".sector-btn")
const pacmanBtn = document.querySelector(".pacman-btn")
triangleBtn.addEventListener("click", () => {
numberOfImage = triangle.length
createScanimation(triangle)
})
sectorBtn.addEventListener("click", () => {
numberOfImage = sector.length
createScanimation(sector)
})
pacmanBtn.addEventListener("click", () => {
numberOfImage = pacman.length
createScanimation(pacman)
})
showFilmBtn.addEventListener("click", handleClickShowFilmBtn)
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.