Coding/JavsScript 삽질기2022. 1. 19. 10:25

유튜브에서본 회전 하는 3D 도넛을 구현해 보았다.

3D doughnut

코드는 아래와 같다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>3D doughnut</title>
    <meta name='viewport' content='width=device-width, initial-scale=1.0'>
    <style>
        canvas {
            height: 100%;
            width: 100%;
        }
    </style>
</head>
<body>
<div align='center'>
    <canvas id="canvas"></canvas>
</div>
<script language="JavaScript">
    // Start: 2022.01.16
    // Update: 2022.01.18

    let cvs;
    let canvas;
    let bufCanvas;
    let bufCtx;
    let thetaX = 127;
    let thetaZ = 0;

    function InitCanvas() {
        height = window.innerHeight;
        width = window.innerWidth;

        canvas = document.getElementById("canvas");
        canvas.width = width;
        canvas.height = height;
        cvs = canvas.getContext("2d");

        bufCanvas = document.createElement("canvas");
        bufCanvas.width = canvas.width;
        bufCanvas.height = canvas.height;
        bufCtx = bufCanvas.getContext("2d");
    }

    function drawCircle(x, y, c, r) {
        if (c <= 0 || c >= 255){
            console.log(c);
        }

        bufCtx.beginPath();
        bufCtx.fillStyle = "rgb(" + c + "," + c + "," + c + ")";
        bufCtx.strokeStyle = "rgb(255, 255, 255)";
        bufCtx.arc(x, y, r, 0, Math.PI * 2);
        bufCtx.stroke();
        bufCtx.fill();
        bufCtx.closePath();
    }

    function _draw() {
        let maxSize = canvas.height < canvas.width ? canvas.height : canvas.width;
        let dimen = 8;
        let ox = canvas.width / 2;
        let oy = canvas.height / 2;

        let R1 = maxSize/20;  // 원의 반지름
        let R2 = maxSize/10;  // Y축으로 회전하기 위한 반경

        // 카메라와 스크린의 거리를 z'라 하고, 그 투영되는 상을 x',y'
        // z:x = z':x'
        // z:y = z':y'
        // x' = xz'/z, y' = yz'/z
        // z' = z1
        // x', y' = xz1/z, yz1/z
        // z의 최대거리 z2 = 5000이라 하면
        // x' <= (height/2 * 0.8) (화면 중앙 위치, 마진 0.1)
        // x 의 최대 값은 R1 + R2
        // x' = Z1(R1+R2)/z2 = height * 0.4
        // Z1 = Z2 * height * 0.4 / (R1+R2)

        let ZZ2 = 5000;
        let ZZ1 = maxSize * ZZ2 * 0.4 / (R1 + R2);

        let points = [];

        for (let i = 0; i < 628; i += dimen) {
            let x1 = Math.cos(i/100) * R1 + R2;
            let y1 = Math.sin(i/100) * R1;
            let nx1 = Math.cos(i/100);
            let ny1 = Math.sin(i/100);

            for (let j = 0; j < 628; j += dimen) {
                // Y축 회전
                let x2 = x1 * Math.cos(j/100);
                let y2 = y1;
                let z2 = x1 * Math.sin(j/100);

                let nx2 = nx1 * Math.cos(j/100);
                let ny2 = ny1;
                let nz2 = nx1 * Math.sin(j/100);

                // X축 회전
                let x3 = x2;
                let y3 = y2 * Math.cos(thetaX/100) - z2 * Math.sin(thetaX/100);
                let z3 = y2 * Math.sin(thetaX/100) + z2 * Math.cos(thetaX/100);

                let nx3 = nx2;
                let ny3 = ny2 * Math.cos(thetaX/100) - nz2 * Math.sin(thetaX/100);
                let nz3 = ny2 * Math.sin(thetaX/100) + nz2 * Math.cos(thetaX/100);

                // Z축 회전
                let x4 = x3 * Math.cos(thetaZ/100) - y3 * Math.sin(thetaZ/100);
                let y4 = x3 * Math.sin(thetaZ/100) + y3 * Math.cos(thetaZ/100);
                let z4 = ZZ2 + z3;

                let nx4 = nx3 * Math.cos(thetaZ/100) - ny3 * Math.sin(thetaZ/100);
                let ny4 = nx3 * Math.sin(thetaZ/100) + ny3 * Math.cos(thetaZ/100);
                let nz4 = nz3;

                // 법선 벡터 (nx4, ny4, nz)와 광원의 백터 내적 계산
                // 광원 위치는 (0, 0, -1)
                let lx = 0;
                let ly = 0;
                let lz = -1;
                let light = nx4 * lx + ny4 * ly + nz4 * lz;

                if (light > 0) {
                    let color = Math.round(light * 255);

                    // x' = xz'/z, y' = yz'/z
                    let xp = Math.floor(x4 * ZZ1 / z4);
                    let yp = Math.floor(-y4 * ZZ1 / z4);

                    points.push([xp + ox, yp + oy, 255-color]);
                }
            }
        }

        bufCtx.beginPath();
        bufCtx.strokeStyle = "black";
        bufCtx.fillStyle = "black";
        bufCtx.fill();

        bufCtx.fillRect(0, 0, canvas.width, canvas.height);
        bufCtx.closePath();
        bufCtx.stroke();

        points.forEach(e => drawCircle(e[0], e[1], e[2], 1));

        thetaX = (thetaX + 2) % 629;
        thetaZ = (thetaZ + 2) % 629;
    }

    function OnDraw() {
        _draw();

        cvs.beginPath();
        cvs.clearRect(0, 0, canvas.width, canvas.height);
        cvs.drawImage(bufCanvas, 0, 0);

        console.log(">OnDraw()");
    }


    function onLoadPage() {
        InitCanvas();
        OnDraw();
        setInterval(OnDraw, 50);
    }

    window.onload = onLoadPage();
