반응형

beginShape를 통해 하트 모양의 도형을 그린 후 빙글빙글 회전하면서 이동하는 예제입니다.

See the Pen p5.js Heart moving and rotates by myhappyman (@myhappyman) on CodePen.

 

해당 예제를 만들어보면서 발생했던 문제점과 해결방법을 공유해 봅니다.

x, y 값을 통해 기본도형(원, 사각형)등의 생성 위치를 변경하면서 이동하는 애니메이션을 처리 예제를 먼저 만들어봤었는데, 이때는 큰 문제가 없었습니다.

추가적으로 회전 기능을 추가하면서 문제가 발생했습니다.

중심점이 계속 변경되면서 깜빡거리는 현상이 발생하는데, 일반 도형의 경우 모드가 존재하여 rectMode(CENTER)를 처리 후 rotate()와 좌표 변경으로 애니메이션을 처리하였습니다.

 

하트모양을 만들기 위해 beginShape()를 통해 하트를 구성하고 그려냈는데, 중심점을 고정하는 메소드가 존재하지 않았습니다. 이상태에서 회전과 이동을 생성점을 통해 처리하게 되면 빙글빙글 돌면서 정상적으로 돌지 않는걸 볼 수 있습니다.

이런 현상을 방지하기 위해 중앙점을 고정으로 (0, 0) 처리하였고, 이동은 translate() 메소드를 통해 이동 좌표를 별개로 처리하여 해결하였습니다.

 

아래는 작성한 샘플소스이며 ES6 문법으로 작성되었습니다.

class Heart{
    constructor(){
        this.x = 0;
        this.y = 0;
        this.mx = random(0, width);
        this.my = random(0, height);
        this.speedRange = [-2,-1,1,2];
        this.xSpeed = random(this.speedRange);
        this.ySpeed = random(this.speedRange);
        this.size = random(55);
        this.degree = random(10);

        this.red = random(255);
        this.green = random(255);
        this.blue = random(255);
    }

    createHeart(){
        push();
        translate(this.mx, this.my);
        rotate(PI * this.degree);

        noStroke();
        noSmooth();
        fill(this.red, this.green, this.blue);
        beginShape();
        vertex(this.x, this.y);
        bezierVertex(this.x - this.size / 2, this.y - this.size / 2, this.x - this.size, this.y + this.size / 3, this.x, this.y + this.size);
        bezierVertex(this.x + this.size, this.y + this.size / 3, this.x + this.size / 2, this.y - this.size / 2, this.x, this.y);            
        endShape(CLOSE);
        pop();
    }

    move(){
        if(this.mx < 0 || this.mx > width){
            this.xSpeed *= -1;
        }
        if(this.my < 0 || this.my > height){
            this.ySpeed *= -1; 
        }

        this.mx += this.xSpeed;
        this.my += this.ySpeed;
        this.degree = this.degree + 0.01;
    }       
}

let heartArr = [];
function setup(){
    var w = window.innerWidth
    var h = window.innerHeight
    createCanvas(w, h);

    for(i=0; i<150; i++){
        heartArr.push(new Heart());
    }
}

function draw(){
    background(11);

    heartArr.forEach(function(r){
        r.createHeart();
        r.move();   
    });        
}

 

 

반응형
반응형

3D 정육면체 박스 제어하기

P5.js 사용하여 면에 이미지를 넣고 회전을 시키며 마우스에 따라 회전되도록 제어해보겠습니다.

 

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="./p5.min.js"></script>
    <title>Document</title>
</head>
<body>
    <div class="controller">
        <div>
            W : <input type="range" name="width" value="120" step="10" min="10" max="250"><br/>
            H : <input type="range" name="height" value="120" step="10" min="10" max="250"><br/>
            D : <input type="range" name="depth" value="120" step="10" min="10" max="250"><br/>
        </div>
        <div>
            <button type="button" id="rotate">회전</button>
            <button type="button" id="stop">멈춤</button>
        </div>
    </div>
</body>
</html>

 

p5.js

 

var size = [];
var sizeName = ["width", "height", "depth"];
var img;
var rotate = true;
var rotateValue = 1;


window.onload = function(){
    sizeName.forEach(function(s, i){
        size[i] = document.querySelector("input[name="+s+"]").value;
        document.querySelector("input[name="+s+"]").addEventListener("change", function(){
            size[i] = this.value;
        });
    });

    document.getElementById("rotate").addEventListener("click", function(){
        rotate = true;
    });

    document.getElementById("stop").addEventListener("click", function(){
        rotate = false;
    });
}

