top drop menu

Recent Post

레이블이 자바스크립트인 게시물을 표시합니다. 모든 게시물 표시
레이블이 자바스크립트인 게시물을 표시합니다. 모든 게시물 표시

목요일, 11월 29

웹 비디오 픽처 인 픽처(PiP) 기능 사용하기

PiP (Picture-in-Picture API)는 웹 페이지가 다른 창 상단에있는 작은 창에서 비디오를 재생할 수있게 해주는 새로운 실험용 웹 플랫폼 API이다. 이 기능은 사용자가 다른 일을하면서 비디오를 계속보고 싶어하는 비디오 사이트, 예를 들어 텍스트 자습서 비디오를 보면서 텍스트 편집기 등에서 코딩하는 비디오 사이트에 유용하다. 브라우저 버전이나 종류에 따라 지원하지 않을 경우가 있다. 크롬 최신 버전은 지원을 한다.


---------- index.html ---------------


<!DOCTYPE html>
<html>
<head>
     <meta charset="utf-8">
     <title>Javascript test 03</title>
     <style>
         body{
             text-align: center;
             display: flex;
             align-items: center;
             justify-content: center;
             flex-direction: column;
         }
         video{
             width: 320px;
             height: auto;
         }

        button{
             margin: 10px auto;
         }

    </style>
</head>
<body>
     <h1 id="title">Javascript Example 03 : PIP 모드에서 영상 재생</h1>

    <video id="video" src="videos/Mountains - 7418.mp4" autoplay loop></video>
     <button id="pipButton">PIP</button>

    <script>
       pipButton.hidden = !document.pictureInPictureEnabled;

      function runPip(){
           if (!document.pictureInPictureElement) {
           video.requestPictureInPicture()
           .catch(error => {
             // Video failed to enter Picture-in-Picture mode.
           });
         } else {
           document.exitPictureInPicture()
           .catch(error => {
             // Video failed to leave Picture-in-Picture mode.
           });
         }
       }


       pipButton.addEventListener('click', function() {
         runPip();
       });
     </script>
</body>
</html>


------------------


아래 사이트에서 확인해 보자.

http://visualssing.dothome.co.kr/javascript/js_example003.html

화요일, 11월 27

자바스크립트와 CSS로 Carousel Slider 만들기

js_logo


jQuery를 이용하는 화려한 슬라이더 효과를 주는 라이브러리들이 많이 있다. 그런것 가져다가 사용하면 편할것 같지만 라이브러리 추가하고 설정을 해줘야 한다. 복잡하고 무겁다. 순수 자바스크립트(바닐라 자바스크립트)와 CSS만으로 간단한 슬라이더 효과를 만들어 보자. 세상.. 심플한것이 제일이다.

------------ index.html --------------

<!DOCTYPE html>
<html>
<head>
     <meta charset="utf-8">
     <title>Javascript Example</title>
     <style type="text/css">
         body{
             font-size: .8em;
             text-align: center;   
             margin: 0; padding: 0;
         }
         .slider{
             width: 100%;
             position: relative;
         }
         .slider_item{
             width: 100%;
             height: 500px;
             overflow: hidden;
             position: absolute;
             z-index: 0;
             opacity: 0;
             transition: all .7s ease-in-out;
             transform: scale(.8);
         }
         img {width: 100%;}

        .showing{
             opacity: 1;
             z-index: 1;
             transform: none;
         }
     </style>
</head>
<body>
     <h1>Javascript Example 001 - 자동 슬라이더</h1>
     <p>자바스크립트와 CSS만으로 Carousel Slider 효과를 구현해 봅니다. </p>

    <!-- Slider -->
     <div class="slider">
         <!-- items -->
         <div class="slider_item"><img src="img/sample01.jpg"></div>
         <div class="slider_item"><img src="img/sample02.jpg"></div>
         <div class="slider_item"><img src="img/sample03.jpg"></div>
         <div class="slider_item"><img src="img/sample04.jpg"></div>
         <div class="slider_item"><img src="img/sample05.jpg"></div>
     </div>

    <script type="text/javascript">
         const showing_class = "showing";
         const firstSlide = document.querySelector(".slider_item:first-child");
         function slide(){
             const currentSlide = document.querySelector(`.${showing_class}`); // showing 클래스가  있는 엘리먼트를 찾는다.
             if(currentSlide){
                 // 지금 shwoing 클래스를 가진 엘리먼트 다음 엘리먼트에 클래스를 추가 한다.
                 currentSlide.classList.remove(showing_class);
                 const nextSlide = currentSlide.nextElementSibling;
                 // 다음 엘리먼트가 있는지 없는지 체크 후 처리
                 if (nextSlide){
                     console.log(currentSlide);
                     nextSlide.classList.add(showing_class);
                 } else {//마지막이면(그다음 형제 엘리먼트가 없으니까) 첫 슬라이드에 추가 함.
                     firstSlide.classList.add(showing_class);
                 }

            } else { // showing 클래스가 지정된 엘리먼트가 없으면 첫번째에 추가해 준다.(페이지 시작시)
                 firstSlide.classList.add(showing_class);
             }
         }

        slide();
         setInterval(slide, 3000); // 1000은 1초
        
     </script>

</body>
</html>


----------------

데모페이지 : http://visualssing.dothome.co.kr/javascript/js_example001.html

토요일, 11월 24

P5.js : 우주 슈팅게임(5)–게임패드 연결

asteroid-1477065_1280
사실 지금까지 해 왔던게 바로 이 게임패드를 연결해 보려고 했던것이었다.  게임패드 용도에 맞게 하나의 게임이 필요해서 P5.js로 만드는 게임을 지금 까지 해 봤던 것이다. 최신 웹 브라우저에서는 게임패드를 인식하고 사용할 수 있도록 기본으로 되어 있는데, 물론 브라우저마다 안되거나 약간 다른 용법을 사용한것 같기도 하다. 아직 지원하지 않기도 하는 모양이다. 여기서는 윈도우10에서 크롬브라우저를 기준으로 예제를 만들었다. 다른 환경에서 테스트는 해 보지 않았다.  제일 먼저 html 문서를 보자.
-------------------index.html-----------------
<!doctype html>
<html lang="ko">
  <head>
   <meta name="viewport" content="width=device-width, user-scalable=no">
   <meta charset="UTF-8">
   <meta name="Description" content="">
   <title>P5.JS 연습</title>
   <link href="https://fonts.googleapis.com/css?family=Orbitron" rel="stylesheet">
   <style type="text/css">
        body{
       text-align: center;
       margin: 0px;
       padding: 0px;
     }
      p{
       font-size: .8em;
      }
      #defaultCanvas0{
     }
   </style>
   <!--공통-->
   <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.min.js"></script>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/addons/p5.sound.min.js"></script>
   <!--프로젝트 스크립트-->
   <script src="sketch19-final.js"></script>
   <script src="ship3.js"></script>
   <script src="asteroid.js"></script>
   <script src="laser.js"></script>
   <script src="particle2.js"></script>
   <script src="explode.js"></script>
   <script src="firework.js"></script>
