[Canvas] Interaction

Chenยท2024๋…„ 6์›” 7์ผ
1

Canvas

๋ชฉ๋ก ๋ณด๊ธฐ
8/11
post-thumbnail

์˜ค๋Š˜ ๋ฐฐ์šด ๊ฒƒ! ์บ”๋ฒ„์Šค์—์„œ ํด๋ฆญํ•œ ํŠน์ • ๊ฐ์ฒด๋ฅผ ๋”ฑ ์ง‘์–ด๋‚ด๋Š” ๊ฒƒ!!


clientX, layerX, offsetX

clientX๋Š” ์บ”๋ฒ„์Šค ์ด๋ฒค๋“œ ๋ฆฌ์Šค๋„ˆ๋ผ๋„ ๋ธŒ๋ผ์šฐ์ € ๊ธฐ์ค€,
layerX๋Š” layer ๊ฐœ๋…์œผ๋กœ, ์œ„์— ์žˆ๋Š” layer(๋ฐ•์Šค๋“  ๋ญ๋“ ๊ฐ„์—)๋ฅผ ๊ธฐ์ค€์œผ๋กœ

๊ทผ๋ฐ...!! 0,0 ์ด ์ฐํ˜€์•ผ ํ•˜๋Š”๋ฐ ๋‹ค๋ฅธ ๊ฐ’์ด ์ฐํžŒ๋‹ค? clientX, clientY...?

layerX/layerY๋Š” Gecko ๊ธฐ๋ฐ˜ ๋ธŒ๋ผ์šฐ์ €(Firefox ๋“ฑ)์—์„œ ์‚ฌ์šฉ๋˜๋ฉฐ, ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์œ„์น˜ ์ง€์ •๋œ ์š”์†Œ์— ์ƒ๋Œ€์ ์ธ ๋งˆ์šฐ์Šค ์œ„์น˜ ๋‚˜ํƒ€๋ƒ„. Chrome๊ณผ Opera์—์„œ๋„ ์ง€์›๋˜์ง€๋งŒ, ๊ณง ์‚ฌ์šฉ ์ค‘๋‹จ(deprecated) ์˜ˆ์ •. ์•ž์œผ๋กœ ์‚ฌ์šฉ ์•ˆ ํ•˜๋Š” ๊ฒŒ ์ข‹์Œ. StackOverflow

๊ฐ•์˜๊ฐ€ 4๋…„ ์ „ ๊ฐ•์˜๋ผ ๊ทธ๋Ÿด๋งŒํ•จ

context.fillRect(200, 200, 100, 100);

function clickHandler(e) {
    const x = e.offsetX;
    const y = e.offsetY;

    if (x > 200 && x < 300 && y > 200 && y < 300) {
        console.log('click!');
    }
}

canvas.addEventListener('click', clickHandler);

Box.js (๋žœ๋ค์œผ๋กœ ๋ฟŒ๋ฆฌ๊ธฐ)

์ƒ์„ฑ ํ›„ v.s. ์ƒ์„ฑํ•˜๋Š” ๋™์‹œ์— ๊ทธ๋ฆฌ๊ธฐ

๊ธฐ๋Šฅ์— ๋”ฐ๋ผ ์„ ํƒ๊ฐ€๋Šฅ, but ์—ฌ๊ธฐ์„œ๋Š” ๋ฐ”๋กœ ๊ทธ๋ฆฌ๋„๋ก

constructor(x, y) {
    this.x = x;
    this.y = y;
    this.draw();
}
const boxes = [];

class Box {
    constructor(x, y) {
        this.x = x;
        this.y = y;
        this.draw();
    }

    draw() {
        context.fillStyle = 'rgba(0, 0, 0, 0.5)';
        context.fillRect(this.x, this.y, 100, 100);
    }
}

let tempX, tempY;
for (let i = 0; i < 10; i++) {
    tempX = Math.random() * canvas.width * 0.8;
    tempY = Math.random() * canvas.height * 0.8;

    boxes.push(new Box(tempX, tempY));
}

console.log(boxes);

๊ฐ ๋ฐ•์Šค๋งˆ๋‹ค ๊ณ ์œ  ์‹๋ณ„์ž index ์ฃผ๊ธฐ

class Box {
    constructor(index, x, y) {
        this.index = index;
        this.x = x;
        this.y = y;
        this.draw();
    }

    draw() {
        context.fillStyle = 'rgba(0, 0, 0, 0.5)';
        context.fillRect(this.x, this.y, 100, 100);
        context.fillStyle = 'white';
        context.fillText(this.index, this.x + 40, this.y + 55);
    }
}
let tempX, tempY;
for (let i = 0; i < 10; i++) {
    tempX = Math.random() * canvas.width * 0.8;
    tempY = Math.random() * canvas.height * 0.8;

    boxes.push(new Box(i, tempX, tempY));
}

mousePos ๊ฐ์ฒด ์ƒ์„ฑ

const mousePos = { x: 0, y: 0}

class Box {
      constructor(index, x, y) {
          this.index = index;
          this.x = x;
          this.width = 100;
          this.height = 100;
          this.y = y;
          this.draw();
      }
}