function preload(){
    img = loadImage("image/ggome.jpg");
}

function setup(){
    createCanvas(710, 400, WEBGL);
    img.loadPixels();
}

function draw() {
    //배경색상
    background(50);

    //질감
    specularMaterial(183, 240, 177);

    //빛
    ambientLight(255, 255, 255);
    directionalLight(50, 50, 50, -frameCount, -frameCount, -1);
    noStroke();

    //마우스 컨트롤 - z축은 고정(Scroll 방지)
    orbitControl(1,1,0);    

    //박스 생성 및 회전
    push();
    if(rotate){
        rotateValue++;
        if(rotateValue > 10000000){
            rotateValue = 1;
        }
    }
    rotateX(rotateValue * 0.01);
    rotateY(rotateValue * 0.01);
    texture(img);
    box(size[0], size[1], size[2]);
    pop();
}

* 이미지 로드기능에서 교차출처(Cors) 오류가 발생하므로 서버에서 구동하셔야합니다.

 

range바에 따라 정육면체로 생성된 박스가 사이즈가 변경되는 모습을 볼 수 있고, 회전, 멈춤 버튼에 따라 회전이 멈추기도 재시작되기도 하는 모습을 볼 수 있습니다.

 

p5 메소드들이 워낙 잘 만들어져 있어서 간단하게 몇개의 메소드만으로 이러한 기능이 만들어지는 것을 볼 수 있습니다.

 

기능을 정리해보겠습니다.

  1. 먼저 3D형태의 박스를 생성하기 위해 캔버스 생성시 WEBGL을 추가합니다.
  2. 박스 겉면에 사진을 입히기 위해 이미지를 미리 로드합니다.(preload() 메소드에서 loadImage())
  3. draw메소드에서 background는 캔버스의 배경을 칠하기 위해 처리하였습니다.
  4. specularMaterial은 질감 표현인데, 이미지를 넣으면서 큰 차이가 없게 되었습니다.
  5. ambientLight는 빛의 밝기입니다 255, 255, 255는 가장 밝으면 0, 0, 0 가장 어둡기에 박스가 검은색으로 표현됩니다.
  6. directionalLight는 특정 방향으로 물체에 쬐는 빛의 색상 및 밝기 입니다.
  7. orbitControl은 마우스 회전등의 이벤트를 제어합니다 3번째 파라미터를 0으로 처리하여 스크롤이 동작하지 않도록 막았습니다.
  8. box(넓이, 높이, 깊이)를 통해 3D 형태의 박스가 생성됩니다.
  9. texture에 먼저 로드해온 이미지를 넣어 이미지를 입힙니다.
  10. 실시간 애니메이션 효과를 위해 rotateX, Y에 값을 처리하였습니다.

 

 

 

반응형
반응형

P5.js

p5.js 무료 오픈소스 라이브러리로 다양한 이미지 처리를 통해 캔버스를 다루거나 3D입체도형, 애니메이션 처리, 기하학적인 이미지 처리 등을 좀 더 쉽게 해결할 수 있습니다.

공식 홈페이지도 한글 번역을 지원하니 보다 API 문서를 읽는데 도움이 됩니다.

p5 라이브러리를 사용하는데 중요한 메소드 2가지가 있습니다.

  • setup()
  • draw()

setup은 초기화 즉 처음에 페이지가 로드될 때, 처리할 코드를 입력합니다.

draw는 애니메이션 처리를 위한 코드를 입력합니다.

함수를 만들어서 정의만 해두면 코드가 알아서 실행됩니다.

 

시작하기

간단한 예제를 보겠습니다.

p5js.org/ko/

 

home | p5.js

안녕하세요! p5.js는 크리에이티브 코딩을 위한 자바스크립트 라이브러리로, 예술가, 디자이너, 교육자, 입문자, 그리고 모두에게 접근성 높고 포용적인 언어를 지향합니다! p5.js는 무료 오픈 소

p5js.org

먼저 공식홈페이지에서 p5.js를 다운로드 후 연결하도록 합니다.

다운로드 - p5.min.js(압축)을 받습니다.

다운로드 받은 파일을 연결 후 간단한 캔버스 생성과 도형을 그려보았습니다.

See the Pen P5.js start1 by myhappyman (@myhappyman) on CodePen.

 

또한, 마우스 이벤트를 통해 입력한 위치에 도형을 계속해서 그릴수도 있습니다.

See the Pen P5.js start2 by myhappyman (@myhappyman) on CodePen.

 

마우스 이동과 클릭에 따라 도형의 색이 달라진다!