</head>
  <body>
   <h1>P5.js Example 19-final(Simple Game)</h1>
   <audio autoplay controls preload="auto" loop  id="myAudio">
      <source src="http://soundimage.org/wp-content/uploads/2014/04/Game-Menu.mp3">
      Your browser does not support the audio element. 
  </audio>
  <p>게임패드 이동: 왼편 스틱, 슈팅: 오른쪽 R2,  재시작 : F5, BGM : Music by Eric Matyas www.soundimage.org</p>
  
  </body>
</html>
---------------------------------------------
필요한 자바스크립들은 별도의 파일로 만들고 링크해서 사용하도록 하였다. 이문서는 간단하다.
-----------------sketch.js-----------------
var ship;
var asteroids = [];
var lasers = [];
var font, fontsize = 15;
var health = 100;
var shoot;
var bomb;
let particles = [];//var와 let의 차이를 모르겠음? let이 더 엄격하다 정도만.
var fireworks = [];
function preload(){
     shoot = loadSound('sound/laser_shoot.mp3');
     bomb = loadSound('sound/bom.wav');
}

function setup() {
     createCanvas(800, 480);
     //createCanvas(windowWidth,windowHeight);
     font="Orbitron";
     textFont(font);
     textSize(fontsize);
     //우주선 생성
     ship = new Ship();
     //소행성 생성
     for(let i =0; i < 10; i++){
         asteroids.push(new Asteroid());
     }
}
function draw() {
     background(0);
    // Gamepad
     pads = navigator.getGamepads();
     pad0 = pads[0];
    if(pad0){
         // 오른쪽 R2 버튼(앞면 큰 버튼)
         if (pad0.buttons[7].value > 0.6 && pad0.buttons[7].pressed == true){
             lasers.push(new Laser(ship.pos, ship.heading));//너무 연속적으로 추가 되는 문제
             shoot.play();
         }
         // 스틱
         if(pad0.axes[0] >= .5 ){
             ship.boosting(true);
         } else if(pad0.axes[0] <= -.5) {
             ship.boosting(true);
         } else if (pad0.axes[1] < -.5){
             ship.boosting(true);
         } else if (pad0.axes[1] > .5){
             ship.boosting(true);
         }
     }
    ship.c = color(100, 255, 100,  255);
     // Backgroud Particle
     let p = new Particle();
     particles.push(p);//draw()에 동작해서 계속해서 객체를 만들어 추가한다.
     for(let i = particles.length-1; i >= 0; i--){
         particles[i].update();
         particles[i].show();
         if(particles[i].finished()){
             particles.splice(i, 1);
         }
     }
    
     // Explosion
     for(var i = 0; i < fireworks.length; i++){
         fireworks[i].run();   
         if(fireworks.length>10){
             fireworks.splice(0, 1);
         }
     }
    //소행성
     for (var i = 0; i < asteroids.length; i++){
         //소행성과 우주선이 충돌하면
         if(ship.hits(asteroids[i])){
             //console.log("hit");
             ship.c = color(255, 0, 0,  255);
             health = health - asteroids[i].r * 0.05;
         }
        asteroids[i].update();
         asteroids[i].render();
         asteroids[i].edges();
     }
    // 레이저
     for (var i = lasers.length -1; i >= 0; i--){
         lasers[i].update();
         lasers[i].render();
         // 화면을 벗어나면 제거 해줌
         if(lasers[i].offscreen()){
             lasers.splice(i, 1);
         } else {
             // 충돌 감지
             for(var j = asteroids.length-1; j >= 0; j--){
                 if(lasers[i].hits(asteroids[j])){
                     //console.log('hit');
                     health = health + asteroids[j].r * 0.1;
                     if(asteroids[j].r > 10) {
                             var newAsteroids = asteroids[j].breakup();// 충돌된 소행성을 쪼갠다.
                             asteroids = asteroids.concat(newAsteroids);
                     }
                     fireworks.push(new Firework(lasers[i].pos.x, lasers[i].pos.y));
                     asteroids.splice(j, 1); //j번째 1개를 제거한다.
                     lasers.splice(i, 1);
                     bomb.play();
                    break;
                 }
             }
        }
     }
    // 우주선
     ship.render();
     ship.turn();
     ship.update();
     ship.edges();
    // Score
     drawScore();
}
// Score and Health
function drawScore(){
     fill(255);
     if(health <= 0){
         text("Game Over", 30, 30);
     } else {
         text(Math.ceil(health), 30, 30);
     }
     if (asteroids.length <= 0){
         text("You Win", 30, 50);   
     }
}
----------------------------
메인 스케치 파일이다. 키보드 조작기능은 제거를 했다. 게임패드와 키보드 조작을 다 같이 사용하게 할려면 설정 코드가 더 필요한데 귀찮다. 원래 목적대로 게임패드만 사용하게 해 주자.  이 메인 스케치 이외에 우주선, 소행성, 레이저, 폭발효과를 위한 객체 클래스들이 필요하다. 이걸 다 일일히 여기 적기는 힘들고 자바스크립트 이니 소스가 다 보인다. 찾아서 참고 하면 될듯 하다. ^^;
기본 게임 만드는 유튜브로 만든 것에 필요한 기능 몇가지를 추가해 준것이다. 사운드 효과를 주면 더 게임 다워 진다.
이미지 130
게임패드의 왼쪽 조이스틱(맞나 용어가?)를 이용해서 우주선을 움직이게 하는데 이게 키보드 이동키로 단순히 회전하고 전진하고 하는 것과는 좀 다르게 해 줄 필요가 있었다. 상하좌우 아무곳으로나 이동이 가능하게 해주고 해당 방향으로 움직이면 그 방향으로 우주선 헤드가 돌아 가도록 해줘야 했다. 이것을 구현하는게 난감하게 생각되었는데 의외로 간단히 구현 할 수 있었다.
---------------ship.js-------------------
this.turn = function(){
         //this.heading += this.rotation;
         this.heading  = this.vel.heading();
     }
--------------------------------------------
vel 벡터의 heading() 을 적용하니 쉽게 구현이 되었다. 좋아~  스틱의 움직임에 따라 우주선이 자유롭게 조정이 가능했다. 정밀하게 제어하기는 힘들지만 이정도면 충분해 보인다.  마지막 최종 결과는 아래 링크에서 확인해 보자. 물론 호환이 되는 기본형 게임패드가 있어야 게임이 가능하다. 없는 사람에게는 아무것도 해 볼 수 업다. ^^; 데모 영상은 차후 만들어서 추가해 볼 예정이다.

http://visualssing.dothome.co.kr/p5js/p5js_exam19-final.html


자바스크립트와 P5.js에서 게임패드 사용하기

일전에 뷰잉에서 게임이나 가끔 해볼까 하고 게임패드를 하나 구입했었다. 이 게임패드를 크롬 브라우저에서 자바스트립트를 이용해서 활용해 보기로 하자. 먼저 간단히 게임패드들의 버튼들을 인식하는 예제를 만들어 보자.