</script>
</body>
</html>

 

 

Posted by chobocho
Coding/JavsScript 삽질기2022. 1. 19. 01:08

유튜브에서 회전하는 도넛 영상을 보고, 회전하는 구를 그려 보았다.

Sphere

1. 난해하게 만든 전체 소스는 아래와 같다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Sphere</title>
    <meta name='viewport' content='width=device-width, initial-scale=1.0'>
    <style>
        canvas {
            height: 100%;
            width: 100%;
        }
    </style>
</head>
<body>
<div align='center'>
    <canvas id="canvas"></canvas>
</div>
<script language="JavaScript">
    // Start: 2022.01.18
    // Update: 2022.01.19

    let cvs;
    let canvas;
    let bufCanvas;
    let bufCtx;
    let thetaX = 0;
    let thetaZ = 0;

    let SIN = [];
    let COS = [];

    function InitValue() {
        for (let i = 0; i < 628; i++) {
            SIN[i] = Math.sin(i / 100);
            COS[i] = Math.cos(i / 100);
        }
    }
    
    function InitCanvas() {
        height = window.innerHeight;
        width = window.innerWidth;

        console.log(">Width:", width);
        console.log(">Heigth:", height);

        canvas = document.getElementById("canvas");
        canvas.width = width;
        canvas.height = height;
        cvs = canvas.getContext("2d");

        bufCanvas = document.createElement("canvas");
        bufCanvas.width = canvas.width;
        bufCanvas.height = canvas.height;
        bufCtx = bufCanvas.getContext("2d");
    }

    function drawCircle(x, y, c, r) {
        bufCtx.beginPath();
        bufCtx.fillStyle = "rgb(" + c + "," + c + "," + c + ")";
        bufCtx.strokeStyle = "rgb(255, 255, 255)";
        bufCtx.arc(x, y, r, 0, Math.PI * 2);
        bufCtx.stroke();
        bufCtx.fill();
        bufCtx.closePath();
    }

    function _draw() {
        let maxSize = canvas.height < canvas.width ? canvas.height : canvas.width;
        let dimen = 8;
        let ox = canvas.width / 2;
        let oy = canvas.height / 2;
        let R1 = maxSize/20;
        let ZZ1 = maxSize * 1000 * 0.4 / R1;

        let points = [];

        for (let i = 0; i < 628; i += dimen) {
            let a = COS[i];
            let b = SIN[i];

            for (let j = 0; j < 628; j += dimen) {
                let c = COS[j];
                let d = SIN[j];
                let e = COS[thetaX];
                let f = SIN[thetaX];
                let g = COS[thetaZ];
                let h = SIN[thetaZ];

                let k = b * R1 * e - a * R1 * d * f;
                let x4 = a * R1 * c * g - k * h;
                let y4 = a * R1 * c * h + k * g;
                let z4 = ZZ1 / (1000 + b * R1 * f + a * R1 * d * e);
                let light = (b * f + a * d * e);

                if (light > 0) {
                    let color = Math.round(light * 255);
                    let xp = Math.floor(x4 * z4 + ox);
                    let yp = Math.floor(-y4 * z4 + oy);
                    points.push([xp, yp, 255-color]);
                }
            }
        }

        bufCtx.strokeStyle = "black";
        bufCtx.fillStyle = "black";
        bufCtx.fillRect(0, 0, canvas.width, canvas.height);
        points.forEach(e => drawCircle(e[0], e[1], e[2], 1));

        thetaX = (thetaX + 2) % 629;
        thetaZ = (thetaZ + 2) % 629;
    }

    function OnDraw() {
        let startTime = new Date();
        _draw();

        cvs.clearRect(0, 0, canvas.width, canvas.height);
        cvs.drawImage(bufCanvas, 0, 0);

        console.log("Elapsed time: " + (new Date() - startTime));
    }


    function onLoadPage() {
        InitValue();
        InitCanvas();
        OnDraw();
        setInterval(OnDraw, 50);
    }

    window.onload = onLoadPage();