canvas.addEventListener('click', (e) => {
    mousePos.x = e.offsetX;
    mousePos.y = e.offsetY;

    // ๋ฐ•์Šค 10๊ฐœ๋‹ˆ๊นŒ boxes.length ๋Œ์•„์•ผํ•จ ์–ด์ฉ”์ˆ˜์—†์Œ
    let box;
    for (let i = 0; i < boxes.length; i++) {
        box = boxes[i];
        if (
            mousePos.x > box.x &&
            mousePos.x < box.x + box.width &&
            mousePos.y > box.y &&
            mousePos.y < box.y + box.height
        ) {
            console.log(box.index);
        }
    }
});

๋ฐ•์Šค๊ฐ€ ๊ฒน์น˜๋ฉด ?

let selectedBox; // ํด๋ฆญ๋œ ๋ฐ•์Šค
let box;
for (let i = 0; i < boxes.length; i++) {
    box = boxes[i];
    if (
        mousePos.x > box.x &&
        mousePos.x < box.x + box.width &&
        mousePos.y > box.y &&
        mousePos.y < box.y + box.height
    ) {
        selectedBox = box; // ๋Œ€์ฒด
    }
}
console.log(selectedBox.index);


์›€์ง์ด๋Š” ๋ฐ•์Šค + ํด๋ฆญ ์ธํ„ฐ๋ž™์…˜!

draw()ํ•จ์ˆ˜๊ฐ€ requestAniFrame์„ ํ•˜๋ฉด์„œ ๋ฐ˜๋ณตํ•ด์„œ ๊ทธ๋ฆฌ๊ณ  ์ง€์šฐ๊ธฐ๋ฅผ ํ•˜๋ฉด์„œ => x, y ์ขŒํ‘œ๋ฅผ ๋ฐ”๊ฟ”์ฃผ๋Š” ์›๋ฆฌ

x++, y++

function render() {
    context.clearRect(0, 0, canvas.width, canvas.height);
    let box;
    for (let i = 0; i < boxes.length; i++) {
        box = boxes[i];
        box.x += 3;
        if (box.x > canvas.width) {
            box.x = -box.width;
        }
        box.draw();
    }
    requestAnimationFrame(render);
}


render()


๋ฐ•์Šค ์†๋„๋ฅผ ์ œ๊ฐ๊ฐ์œผ๋กœ!

class Box {
    constructor(index, x, y, speed) {
        this.index = index;
        this.x = x;
        this.speed = speed;
        this.width = 100;
        this.height = 100;
        this.y = y;
        this.draw();
    }
}
function render() {
    context.clearRect(0, 0, canvas.width, canvas.height);
    let box;
    for (let i = 0; i < boxes.length; i++) {
        box = boxes[i];
        box.x += box.speed;
        if (box.x > canvas.width) {
            box.x = -box.width;
        }
        box.draw();
    }
    requestAnimationFrame(render);
}
let tempX, tempY, tempSpeed;
for (let i = 0; i < 10; i++) {
    tempX = Math.random() * canvas.width * 0.8;
    tempY = Math.random() * canvas.height * 0.8;
    tempSpeed = Math.random() * 4 + 1; // ์ตœ์†Œ๊ฐ’, ์ตœ๋Œ“๊ฐ’ ์„ค์ •
    boxes.push(new Box(i, tempX, tempY, tempSpeed));
}


์—๋Ÿฌ 1

selectedBox.index ๊ฐ€ ์•„๋‹Œ ๊ฑธ ํด๋ฆญํ–ˆ์„ ๋•Œ, else ์ฒ˜๋ฆฌ๋ฅผ ์•ˆํ•ด์คฌ๊ธฐ ๋•Œ๋ฌธ์— ๋‚˜๋Š” ๋‹น์—ฐํ•œ ์—๋Ÿฌ! ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ํ•ด์ฃผ์ž

๊ธฐ์กด

console.log(selectedBox.index);

๋ณ€๊ฒฝ (selectedBox ๊ฐ€ ์กด์žฌํ•  ๋•Œ์—๋งŒ)

if (selectedBox) {
    console.log(selectedBox.index);
}

์—๋Ÿฌ 2

์—ฌ๋ฐฑ์„ ํด๋ฆญํ•ด๋„ ๋งˆ์ง€๋ง‰์œผ๋กœ ํด๋ฆญํ•œ ๋ฐ•์Šค index๊ฐ€ ์ฐํžŒ๋‹ค.
์ด์œ ๋Š” selectedBox = box๋ผ๊ณ  ํ•˜๊ณ  clear ์„ ์•ˆํ•ด์คฌ๊ธฐ ๋•Œ๋ฌธ. ๊ฐ’์„ ๋น„์›Œ์ค˜์•ผ์ง€

if (selectedBox) {
    console.log(selectedBox.index);
    selectedBox = null;
}
profile
ํ˜„์‹ค์ ์ธ ๋ชฝ์ƒ๊ฐ€

0๊ฐœ์˜ ๋Œ“๊ธ€