20181120_191657


<!doctype html>
<html lang="ko">
  <head>
   <meta name="viewport" content="width=device-width, user-scalable=no">
   <meta charset="UTF-8">
   <meta name="Description" content="">
   <title>P5.JS 연습</title>
   <style type="text/css">
        body{
       text-align: center;
     }
      p{
       font-size: .9em;
      }
      #defaultCanvas0{

     }

     #screen{
       width: 80px;
       height: 80px;
       margin: 0 auto;
       position: relative;
      }

     #ball {
         width: 80px;
         height: 80px;
         border-radius: 40px;
         background-color: red;
         position: relative;
         line-height: 75px;
         text-align: center;
         font-size: 40px;
       }
   </style>
   <!--공통-->
   <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.min.js"></script> -->
   <!--프로젝트 스크립트-->
   <!-- <script src="sketch21.js"></script>
   <script src="gamepad.js"></script> -->
  </head>
  <body>
   <h1>P5.js Example 21</h1>
   <p id="gamepad-info">Waiting for Gamepad.</p>
   <div id="screen">
     <div id="ball"></div>
   </div>

  <script type="text/javascript">
     var gamepadInfo = document.getElementById("gamepad-info");
     var ball = document.getElementById("ball");
     // pos
     var a = 0;
     var b = 0;
     var start;
     var text = "";

    // webkitRequestAnimationFrame
     var rAF = window.mozRequestAnimationFrame ||
         window.webkitRequestAnimationFrame ||
         window.requestAnimationFrame;

    var rAFStop = window.mozCancelRequestAnimationFrame ||
       window.webkitCancelRequestAnimationFrame ||
       window.cancelRequestAnimationFrame;

    // Check connection
     window.addEventListener("gamepadconnected", function(e) {
       var gp = navigator.getGamepads()[e.gamepad.index];
           gamepadInfo.innerHTML = "Gamepad connected at index "+gp.index+": "+gp.id+", "+gp.buttons.length+" buttons, "+gp.axes.length+" axes";
    
       gameLoop();
     });

    // Check disconnection
     window.addEventListener("gamepaddisconnected", function() {
       gamepadInfo.innerHTML = "Waiting for gamepad.";

      //rAFStop(start);
     });

    function gameLoop() {
       if(navigator.webkitGetGamepads) {//이게 아니다.
         console.log(webkitGetGamepads);
       } else {
         var gp = navigator.getGamepads()[0];


         if(gp.axes[0] !=0 || gp.axes[1] != 0){
           a += gp.axes[0];
           b += gp.axes[1];
           text= "Ax";
         }

        if(gp.buttons[0].value > 0 || gp.buttons[0].pressed == true) {//A button
           text = "A";
         } else if(gp.buttons[1].value > 0 || gp.buttons[1].pressed == true) {//B button
           text = "B";
         } else if(gp.buttons[2].value > 0 || gp.buttons[2].pressed == true) {//X button
           text = "X";
         } else if(gp.buttons[3].value > 0 || gp.buttons[3].pressed == true) {//Y button
             text = "Y";
         }

      }

      ball.style.left = a*4 + "px";
       ball.style.top = b*4 + "px";
       ball.innerHTML = text;

      var start = rAF(gameLoop);
     };

  </script>
  
  </body>
</html>

간단히 div 로 만든 빨간 써클을 게임패드로 움직일 수 있는 예제이다.

이미지 127

왼편 조이스틱과 오른쪽 버튼들에게 기능을 지정해 주었다. 두번째 예제는 p5.js안에서 직접 코드를 작성하는 예제도 만들어 보자. 게임패드 각각의 버튼들의 값들을 출력해 주는 예제이다.


var pads, pad0;

function setup(){
     createCanvas(640, 480);
     textSize(14);
     stroke(80);
     strokeWeight(.3);
}

function draw(){
     background(0);
     fill(255);

    pads = navigator.getGamepads();
     pad0 = pads[0];
    
     text('ID: ', 10, 20);
     if(pad0){
         //console.log(pad0.buttons.length);
         text(pad0.id, 35, 20)
         text('-----', 15, 40);
         for(var i =0; i < pad0.buttons.length; i++){
             text('Button'+i+': ' + pad0.buttons[i].value, 15, 60 + 20 * i);
             //console.log(pad0.buttons.length);
         }text('-----', width/2, 40);
         for (var i = 0; i < pad0.axes.length; i++) {
             text('axes' + i + ': ' + pad0.axes[i], width/2, 60 + 20 * i);
         }
     }
}

이미지 128

연결된 게이패드의 버튼과 조이스틱을 움직여 보면 값들이 변하는 것을 확인 할 수 있다. 대부분의 버튼은 0과 1이다. 조이스틱은 –1에서 1사이의 값을 가진다. 이렇게 게임패드의 버튼들의 값이 p5.js로 전달 되었으니 이것을 이용해서 화면안에서 사용할 수 있게 된다.



금요일, 11월 23

프로세싱(115) : P5.js 파티클시스템의 예제

곁다리… 앞서 만든 게임에서 폭파효과를 주기 위해 필요해서 따로 예제를 만들어 보았다.

<!doctype html>
<html lang="ko">
  <head>
   <meta name="viewport" content="width=device-width, user-scalable=no">
   <meta charset="UTF-8">
   <meta name="Description" content="">
   <title>P5.JS 연습</title>
   <style type="text/css">
        body{overflow-x : hidden; overflow-y: hidden; text-align: center;}
      p{
       font-size: .9em;
      }
      #defaultCanvas0{

     }
   </style>
   <!--공통-->
   <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.min.js"></script>
   <!--프로젝트 스크립트-->
   <script src="sketch20.js"></script>
   <script src="explode.js"></script>
   <script src="firework.js"></script>
  </head>
  <body>
   <h1>P5.js Example 20(Particle system)</h1>
   <p>마우스를 클릭하세요</p>
  
  </body>
</html>

마우스를 클릭하면 사방으로 퍼지는 파티클이 생성되었다가 사라진다.

var fireworks = []; //array

function setup(){
     createCanvas(640, 480);
}

function draw(){
     background(0);

    for(var i = 0; i < fireworks.length; i++){
         fireworks[i].run();   
         if(fireworks.length>10){
             fireworks.splice(0, 1);
         }
     }
}

// 마우스를 클릭하면 새로운 파티클을 firewroks array에 추가한다.
function mousePressed() {
   fireworks.push(new Firework(mouseX, mouseY));
}

이중구조 배열에 파티클을 담는다.

function Particle(x, y){
     this.pos = createVector(x, y);
     this.vel = createVector(random(-2, 2), random(-2, 2));
     this.acc = createVector(0,0);
     this.alpha = 255;

    this.finished = function(){
         return this.alpha < 0;
     }

    // 중력을 주고 싶으면 사용
     this.applyForce = function(force){
         this.acc.add(force);
     }

    this.update = function(){
         this.vel.add(this.acc);
         this.pos.add(this.vel);
         this.acc.mult(0);
         this.alpha -= 6;
     }

    this.show = function(){
         stroke(255, this.alpha);
         strokeWeight(2);
         point(this.pos.x, this.pos.y);
     }
}