</script>
</body>
</html>

 

 


1. HTML로 구를 그리기 위한 기본적인 뼈대를 작성한다.

아래 코드에서 _drawSphere()를 채워 나갑니다.

하기 HTML 코드는 좋은 예제가 아닙니다. HTML 관련은 인터넷에 있는 좋은 코드를 참고 하시기 바랍니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Sphere</title>
    <meta name='viewport' content='width=device-width, initial-scale=1.0'>
    <style>
        canvas {
            height: 100%;
            width: 100%;
        }
    </style>
</head>
<body>
<div align='center'>
    <canvas id="canvas"></canvas>
</div>
<script language="JavaScript">
    let cvs;
    let canvas;
    let bufCanvas;
    let bufCtx;

    function InitCanvas() {
        height = window.innerHeight;
        width = window.innerWidth;

        console.log(">Width:", width);
        console.log(">Heigth:", height);

        canvas = document.getElementById("canvas");
        canvas.width = width;
        canvas.height = height;
        cvs = canvas.getContext("2d");

        bufCanvas = document.createElement("canvas");
        bufCanvas.width = canvas.width;
        bufCanvas.height = canvas.height;
        bufCtx = bufCanvas.getContext("2d");
    }

    function _drawSphere() {

    }

    function OnDraw() {
        let startTime = new Date();

        bufCtx.strokeStyle = "black";
        bufCtx.fillStyle = "black";
        bufCtx.fillRect(0, 0, canvas.width, canvas.height);

        _drawSphere();

        cvs.clearRect(0, 0, canvas.width, canvas.height);
        cvs.drawImage(bufCanvas, 0, 0);
        console.log("Elapsed time: " + (new Date() - startTime));
    }


    function onLoadPage() {
        InitCanvas();
        OnDraw();
        setInterval(OnDraw, 50);
    }

    window.onload = onLoadPage();
</script>
</body>
</html>

 

2. 원 그리기

원점을 기준으로 지름 r인 원은 아래 수식으로 표현 할 수 있습니다.

이때, x, y는 아래와 같이 구 할 수 있습니다.


원래 작성한 코드는 아래와 같다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Sphere</title>
    <meta name='viewport' content='width=device-width, initial-scale=1.0'>
    <style>
        canvas {
            height: 100%;
            width: 100%;
        }
    </style>
</head>
<body>
<div align='center'>
    <canvas id="canvas"></canvas>