반응형
반응형

캔버스에 마우스 이벤트를 통해 클릭을 하는순간 그리기모드로 전환 후

마우스 이동에 따라 선을 그리고 마우스가 영역을 벗어나거나 마우스 클릭을 떼는 순간 그리기를 멈추는 소스를 작성해보겠습니다.

 

사인 만들기(그림 그리기)

See the Pen CanvasDrawSign by myhappyman (@myhappyman) on CodePen.

 

동작 모습

잘 그려진다!

반응형
반응형

캔버스 내 클릭이벤트를 받아 처음에는 점만 그리고 한번 더 클릭하면 두 점을 잇는 선을 생성하고 두번째 생성된 위치에 화살표 모양을 처리해보겠습니다.

해당 기능을 구현하면서 Miscro Soft사의 파워포인트 기능들이... 엄청 훌륭하다는것을 다시한번 느꼈습니다!

수학적 기능이 많이 들어갔고, 두 점 사이의 좌표값을 알때, 사이각을 atan2를 통해 구하고 삼각형의 빗변을 구하는 공식을 통해 기준점을 정해 양 사이의 화살표처리를 하여 마무리하였습니다.

 

마지막에 화살표 처리를 위해 삼각형을 억지로 그려넣으면서 꽤나 뻘짓의 끝을 달렸는데, 수학적으로 접근하여 처리하니 어떤 방향에서든 정상적으로 처리되었습니다.

 

문제 해결에 도움되었던 사이트로는 아래 URL을 참조하였습니다.

참조 문서 : https://riptutorial.com/html5-canvas/example/18136/line-with-arrowheads

 

html5-canvas - Line with arrowheads | html5-canvas Tutorial

html5-canvas documentation: Line with arrowheads

riptutorial.com

 

동작 모습.gif

power point는 대단하구나...!

 

 

화살표가 생기는 Canvas

See the Pen CanvasToDrawArrow by myhappyman (@myhappyman) on CodePen.

반응형
반응형

클릭한 곳에 사각형 생성하기

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Canvas tutorial</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script type="text/javascript">
        $(function () {
            draw();
        });

        function draw() {
            var ctx;
            var canvas = document.getElementById("canvas");
            if (canvas.getContext) {
                ctx = canvas.getContext("2d");
            }

            $(canvas).on("click", function (e) {
                if (canvas.getContext) {
                    var l = $(this).offset().left;
                    var t = $(this).offset().top;
                    var x = e.pageX - l;
                    var y = e.pageY - t;
                    var w = 15;
                    var h = 15;

                    ctx.fillStyle = "rgb(255, 187, 0)";
                    ctx.fillRect(x, y, w, h);
                }
            })
        }
    </script>
    <style type="text/css">
        * {
            margin: 0;
            padding: 0;
        }

        canvas {
            border: 1px solid black;
        }

        #canvas {
            position: relative;
            top: 150px;
            left: 600px;
        }
    </style>
</head>
<body>
    <canvas id="canvas" width="750" height="750"></canvas>
</body>
</html>

canvas를 생성하고, 생성한 캔버스를 클릭하면 현재의 좌표를 받고 지정한 사이즈와 색상으로 사각형을 생성하는 예제입니다.

 

사각형 생성

 

 

클릭한 곳에 동그라미 생성하기

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Canvas tutorial</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script type="text/javascript">
        $(function () {
            draw();
        });

        function draw() {
            var ctx;
            var canvas = document.getElementById("canvas");
            if (canvas.getContext) {
                ctx = canvas.getContext("2d");
            }

            $(canvas).on("click", function (e) {
                if (canvas.getContext) {
                    var l = $(this).offset().left;
                    var t = $(this).offset().top;
                    var x = e.pageX - l;
                    var y = e.pageY - t;
                    var r = 5;
                    console.log("canvas click" + x + "    " + y);

                    ctx.beginPath();
                    ctx.fillStyle = "rgb(54, 138, 255)";
                    ctx.arc(x, y, r, 0, Math.PI * 2, true);
                    ctx.fill();
                }
            })
        }
    </script>
    <style type="text/css">
        * {
            margin: 0;
            padding: 0;
        }

        canvas {
            border: 1px solid black;
        }

        #canvas {
            position: relative;
            top: 150px;
            left: 600px;
        }
    </style>
</head>
<body>
    <canvas id="canvas" width="750" height="750"></canvas>
</body>
</html>

사각형과 원리는 동일하며 생성하는 데이터각 사각형이 아닌 동그라미를 생성하고 그립니다.

 

동그라미 생성

 

반응형