그 결과는 아래 링크에서 확인 하자.

http://visualssing.dothome.co.kr/p5js/p5js_exam20.html

프로세싱(114) : P5.js 우주 슈팅 게임(3)

asteroid-1477065_1280

이제 게임에 사운드와 몇가지 효과를 추가하자.  P5.js에서 사운드를 사용하기 위해서는 오디오 관련 라이브러리를 사용해야 한다.

<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/addons/p5.sound.min.js"></script>

이미지 126


배경에 파티클을 이용해서 저 멀리 별들도 그려 주자. 우주공간이 이잖아. 사운드 이펙트는 레이저빔 소리와 행성 쪼개지는 소리(이건 별로 마음에 안듬)를 넣어 주었다. 핼쓰(스코어)  수치도 넣어 주었다. 이제 더이상 할게 없다. ^^; 최종 결과는 아래 링크에서 확인 하자.

http://visualssing.dothome.co.kr/p5js/p5js_exam19-3.html

목요일, 11월 22

프로세싱(113) : P5.js 우주 슈팅 게임(2)

asteroid-1477065_1280

이제 떠돌아 다니는 소행성들을 만들어 주자. 마찬가지로 아래 유튜브 영상을 따라가자.

https://youtu.be/hacZU523FyM

  • 다수의 asteroid를 만들어 줘야 한다. 모양도 제각각이다. Asteroid 클스를 이용하여 원하는 갯수만큼 만들어 주면 된다.  여러가지 모양은 vertex를 이용해서 꼭지점의 위치에 무작위 변화를 주어 다른 모양으로 그려 준다. 기본적인 동작은 동일하다. 화면을 벗어 나면 반대편에서 다시 나오게 되어 있다.

http://visualssing.dothome.co.kr/p5js/p5js_exam19-1.html

이제 우주선에서 레이저가 발사 되게 만들어 주고 소행성들에 레이저가 맞게 되면 소행성이 둘로 쪼개지도록 해준다.  지정한 크기의 행성을 맞추면 완전히 제걱 된다. 자세한 내용는 아래 유트브를 따라 가자.

https://youtu.be/xTTuih7P0c0

이미지 125

이제 어느정도 게임이 기본 형태를 갖췄다. 필요하다면 점수판을 넣어 주고 오디오 효과도 넣어 주도록 하자.  최종 결과는 아래 링크로 확인 하자.

http://visualssing.dothome.co.kr/p5js/p5js_exam19-2.html

프로세싱(112) : P5.js 우주 슈팅 게임(1)

asteroid-1477065_1280

P5.js를 이용하여 게임을 만드는 유튜브 동영상을 따라서 간단히(?) 게임을 하나 만들어 보자. 코드를 작성하는게 중요한게 아니고 코드의 의미를 이해하는 것이 더 중요하다. 제일 먼저 우주선 클래스를 만들고 플레이어가 될 우주선을 하나 만들어 키보드에 따라 움직이도록 하는 작업을 하자. 자세한 내용은 아래 링크이 동영상을 참조 하자. 게임의 목표는 떠 돌아 다니는 소행성을 모두 제거하면 된다.

https://youtu.be/hacZU523FyM

이거 하나 움직이는데도 코드가 복잡하다. 최종 결과물은 실제 우주공간에 떠 있는 것처럼 끊어 지지 않고 유영하듯이 잘 움직이다. 화살표 키보드에 의해 동작된다. 좌, 우키로 방향을 전환하고 업키로는 우주선을 전진하게 한다.

1차 결과는 아래 링크에서 확인하자. 따라 한거라서 별 쓸 내용이 없다 ^^;

http://visualssing.dothome.co.kr/p5js/p5js_exam19.html

이제 소행성들을 만들어 주자.

다음편에 계속 …

화요일, 11월 20

크롬 브라우저에서 음성인식 SpeechRecognition API 구현(2)

파트1에 이어서 이번에는 좀 더 기능을 추가해 보기로 하자. 앞서 크롬 브라우저에서 음성을 인식하고 텍스트를 화면에 출력해 주는 것 까지 구현이 되었다. 여기다 한글 텍스트를 영문으로 번역하고 그 결과를 음성으로 읽어 주는 기능을 추가하자. 번역 API를 찾아 보니 몇가지 대안이 있는데 강력한 후보이 구글번역 API가 유료로 전환된듯 결제설정을 하라고 나온다. 이런…

  • 구글 Translate API
  • Microsoft Azure Translate API
  • Yandex

구글은 유료(정확하지 않음)이고 마이크로소프트는 12개월 무료인데 그후엔 유료라고 한다. 결국 선택한것은 Yadex라는 API 서비스이다. 그런데 문제는 번역 품질이 시원찮다. 일단 흐름을 파악하기 위해서 이것을 이용해 보기로 하자.


https://tech.yandex.com/translate/


위 링크에서 회원가입을 하고  API 키를 발급 받아야 한다.


function translate_yandex(txt){
             var url = "https://translate.yandex.net/api/v1.5/tr.json/translate",
             keyAPI = "your_yandex_api_key";

            var xhr = new XMLHttpRequest(),
             textAPI = txt;
             langAPI = "en";

        //     https://translate.yandex.net/api/v1.5/tr.json/translate
                  // ? key=<API key>
                  // & text=<text to translate>
                  // & lang=<translation direction>
                  // & [format=<text format>]
                  // & [options=<translation options>]
                  // & [callback=<name of the callback function>]

            data = "key="+keyAPI+"&text="+textAPI+"&lang="+langAPI;
             xhr.open("POST",url,true);
             xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
             xhr.send(data);
             xhr.onreadystatechange = function() {
                 if (this.readyState==4 && this.status==200) {
                     var res = this.responseText;
                     console.log(res);
                     //document.querySelector('#json').innerHTML = res;
                     var json = JSON.parse(res);
                     if(json.code == 200) {
                         console.log(json.text[0]);
                         english.innerHTML = json.text[0];
                         text_to_speech(json.text[0]);

                    }
                     else {
                         console.log("Error Code: " + json.code);
                         //document.querySelector('#output').innerHTML = "Error Code: " + json.code;
                     }
                 }
             }
         }


함수를 추가하자. 앞 파트1에서 나온 음성인식 결과를 인자로 넣어서 호출해 주면 된다.


데모링크 : https://timbuktu031.github.io/voice_recogintion/


translate-3796096_640

월요일, 11월 19

크롬 브라우저에서 음성인식 SpeechRecognition API 구현

이것은 현재 구글 크롬 브라우저에서만 가능한것 같다. 다른 브라우저(파이어폭스, 익스플로러)에서는 되지 않는다. 간단히 예제를 만들어 보자.

이미지 124