</div>
<script language="JavaScript">
    // Start: 2022.01.16
    // Update: 2022.01.18

    let cvs;
    let canvas;
    let bufCanvas;
    let bufCtx;
    let thetaX = 0;
    let thetaZ = 0;

    function InitCanvas() {
        height = window.innerHeight;
        width = window.innerWidth;

        console.log(">Width:", width);
        console.log(">Heigth:", height);

        canvas = document.getElementById("canvas");
        canvas.width = width;
        canvas.height = height;
        cvs = canvas.getContext("2d");

        bufCanvas = document.createElement("canvas");
        bufCanvas.width = canvas.width;
        bufCanvas.height = canvas.height;
        bufCtx = bufCanvas.getContext("2d");
    }

    function drawCircle(x, y, c, r) {

        bufCtx.beginPath();
        bufCtx.fillStyle = "rgb(" + c + "," + c + "," + c + ")";
        bufCtx.strokeStyle = "rgb(255, 255, 255)";
        bufCtx.arc(x, y, r, 0, Math.PI * 2);
        bufCtx.stroke();
        bufCtx.fill();
        bufCtx.closePath();
    }

    function _draw() {
        let maxSize = canvas.height < canvas.width ? canvas.height : canvas.width;
        let dimen = 8;
        let ox = canvas.width / 2;
        let oy = canvas.height / 2;
        let R1 = maxSize/20;  // 원의 반지름

        // 카메라와 스크린의 거리를 z'라 하고, 그 투영되는 상을 x',y'
        // z:x = z':x'
        // z:y = z':y'
        // x' = xz'/z, y' = yz'/z
        // z' = z1
        // x', y' = xz1/z, yz1/z
        // z의 최대거리 z2 = 1000이라 하면
        // x' <= (height/2 * 0.8) (화면 중앙 위치, 마진 0.1)
        // x 의 최대 값은 R1 + R2
        // x' = Z1(R1+R2)/z2 = height * 0.4
        // Z1 = Z2 * height * 0.4 / (R1+R2)

        let ZZ2 = 1000;
        let ZZ1 = maxSize * ZZ2 * 0.4 / R1;

        let points = [];

        for (let i = 0; i < 628; i += dimen) {
            let x1 = Math.cos(i/100) * R1;
            let y1 = Math.sin(i/100) * R1;
            let nx1 = Math.cos(i/100);
            let ny1 = Math.sin(i/100);

            for (let j = 0; j < 628; j += dimen) {
                // Y축 회전
                let x2 = x1 * Math.cos(j/100);
                let y2 = y1;
                let z2 = x1 * Math.sin(j/100);

                let nx2 = nx1 * Math.cos(j/100);
                let ny2 = ny1;
                let nz2 = nx1 * Math.sin(j/100);

                // X축 회전
                let x3 = x2;
                let y3 = y2 * Math.cos(thetaX/100) - z2 * Math.sin(thetaX/100);
                let z3 = y2 * Math.sin(thetaX/100) + z2 * Math.cos(thetaX/100);

                let nx3 = nx2;
                let ny3 = ny2 * Math.cos(thetaX/100) - nz2 * Math.sin(thetaX/100);
                let nz3 = ny2 * Math.sin(thetaX/100) + nz2 * Math.cos(thetaX/100);

                // Z축 회전
                let x4 = x3 * Math.cos(thetaZ/100) - y3 * Math.sin(thetaZ/100);
                let y4 = x3 * Math.sin(thetaZ/100) + y3 * Math.cos(thetaZ/100);
                let z4 = ZZ2 + z3;

                let nx4 = nx3 * Math.cos(thetaZ/100) - ny3 * Math.sin(thetaZ/100);
                let ny4 = nx3 * Math.sin(thetaZ/100) + ny3 * Math.cos(thetaZ/100);
                let nz4 = nz3;

                // 법선 벡터 (nx4, ny4, nz)와 광원의 백터 내적 계산
                // 광원 위치는 (0, 0, -1)
                let lx = 0;
                let ly = 0;
                let lz = -1;
                let light = nx4 * lx + ny4 * ly + nz4 * lz;

                if (light > 0) {
                    let color = Math.round(light * 255);
                    
                    // x' = xz'/z, y' = yz'/z
                    let xp = Math.floor(x4 * ZZ1 / z4);
                    let yp = Math.floor(-y4 * ZZ1 / z4);

                    points.push([xp + ox, yp + oy, 255-color]);
                }
            }
        }

        bufCtx.strokeStyle = "black";
        bufCtx.fillStyle = "black";
        bufCtx.fillRect(0, 0, canvas.width, canvas.height);
        points.forEach(e => drawCircle(e[0], e[1], e[2], 1));

        thetaX = (thetaX + 2) % 629;
        thetaZ = (thetaZ + 2) % 629;
    }

    function OnDraw() {
        _draw();

        cvs.clearRect(0, 0, canvas.width, canvas.height);
        cvs.drawImage(bufCanvas, 0, 0);
    }


    function onLoadPage() {
        InitCanvas();
        OnDraw();
        setInterval(OnDraw, 50);
    }

    window.onload = onLoadPage();