페이지에 접속하면 이런 화면이다. Start버튼을 누르면 SpeechRecognition 을 음성인식이 시작된다. 인식된 데이터를 왼쪽 필드에 출력해 준다. 이어서 speechSynthesis 를 이용해서 음성으로 출력해 주게 된다.  일단 여기 까지만 구현해 보자.


<!DOCTYPE html>
<html>
<head>
     <meta charset="utf-8">
     <title>Speech to Text</title>
     <style>
         body{
             text-align: center;
         }

        button{
             padding: 8px;
             /*border-radius: 6px;*/
         }
         #message {
             color: #996600;
         }

        .textWrapper{
             width: 800px;
             margin: 0 auto;
             display: flex;
             flex-direction: row;
         }
         .textbox{
             height: 100px;
             border: 1px solid #d3d3d3;
             flex: 1;
             margin : 5px 15px;
             border-radius: 6px;
             text-align: left;
             padding: 16px;
         }
     </style>
     <!-- <script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.js"></script> -->
     <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/annyang/2.6.0/annyang.min.js"></script> -->
</head>
<body>

    <h1>Speech to Text Example!!!</h1>

    <button id="speech" onclick="speech_to_text()">Start STT</button>
     <button id="stop" onclick="stop()">Stop</button>
     <p id="message">버튼을 누르고 아무말이나 하세요.</p>

    <div class="textWrapper">
         <div id="korea" class="textbox"></div>
         <div id="english" class="textbox"></div>
     </div>

    <script type="text/javascript">

        var message = document.querySelector("#message");
         var button = document.querySelector("#speech");
         var korea = document.querySelector("#korea");
         var english = document.querySelector("#english");
         var isRecognizing = false;

        if ('SpeechRecognition' in window) {
           // Speech recognition support. Talk to your apps!
           console.log("음성인식을 지원하는 브라우저입니다.")
         }

        try {
             var recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition || window.mozSpeechRecognition || window.msSpeechRecognition)();
         } catch(e){
             console.error(e);
         }

        recognition.lang = 'ko-KR'; //선택하게 해줘야 할듯 .
         recognition.interimResults = false;
         recognition.maxAlternatives = 5;
         //recognition.continuous = true;


         function speech_to_text(){
            
             recognition.start();
             isRecognizing = true;

            recognition.onstart = function(){
                 console.log("음성인식이 시작 되었습니다. 이제 마이크에 무슨 말이든 하세요.")
                 message.innerHTML = "음성인식 시작...";
                 button.innerHTML = "Listening...";
                 button.disabled = true;
             }
            

            recognition.onspeechend = function(){
                 message.innerHTML = "버튼을 누르고 아무말이나 하세요.";
                 button.disabled = false;
                 button.innerHTML = "Start STT";
             }

            recognition.onresult = function(event) {
                 console.log('You said: ', event.results[0][0].transcript);
                 // 결과를 출력
                 var resText = event.results[0][0].transcript;
                 korea.innerHTML = resText;

                //text to sppech
                 text_to_speech(resText);
                
             };

            recognition.onend = function(){
                 message.innerHTML = "버튼을 누르고 아무말이나 하세요.";
                 button.disabled = false;
                 button.innerHTML = "Start STT";
                 isRecognizing = false;

            }
         }

        function stop(){
             recognition.stop();
             message.innerHTML = "버튼을 누르고 아무말이나 하세요.";
             button.disabled = false;
             button.innerHTML = "Start STT";
             isRecognizing = false;
         }


        // Text to speech
         function text_to_speech(txt){
             // Web Speech API - speech synthesis
             if ('speechSynthesis' in window) {
              // Synthesis support. Make your web apps talk!
                  console.log("음성합성을 지원하는  브라우저입니다.");
             }
             var msg = new SpeechSynthesisUtterance();
             var voices = window.speechSynthesis.getVoices();
             //msg.voice = voices[10]; // 두번째 부터 완전 외국인 발음이 됨. 사용하지 말것.
             msg.voiceURI = 'native';
             msg.volume = 1; // 0 to 1
             msg.rate = 1.3; // 0.1 to 10
             //msg.pitch = 2; //0 to 2
             msg.text = txt;
             msg.lang = 'ko-KR';

            msg.onend = function(e) {
                 if(isRecognizing == false){
                     recognition.start();   
                 }
                   console.log('Finished in ' + event.elapsedTime + ' seconds.');
             };
             window.speechSynthesis.speak(msg);
         }

    </script>

</body>
</html>


전체 코드인데 제대로 된건지는 아직 모르겠다. 일단 작동은 하니깐. 여러가지 메소드들이 있는데 정확한 사용법은 앞으로  예제를 더 만들어 보면서 바로 잡도로 하자. 예제는 단순히 앞 음성인식이 끝이 나면 자도으로 다시 음성인식을 시작하도록 하였다. 다른 방법도 있을것 같은데 …  자세한 내용은 아래 사이트를 참조 하자.


https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition


앞으로 계획은 한글로 인식된 음성을 gTTS를 이용해서 영어로 번역해서 음성으로 출력하게 하면 된다. 자동 영어 번역기 ㅋㅋ  한글-> 영어 혹은 영어 –> 한글을 옵션으로 선택하게 해주는 버튼도 추가를 해줘야 할것 같다.


데모 사이트 : https://timbuktu031.github.io/voice_recogintion/

크롬 브라우저에서만 테스트 가능하다. 이게 문제네…

google-chrome-1326908_640

금요일, 11월 16

자바스크립트 jQuery를 이용한 이미지에서 얼굴인식

jQuery를 이용하여 간단히 이미지의 얼굴을 인식하게 해주는 라이브러리가 있다. 아래 링크에서 확인하자.

https://github.com/jaysalvat/jquery.facedetection

먼저 먼저 html에 사진을 배치 하자. 그리고 하단에 인식을 시작하는 버튼을 만들자.

이미지 120

<!DOCTYPE html>
<html>
<head>
     <title>face detection</title>
     <style>
         body {text-align: center;}
         button {
             margin-top: 20px;
         }
         #wrapper{
             position: relative;
             display: flex;
             align-items: center;
               justify-content: center;
             margin: 0 auto;
         }
         .face {
             position: absolute;
             border: 2px solid #ff3333;
         }
     </style>
</head>
<body>

    <h1>jQuery FaceDetection Demo</h1>

    <div id="wrapper">
         <img src="images/sample01.jpg" class="pic" id="picture">
         <img src="images/sample02.jpg" class="pic" id="picture">
     </div>

    <button id="startButton">얼굴인식 시작</button>

    <script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.js"></script>
     <script type="text/javascript" src="dist/jquery.facedetection.min.js"></script>
     <script type="text/javascript">
        
         /* global $ */
         $(function () {
             "use strict";
             var clicked = 0;

            $(window).resize(function(e){
                 //e.preventDefault();
                 if(clicked == 1){
                     faceDetaction();
                 }
             });

            $('#startButton').click(function(e){
                 e.preventDefault();
                 clicked = 1
                 //console.log('click');
                 faceDetaction();
             });


             function faceDetaction(){
                 $('.face').remove();//기존의 박스를 지우고
                 $('.pic').faceDetection({
                     complete: function(faces){
                         //console.log(faces);

                        for (var i = 0; i < faces.length; i++) {
                             $('<div>', {
                                 'class':'face',
                                 'css': {
                                     'position': 'absolute',
                                     'left':     faces[i].positionX + 'px',
                                     'top':      faces[i].positionY + 'px',
                                     'width':    faces[i].width  * faces[i].scaleX + 'px',
                                     'height':   faces[i].height * faces[i].scaleY + 'px'
                                 }
                             })
                             .insertAfter(this);
                         }

                    }, error: function(code, message){
                         console.log("Error: " + message);
                     }

                });
             }

        });
     </script>

</body>
</html>


버튼을 클릭하면 이미지에서 얼굴을 인식하고 사각 박스를 그려 준다.

이미지 121

https://timbuktu031.github.io/jquery.facedetection/

화요일, 11월 13

Node.js(7) Heroku에 Node.js 앱(홈페이지) 배포하기

앞서 만들고 있는 Node.js로 만든 홈페이지를 무료로 Heroku(히로쿠)  에 올려서 누구나 접속 하도로고 해보자. 배포라는 말을 쓰기도 하는것 같은데 홈페이지를 배포한다고? ^^; 아직 완성이 안된것이지만(언제 끝이 날지도 모르고 해서) 배포를 어떻게 하는지 그 절차가 궁금하다. 이 작업은 윈도우에서 해도 되고 리눅스나 라즈베리파이에서도 가능하다. 일단 기존에 작업을 라즈베리파이에 올려서 하던 중이니 라즈베리파이에서 해보기로 하자.
Heroku는 헤로쿠는 웹 애플리케이션 배치 모델로 사용되는 여러 프로그래밍 언어를 지원하는 클라우드 PaaS이다. PaaS? 이건또 뭐냐? 아뭏든 이것을 이용하면 Node.js로 만든 홈페이지를 공개할 수 있다는 것 같다. 일단 무료인데 조건이 좀 까다롭다. 접속자가 없으면 잠자기 모드로 들어간다고 한다. 자세한 것은 아래 사이트에서 확인 하자.
https://www.heroku.com
라즈베리파이에서 진행하는 간단한 절차
sudo apt update
sudo apt install snapd
sudo reboot
이제 snap을 설치했으니 heroku cli를 설치하면 된다. cli는 명령 줄 인터페이스라는 뜻이다. 한마디로 터미널로 조작하는 거인듯 …
sudo snap install heroku –classic
heroku login
이미지 114
터미널 상태에서  로그인을 지원하지 않는다. 주소를 보여주는데 그 주소를 복사해서 아무 컴 브라우저를 열어서 접속하여 로그인을 진행하면 된다. 그리고 브라우즈는 닫아도 된다. 그러면 터미널에서 로그인 된 상태로 진행이 되어 있다.  로그인이 되었으면 간단히 heroku로 부터 기본 프로젝트를 하나 clone해서 동작을 시켜 보기로 하자.
git clone https://github.com/heroku/node-js-getting-started.git
cd node-js-getting-started/
이미지 115
패키지를 열어 보면 필요한 의존성 패키지 정보가 들어 있다. 이것을 라즈베리파이에서 실행해 볼려면 이 패키지들을 이 프로젝트에 설치해서 줘야 한다.
npm install
해주고 이 프로젝트를 실행시켜 보자. 
node index.js
포트 5000번으로 서버가 실행되었다고 터미널에 출력된다. 이제 웹브라우저로 접소개 보자.
이미지 116
잘 들어 간다. 앞에서 다운로드 받은 프로젝트가 이런 모양이라는 것이다. 이 기본틀을 가지고 사용자가 원하는 모양으로 수정해서 자신의 홈페이지를 만들거나 아니면 독자적으로 원하는 형태의 홈페이지를 만들면 된다는 것이다. 어쨌든 이렇게 저렇게 홈페이지를 만들었다면 이제 이것을 다시 heroku에 올려서 배포를 시켜야 한다. 이 샘플을 사용할것은 아니고 앞서 만들고 있는 홈페이지를 업로드 시켜 보기로 하자.
heroku create ghostsocket01
Heroku에 저장소를 만들어야 한다. 그냥 create하면 랜덤 이름으로 만들어주는것 같다. 프로젝트 이름으로 만들어 주면 될듯 하다. 중복되는 이름이 있으면 생성되지 않는다.
공식 가이드에는 언급이 없지만 로컬 저장소에서 파일 수정이 있거나 하면(있어야 가능한듯) commit를 해주는 과정이 필요한듯 하다.  일부러 쓸데 없는 파일 만들고 하라고 하는 사람도 있다.
git add .
git commit –m “message…블라블라”
하고 나서 push를 해줘야 한다.
git push heroku master
라고 하면 된다고 가이드에는 되어 있는데 이것은 다운로드 받은 것을 그대로 수정해서 하는 경우를 염두에 두고 한 듯 하다. 내가 작업 중이든 프로젝트를 올리려고 하니 에러 나고 난리도 아니다.  git 자체에 config 설정이 빠진 부분이 있어서 수정했다. 이메일과 이름을 설정하라는 에러이다. 설정하고 다시 시도 하니 또 에러다. npm start 가 설정이 안되어 있다는 것 같다. 음~ 이건 또 뭔가?
{
   "name": "web2018",
   "version": "1.0.0",
   "description": "",
   "main": "app.js",
   "scripts": {
     "start": "node app.js",
     "test": "echo \"Error: no test specified\" && exit 1"
   },
   "author": "",
   "license": "ISC",
   "dependencies": {
     "body-parser": "^1.18.3",
     "ejs": "^2.6.1",
     "express": "^4.16.4"
   }
}

빨간색 부분이 누락되어 있어서 추가해 주었다.  최초 실행되는 스크립트 파일명을 적어 주는 듯 하다. 로컬에서 할땐 언급 없더니? 아뭏든 이렇게 수정하고 다시 시도! 또 에러가 업로드는 되었는데 해상 사이트가 열리지 않고 에러가 난다.  일단 오픈하는 과정은 아래와 같다.
heroku ps:scale web=1
이건 의미를 모르겠다. 일단 하자.
heroku open
하면 윈도우라면 자동으로 웹브라저가 열리면서 오픈이 되는 모양인데 라즈베리파이라서 웹브라우저를 열지 못하는 건지 열리지 않고 메세지를 출력한다.
이미지 117
직접 저 주소로 웹브라우저 접속해 보라는 것이다. https://ghostsocket01.herokuapp.com 이게 내 사이트 주소가 된다. 이름을 막 지을게 아니네…!
그런데 또 에러다… 오마이캇! 문제는 포트관련 작성 방법이다. app.js파일을 수정하자.
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(express.static(__dirname + '/public'));
app.use(bodyParser.urlencoded({extended : true}));
app.set('view engine', 'ejs');//ejs 템플릿 엔진  연동