</script>
</body>
</html>
Posted by chobocho
Coding/JavsScript 삽질기2021. 10. 16. 13:54
Coding/JavsScript 삽질기2021. 2. 13. 15:38

Youtube에서 3D 프로그래밍 관련 괜찮은 자료가 있어서 정리를 해 둡니다.

"高校数学とJavaScriptだけ。FPSの作り方 #1【ゲームプログラミング】【ゲーム開発】"

라는 제목의 강의 입니다. 강의 내용을 압축해 두어서, 생략이 많네요;;;

youtu.be/Mtf4rz9UEQo

 

youtu.be/aj1oBvY_LWw

 

youtu.be/34uAtYSirWk

 

Posted by chobocho
Coding/JavsScript 삽질기2020. 9. 23. 23:04

자바스크립트로 테트리스를 만들어 보았습니다.

1) Play 해보기 (크롬만 지원합니다.)

사용키 : 방향키, 스페이스 (블록 아래로 내리기), Ctrl (Hold), S (Start / Resume), P (Pause)

www.chobocho.com/game/tetris/tetris.html

 

Chobocho's Tetris

 

www.chobocho.com

2) Source code

github.com/chobocho/JsTetris/tree/master/src/app/src/main/assets

 

chobocho/JsTetris

Javascript tetris. Contribute to chobocho/JsTetris development by creating an account on GitHub.

github.com

3) UML

Javascript Tetris UML

Posted by chobocho
Coding/JavsScript 삽질기2020. 9. 10. 01:40

자바스크립트를 이용하여 테트리스를 만들고, 이를 Android의 WebView를 이용하여 Android 앱으로 만들어 보았다.

소스코드: github.com/chobocho/JsTetris

 

chobocho/JsTetris

Javascript tetris. Contribute to chobocho/JsTetris development by creating an account on GitHub.

github.com

다운로드: play.google.com/store/apps/details?id=com.chobocho.jstetris

 

Classic Block Game V2 - Google Play 앱

Simple block game

play.google.com

웹 브라우저로 해보기 (크롬에서만 동작 확인을 했습니다)

www.chobocho.com/game/tetris/tetris.html

 

Chobocho's Tetris

 

www.chobocho.com

* 사용키 : 방향키, 스페이스 (블록 아래로 내리기), Ctrl (Hold), S (Start / Resume), P (Pause)

 

Posted by chobocho
Coding/JavsScript 삽질기2020. 1. 13. 01:04

소개 https://chobocho.tistory.com/2461396
실행하기 http://www.chobocho.com/javascript/painter.html
전체 소스코드 https://github.com/chobocho/painter

 

chobocho/painter

Painter written html5. Contribute to chobocho/painter development by creating an account on GitHub.

github.com

9.1 Undo/Redo 기능 구현

Undo/Redo 기능을 구현하기 위해서는 모든 사용자의 동작을 저장해야 합니다

그럼 사용자의 동작을 저장하기 위해서, 선을 그리거나, 원을 그리는 동작을

아래와 같이 커맨드로 정의 해야 합니다.

마우스로 그린 그림