// route setting - 라우팅(routing)
app.get('/', function (req, res) {
   //res.send('Hello World!');
   var data = req.body.name;
   res.render('index', {name: data});//views디렉토리안에 있는 index.ejs 파일
});

app.listen(process.env.PORT || 5000, function(){
     console.log('App Listening on port 5000');
});

포트번호는 문제가 아닌데 단순히 포트번호만 적지 말고 process.env.PORT를 같이 기술해 줘야 하는가 보다. 이렇게 수정하고 다시 오픈을 해보니 정상적으로 동작한다. 초기에 샘플로 받은 프로젝트에 index.js파일을 열어 보면 이런식으로 되어 있는 것을 확인 할 수 있다. 대충 보고 했더니 ….
이렇게 하면 내 로컬에 있던 node.js로 만든 사이트를 인터넷에 공개 할 수 있다.
https://ghostsocket01.herokuapp.com
궁금하면 … ^^ 아직 작업중인것이라서 …  대충 이런 흐름으로 heroku 를 이용하여 앱을 배포할 수 있다는 것이다. 중간에 에러가 나서 개고생했는데 에러 메세지나 구글 검색으로 해결을 해가면서 작업을 진행하면 될듯 하다. 처음 다운로드 받은 샘플을 잘 검토 하고 적용하면 될듯 하다.
heroku가 무료라서 좋지만 그렇게 마음 놓고 쓰기는 힘들어 보인다. 그냥 개인 사이트로 활용하기는 문제는 없어 보인다.  속도도 느리다는 평가이고 시간 제한도 있고 … 다른 솔루션이 있는지 더 찾아 보기로 하자.

이미지 118

Node.js(6) 간단한 홈페이지 만들기 part2

최대한 간단하게라도 일일히 홈페이지를 만들려니 귀찮다. 이럴때는 템플릿을 이용하면 된다. 무료로 다운로드 가능한 템플릿을 검색해 보면 엄청 많다. 이 보다 더 잘 만들수가 없다.  원하는 템플릿을 찾았다면 다운로드 받자. 보통 index.html 파일과 CSS/JS/Image등으로 디렉토리 별로 잘 정리 되어 있다. 이걸 작동중이 Node.js서버에 그대로 올려 주면 된다.
이미지 111
문제는 index.html 파일이다. 확장자를 그대로 올려는 안된다. 지금 Node.js 에서 ejs 템플릿 엔진을 사용하고 있으니 확장자를 ejs로 변경해 줘야 한다.  그리고 index파일만은  views 디렉토리에 업로드 해줘야 한다. 나머지 css/fonts/images/js 디렉토리는 public 디렉토리 안에 그대로 업로드 해주면 된다. 이렇게 해서 아무런 문제가 없으면 정말 다행이다. 그런데 뭔가 문제가 발생되면 수정하기가 골치 아프다. 다른 사람이 만들어 놓은것이라서 찾기가 간단하지 않다. 행운을 빌어야지…
수많은 템플릿 중에서 하나를 다운로드 받아서 Node.js서버에 올렸다. 아무런 문제가 없다. 잘 동작한다. 이제 내용만 변경해 주거나 약간 손을 보면 된다. One page 홈페이지이다. 당장은 콘텐츠랄게 없기 때문에 페이지 하나면 다 해결된다.  index 페이지에 부하가 많이 걸릴수 있지만 이정도는 문제 없을것으로 생각된다.
이미지 112
중간 결과물 - 대충 이런 느낌이다. 쉽게는 텍스트나 이미지만 교체를 해주고 링크만 손을 보면 된다. 여기다 원하는 기능을 첨가 해 주면 될듯 하다. 메인 메뉴를 클릭하면 스크롤 되어 해당 영역으로 이동되는 방식이다.

사용한 템플릿은 아래 링크이다.
https://justfreetemplates.com/web-templates/view/3898-flame-onepage.html


Node.js(5) 간단한 홈페이지 만들기 part1

Node.js 를 이용해서 간단히 개인 홈페이지를 만들어 보기로 하자. 몇가지 새로운 개념을 동원해야 한다.

mkdir web2018 && cd web2018

새 디렉토리를 만들자.

npm init

패키지 관리를 위한 package.json 파일을 만들어 주자. 특별한 경우가 아니면 그냥 엔터로 진행하면 되겠다. package.json파일이 만들어진다.

{
   "name": "web2018",
   "version": "1.0.0",
   "description": "",
   "main": "app.js",
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1"
   },
   "author": "",
   "license": "ISC",
   "dependencies": {
     "ejs": "^2.6.1",
     "express": "^4.16.4"
   }
}

이제  프로젝트를 위해 필요한 패키지들을 설치하자.

npm install express –save

npm install ejs –save

설치후 package.json 내용을 보면 의존성에 추가 되어 있는 것을 확인 할 수 있다. Express는 앱개발 프레임워크이고 ejs는 템플릿 엔진이다. 이것말고 pug(jade)라는 것도 있던데 … 이건 뭐 다시 새로운 문법을 배워야 한다. 된장. 지금도 머리 아파 죽겠는데 새로운 체계를 배우라고? 그래서 기존의 html 문법을 그대로 사용할수 있는 ejs를 사용하기로 했다.  그렇게 복잡한 사이트를 만들것도 아니고 일단 ejs로 하자. 어느게 좋은지 그런건 아직 모르겠다.

app.js라는 파일은 생성하고 코드를 아래와 같이 작성하자.

var express = require('express');
var app = express();


app.get('/', function (req, res) {
   res.send('Hello World!');
});
app.listen(3000, function(){
     console.log('App Listening on port 3000');
});

저장 하고 실행해 보자.

node app.js

이제 웹브라우저에서 raspberrypi_ip:3000 으로 접속하면 Hello World라고 출력되는 것을 확인 할 수 있다. 이제 ejs 템플릿을 이용해서 만들어 보자. ejs는 앞서 언급했듯이 기존 HTML를 그대로 사용할 수 있다. 그래 이게 좋은거지. 여기에다 <% %>를 사용하여 서버의 데이터나 코드를 실행할 수 있게 된다. ejs를 사용하기 위해서 app.js에 설정을 해줘야 한다.

var express = require('express');
var app = express();

// app.set('views', './views');
app.set('view engine', 'ejs');//ejs 템플릿 엔진  연동

// route setting - 라우팅(routing)
app.get('/', function (req, res) {
   //res.send('Hello World!');
   res.render('index');//views디렉토리안에 있는 index.ejs 파일
});

app.listen(3000, function(){
     console.log('App Listening on port 3000');
});

코드에서 알수 있듯이 views라는 디렉토리를 만들어 주고 그 안에 html 문서를 넣어 주면 된다.  send 대신에 render라는 메소드를 사용하는 것도 유의하자. HTML문서의 확장자가 .html이 아니라 .ejs라고 해서 저장해야 한다.  샘플로 html문서는 아래와 같이 해주자.

<!DOCTYPE html>
<html>
<head>
     <meta charset="utf-8">
     <title>Ghost</title>
</head>
<body>
     <h1>Ghost</h1>
     <p>샘플 사이트입니다. 앞으로 계속 추가해 나가도록 하겠습니다.</p>
</body>
</html>

이렇게 저장해주고 다시 app.js를 실행하고 브라우저에서 접속해 보면 html 내용이 출력되는 것을 확인 할 수 있다. 이것이 기본적인 사용법이다.

app.js 재실행시 이미 포트를 사용중이라고 에러가 나면 다음과 같이 해주자.

ps –ef | grep app.js

pid번호를 확인하고 죽이면 된다.

kill –9 <pid_num>

이미지 107

프로젝트 전체의 파일 구조를 보면 아래와 같이 되어 있다.

이미지 110

<% %>의 사용법을 알아 보자. app.js로 부터 데이터를 전송 받아서 브라우저에 출력하는 것으로 만들어 보자. 지금까지는 get을 사용했지만 이번에는 post를 사용해야 한다. html은 다음과 같이 수정했다.

<!DOCTYPE html>
<html>
<head>
     <meta charset="utf-8">
     <title>Ghost</title>
     <link  rel="stylesheet" type="text/css" href="stylesheet">
</head>
<body>
     <h1>Ghost</h1>
     <p>샘플 사이트입니다. 앞으로 계속 추가해 나가도록 하겠습니다.</p>
     <h3><%= name %>님 반갑습니다.</h3>

    <div class="container">
       <fieldset>
         <form action="/" method="post">
           <input name="name" type="text" class="ghost-input" placeholder="Enter Your Name" required>
           <input type="submit" class="ghost-button" value="submit">
         </form>
       </fieldset>
     </div>

</body>
</html>

form의 내용을 post 로 넘긴다. app.js를 수정하자. 여기서 다시 필요한것이 있다.

npm install body-parser –save

설치를 했으면 app.js를 수정하기로 하자.

var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(express.static('public'));
app.use(bodyParser.urlencoded({extended : true}));
app.set('view engine', 'ejs');//ejs 템플릿 엔진  연동

// route setting - 라우팅(routing)
app.get('/', function (req, res) {
   //res.send('Hello World!');
   var data = req.body;
   res.render('index', {name: data});//views디렉토리안에 있는 index.ejs 파일
});

app.post('/', function (req, res) {
   var data = req.body.name;
   res.render('index', {name: data});
});


app.listen(3000, function(){
     console.log('App Listening on port 3000');
});

이미지 109

이름을 입력하고 submit 하면 입력된 이름을 출력해 준다. 지금까지 기본적인 흐름을 파악하기 위해 기초적인 사항들을 다루어 보았다. 이제 본격적으로 그럴싸한 홈페이지를 만들어 보기로 하자.



다음편에 계속 ….

일요일, 11월 11

Node.js(4) 안드로이드와 Socket.io로 통신하기

이번에는 Socket.io를 이용해서 안드로이드와 소켓통신을 해보기로 하자. 먼저 Node.js로 서버를 가동하자. 여기서 express라는 것을 이용할텐데 이 express는 Node.js에서 동작하는 웹 개발 프레임워크이다. 한마디로 편하게 웹서버를 가동하고 개발할 수있도록 해주는 것이니 이용하기로 하자. 편한길로 가야지. express(이것도 뭔가 복잡한데 다음에 알아 보자.)를 사용하기 위해서 먼저 설치를 해줘야 한다. 그리고 socket.io도 설치하자.

npm install express

npm install socket.io

이제 서버코드를 작성하자.

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
   res.sendfile('index.html');//default page
});

http.listen(3000, function(){
   console.log('listening on *:3000');
});

io.sockets.on('connection', function (socket){
   //원격에서 접속이 되면 기본 응답
   socket.emit('message_from_server', 'hello, world');

  //메세지가 들어 오면 응답
   socket.on('message_from_client', function (msg){
     console.log('message:', msg);
     /*받은 메세지를 되돌려 주자.
     아니면 받은 데이터를 이용 라즈베리파에서 뭐든 할 수 있다.
     */
     socket.emit('message_from_server', '"' +msg+ '" 라고하셨군요.');
   });

});

간단히 소켓으로 받은 데이터를 되돌려 전송하는 코드이다.  실행해 두자.

node server.js

이제 원격 자바스크리트로 클라이언트를 만들자.

이미지 103

텍스트를 입력하고 전송하면 서버에서 그 값을 되돌려 받아서 화면에 출력하게 된다. 라이브러리를 추가해 줘야 하는데 아래 사이트에서 복사해 넣자.

https://cdnjs.com/libraries/socket.io


<!DOCTYPE html>
<html>
<head>
     <meta charset="utf-8">
     <title>Socket.io example</title>
     <style type="text/css">
         body{
             text-align: center;
         }
         #response{
             color: red;
         }
     </style>
</head>
<script type="text/javascript" src="
https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.dev.js"></script>
<body>

    <h1>Socket.io example</h1>

    <form action="javascript:void(0);">
             <input type="text" id="inputMsg" required>
             <button onclick="sendsocket()">보내기</button>
     </form>

    <p>서버로부터 응답: </p>
     <div id="response"></div>

    <script type="text/javascript">
         var socket = io.connect("192.168.0.4:3000");
         var res = document.querySelector("#response");
         var msg = document.querySelector("#inputMsg");

        socket.on('message_from_server', function(data){
             console.log(data);
             res.innerHTML = "<p>"+data+"</p>";
         });

        function sendsocket(){
             socket.emit('message_from_client', inputMsg.value);
         }
     </script>

</body>
</html>


웹브라우저에서 접속해서 간단히 보내 보면 … 잘 된다. 끝! 이제 안드로이드앱에서 데이터를 보내 보자. 서버는 특별히 손댈 필요가 없으니 그대로 두자.

Screenshot_20181112-160446


마찬가지로 간단히 텍스트를 입력해서 전송하는 앱이다. 서버에서 보내온 응답 메세지를 화면에 출력해 준다. layout 파일은 생략하고 자바코드만 보자.

public class MainActivity extends AppCompatActivity {

Socket socket;
Button button;
EditText editText;
TextView textView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

try {
socket = IO.socket("http://192.168.0.4:3000");
}catch (Exception e) {
e.printStackTrace();
}

socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
@Override
public void call(Object... args) {
socket.emit("message_from_client", "Hi~ 나는 안드로이드야.");
}
}).on("message_from_server", new Emitter.Listener() {
@Override
public void call(final Object... args) {
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText(args[0].toString());
}
});
}
});
socket.connect();

editText = (EditText) findViewById(R.id.editText);
textView = (TextView) findViewById(R.id.result);
button = (Button) findViewById(R.id.button);

button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String msg = editText.getText().toString();
socket.emit("message_from_client", msg);
}
});
}
}

문제 없이 동작한다. 이렇게 해서 Node.js로 소켓통신을 위한 서버를 만들고 자바스크립트와 안드로이드에서 통신을 해보는 예제를 만들어 보았다.

Blogger Widget