color red 
color lightblue 
rect 8 6 713 356 F 
color white 
ellipse 190 116 93 44 F 
ellipse 456 115 87 42 F 
color black 
ellipse 226 116 31 31 F 
ellipse 489 113 29 30 F 
ellipse 420 277 0 0 F 

그리고 그 커맨드를 stack에 저장합니다.

 

Posted by chobocho

소개 https://chobocho.tistory.com/2461396
실행하기 http://www.chobocho.com/javascript/painter.html
전체 소스코드 https://github.com/chobocho/painter

8.1 저장하기

painter.html에 save를 위한 버튼을 추가 합니다.

<div>
  <a id="saveImage" download="image.png">
      <INPUT type="button" value="Save" onClick="saveImage()" />
  </a>
</div>

그리고, painter.js에 saveImage()함수를 추가합니다.

function saveImage() {
  console.log("saveImage()");
  var imageName = document.getElementById("title").value;
  console.log(imageName.lenght);
  if (imageName.length == 0) {
    imageName = "image";
  }
  imageName += ".png";
  var savedImage = document.getElementById("saveImage");
  var image = document
    .getElementById("canvas")
    .toDataURL("image/png")
    .replace("image/png", "image/octet-stream");
  savedImage.setAttribute("download", imageName);
  savedImage.setAttribute("href", image);
}

여기 까지 소스코드는 아래 링크를 참고 하시면 됩니다.

https://github.com/chobocho/painter/commit/dceabd6f3ace4d39e21260d593dc55a2d15e47df

Posted by chobocho
Coding/JavsScript 삽질기2019. 12. 25. 23:49

소개 https://chobocho.tistory.com/2461396
실행하기 http://www.chobocho.com/javascript/painter.html
전체 소스코드 https://github.com/chobocho/painter

 

chobocho/painter

Painter written html5. Contribute to chobocho/painter development by creating an account on GitHub.

github.com

 

7.1 Refactoring

선, 원등을 그릴때, 반복되는 코드를 preprocessMouseUp(), postprocessMouseUp() 으로 묶습니다.

function circleMouseMove(event) {
  if (!painter.isDraw()) {
    return;
  }
  var currentPos = getMousePosition(event);
  cvs.beginPath();
  // Need a delay
  cvs.clearRect(0, 0, canvas.width, canvas.height);
  cvs.drawImage(bufCanvas, 0, 0);

  cvs.strokeStyle = painter.getColor();

  var circle = {
    X: Math.round((painter.shape.point.x + currentPos.X) / 2),
    Y: Math.round((painter.shape.point.y + currentPos.Y) / 2),
    R: Math.round(Math.abs(currentPos.Y - painter.shape.point.y) / 2)
  };
  cvs.arc(circle.X, circle.Y, circle.R, 0, Math.PI * 2);
  cvs.closePath();
  cvs.stroke();
}

위의 코드를 아래와 같이 수정하였습니다. 기존 함수 내부를 preprocess()와 postprocess()로 나누어서 묶은 것입니다.

Shape.prototype.preprocessMouseUp = function() {
  bufCtx.beginPath();
  bufCtx.strokeStyle = painter.getColor();
}

Shape.prototype.postprocessMouseUp = function() {
  bufCtx.closePath();
  bufCtx.stroke();

  cvs.clearRect(0, 0, canvas.width, canvas.height);
  cvs.drawImage(bufCanvas, 0, 0);

  this.setDrawMode(false);
}

function circleMouseMove(event) {
  if (!painter.isDraw()) {
    return;
  }
  
  painter.preprocessMouseMove();
  
  var currentPos = getMousePosition(event);
  var circle = {
    X: Math.round((painter.shape.point.x + currentPos.X) / 2),
    Y: Math.round((painter.shape.point.y + currentPos.Y) / 2),
    R: Math.round(Math.abs(currentPos.Y - painter.shape.point.y) / 2)
  };
  cvs.arc(circle.X, circle.Y, circle.R, 0, Math.PI * 2);
  
  painter.postprocessMouseMove();
}

 

7.2 나머지 도형 구현

직선, 원과 같이 삼각형, 직사각형에 대해서도 mouseDown, mouseMove, mouseUp에 대한 이벤트를 정의하고

painter 객체에 추가해 줍니다.

 

여기까지의 참고 자료는 아래 링크를 참고 하시면 됩니다.

https://github.com/chobocho/painter/tree/master/doc/tutorial/007

Posted by chobocho
Coding/JavsScript 삽질기2019. 12. 17. 00:22

소개 (https://chobocho.tistory.com/2461396)
실행하기 http://www.chobocho.com/javascript/painter.html
전체 소스코드 https://github.com/chobocho/painter

 

chobocho/painter

Painter written html5. Contribute to chobocho/painter development by creating an account on GitHub.

github.com

6.1 원 그리기

원을 그리는 함수를 추가합니다.

circle = new Shape("Circle");
circle.mouseAction = new MouseAction(circleMouseUp, circleMouseDown, circleMouseMove);
function circleMouseDown(event) {
  console.log("circleMouseDown");
  if (painter.isDraw()) {
    return;
  }
  bufCtx.drawImage(canvas, 0, 0);
  var startPos = getMousePosition(event);
  painter.shape.point.x = startPos.X;
  painter.shape.point.y = startPos.Y;
  painter.setDrawMode(true);
}

function circleMouseMove(event) {
  if (!painter.isDraw()) {
    return;
  }
  var currentPos = getMousePosition(event);
  cvs.beginPath();
  // Need a delay
  cvs.clearRect(0, 0, canvas.width, canvas.height);
  cvs.drawImage(bufCanvas, 0, 0);

  cvs.strokeStyle = painter.getColor();

  var circle = {
    X: Math.round((painter.shape.point.x + currentPos.X) / 2),
    Y: Math.round((painter.shape.point.y + currentPos.Y) / 2),
    R: Math.round(Math.abs(currentPos.Y - painter.shape.point.y) / 2)
  };
  cvs.arc(circle.X, circle.Y, circle.R, 0, Math.PI * 2);
  cvs.closePath();
  cvs.stroke();
}

function circleMouseUp(event) {
  if (!painter.isDraw()) {
    return;
  }

  var currentPos = getMousePosition(event);
  bufCtx.beginPath();
  bufCtx.strokeStyle = painter.getColor();

  var circle = {
    X: Math.round((painter.shape.point.x + currentPos.X) / 2),
    Y: Math.round((painter.shape.point.y + currentPos.Y) / 2),
    R: Math.round(Math.abs(currentPos.Y - painter.shape.point.y) / 2)
  };
  bufCtx.arc(circle.X, circle.Y, circle.R, 0, Math.PI * 2);
  bufCtx.closePath();
  bufCtx.stroke();

  cvs.clearRect(0, 0, canvas.width, canvas.height);
  cvs.drawImage(bufCanvas, 0, 0);

  painter.setDrawMode(false);
}

 

6.2 도형의 선택

원과 선을 선택 할 수 있도록 html 파일에 함수를 연결 합니다.

[paint.js]

function selectShape(choosedShape) {
  console.log("selectShape:" + choosedShape);
  painter.setShape(choosedShape);
}

Painter 객체에 선, 원을 tools라는 자료형에 추가를 합니다.

Painter.prototype.init = function () {
  line = new Shape("Line");
  line.mouseAction = new MouseAction(lineMouseUp, lineMouseDown, lineMouseMove);
  this.tools[line.name] = line;

  circle = new Shape("Circle");
  circle.mouseAction = new MouseAction(circleMouseUp, circleMouseDown, circleMouseMove);
  this.tools[circle.name] = circle;

  this.shape = this.tools["Line"];
  this.color = "black";
}
function onLoadPage() {
  
  // ...

  painter = new Painter();
  painter.init();
}

6.3 기타 수정 사항

color 값은 모든 도형이 공통적으로 사용하므로,
shape 에서 painter 객체로 이동을 합니다.

Painter.prototype.init = function () {
  // ...
  this.color = "black";
}

 

여기까지 소스코드:

https://github.com/chobocho/painter/tree/master/doc/tutorial/006/src

 

chobocho/painter

Painter written html5. Contribute to chobocho/painter development by creating an account on GitHub.

github.com

 

공감과 댓글은 큰 도움이 됩니다.

Posted by chobocho