1. [4장 실습용 문제] (4-1에서 이어지는 문제)

/******************************************************************************
 * 문제 4-2
 ******************************************************************************/
// 새로운 프로젝트와 Main.java 소스파일을 만든 후 [문제 4-1]에서 작성한 소스코드를 복사해서 삽입하라.
// [문제 4-2] 실행 결과를 참고하여 아래 코드를 작성하라.
// 1) 기존의 main() 함수 내에 있던 String[] name, int[] tall 변수를 Manager 클래스의 
//    static private 멤버로 옮겨라.
// 2) 아래 main() 함수에서 호출하는 Manager.makeManager(in) 문장을 참조하여 Manager 클래스에 
//    해당 함수를 구현하라. 기존 [문제 4-1]의 main 함수에 있던 manager 객체 
//    생성하는 코드들(while 문장 앞까지의 코드)를 makeManager(in) 함수로 옮기면 된다.
//    그리고 생성된 manager 객체를 리턴하면 된다.
// 3) Manager 객체는 항상 makeManager(in) 함수를 사용하여 생성하고 사용자가 직접 
//    new Manager(3) 형태로 호출하여 객체를 생성할 수 없게 하라.
// 4) 기존 main() 함수를 아래 main() 함수로 교체하라.
// 5) 메뉴 항목 "4.FindStudent2"를 선택할 경우 manager.findStudent(pname, tall)가 호출된다.
//    이 함수를 구현하라. 이 함수는 Manager가 관리하는 학생 중에 입력된 이름과 키가 
//    각각 pname과 tall과 동일한 학생을 찾아 출력한다. 찾지 못한 경우 적절한 에러 메시지를 출력한다.

 

public class Main
{
    public static void main(String[] args) 
    {
        Scanner in = new Scanner(System.in);
        Manager manager = Manager.makeManager(in);
        // manager = new Manager(3); 
        // 위 문장의 주석을 제거하면 Manager 생성자 접근할 수 없다는 에러가 발생하여야 한다.

        while(true) {
            System.out.print("\n0.Exit 1.DisplayAll 2.CalculateMean\n");
            System.out.print("3.FindStudent 4.FindStudent2 5.MakeManager >> ");
            int input = in.nextInt();
            if (input == 0)
            	break;
            switch (input) {
            case 1: manager.displayAll();       
                    break;
            case 2: manager.calculateMean();    
                    break;
            case 3: System.out.print("name? ");
                    String pname = in.next();
                    manager.findStudent(pname);
                    break;
            case 4: System.out.print("name, tall? ");
                    pname = in.next();
                    int tall = in.nextInt();
                    manager.findStudent(pname, tall);
                    break;
            case 5: manager = Manager.makeManager(in);
                    break;
            }
        }
        in.close();
    }
}

실행결과 예시

===============================================================================
==  [문제 4-2] 실행 결과
=============================================================================== 
input continuously 6 indices(index) of array: 0 1 2 3 4 5 // 사용자 입력: 0 ~ 5 숫자를 임의의 순서로 입력

0.Exit 1.DisplayAll 2.CalculateMean
3.FindStudent 4.FindStudent2 5.MakeManager >> 1
name	tall	difference
bob	172	  0.00
john	183	  0.00
alice	168	  0.00
nana	161	  0.00
tom	171	  0.00
sandy	172	  0.00

0.Exit 1.DisplayAll 2.CalculateMean
3.FindStudent 4.FindStudent2 5.MakeManager >> 2
tall mean: 171.17

name	tall	difference
bob	172	  0.83
john	183	 11.83
alice	168	 -3.17
nana	161	-10.17
tom	171	 -0.17
sandy	172	  0.83

0.Exit 1.DisplayAll 2.CalculateMean
3.FindStudent 4.FindStudent2 5.MakeManager >> 5
input continuously 6 indices(index) of array: 5 4 3 2 1 0 // 사용자 입력: 0 ~ 5 숫자를 임의의 순서로 입력

0.Exit 1.DisplayAll 2.CalculateMean
3.FindStudent 4.FindStudent2 5.MakeManager >> 1 // 새로운 manager 객체가 생성되었고, 배열에 들어간 객체 순서도 다름 
name	tall	difference
sandy	172	  0.00
tom	171	  0.00
nana	161	  0.00
alice	168	  0.00
john	183	  0.00
bob	172	  0.00

0.Exit 1.DisplayAll 2.CalculateMean
3.FindStudent 4.FindStudent2 5.MakeManager >> 2
tall mean: 171.17

name	tall	difference
sandy	172	  0.83
tom	171	 -0.17
nana	161	-10.17
alice	168	 -3.17
john	183	 11.83
bob	172	  0.83

0.Exit 1.DisplayAll 2.CalculateMean
3.FindStudent 4.FindStudent2 5.MakeManager >> 4
name, tall? nana 161
nana	161	-10.17

0.Exit 1.DisplayAll 2.CalculateMean
3.FindStudent 4.FindStudent2 5.MakeManager >> 4
name, tall? nana 160
nana 160: not found.

0.Exit 1.DisplayAll 2.CalculateMean
3.FindStudent 4.FindStudent2 5.MakeManager >> 4
name, tall? NANA 161
NANA 161: not found.

0.Exit 1.DisplayAll 2.CalculateMean
3.FindStudent 4.FindStudent2 5.MakeManager >> 4
name, tall? bob 171
bob 171: not found.

0.Exit 1.DisplayAll 2.CalculateMean
3.FindStudent 4.FindStudent2 5.MakeManager >> 4
name, tall? bob 172
bob	172	  0.83

0.Exit 1.DisplayAll 2.CalculateMean
3.FindStudent 4.FindStudent2 5.MakeManager >> 0

 

2. 정답코드

import java.util.Scanner;

class Student { 
    // 아래 name, tall, diff는 반드시 private로 하라.
    private String name;
    private int tall;
    private double diff;

    public Student(String name, int tall){
      this.name = name;
      this.tall = tall;
    }
  
    public void printStudent() {
       System.out.printf("%s\t%d\t%6.2f\n", name, tall, diff);
    }
    // 필요한 경우 멤버 값을 설정하고 구해오는 메소드(함수)를 만들어 멤버에 접근하라.
    public int getTall(){
      return this.tall;
    }

    public void setDiff(double diff){
      this.diff = diff;
    }
    public String getName(){
      return this.name;
    }
}

// 필요한 메소드(함수)를 구현하라.
class Manager {
  private static String[] name = {"bob", "john", "alice", "nana", "tom", "sandy"};
  private static int[] tall = {172, 183, 168, 161, 171, 172};
  private int curIndex;
  private Student[] students;
  
  private Manager() {}
  
  private Manager(int length){
    this.curIndex = 0;
    students = new Student[length];
  }
  
  public static Manager makeManager(Scanner in) {
     Manager manager = new Manager(Manager.name.length);
     System.out.print("input continuously 6 indices(index) of array: ");
      
      // 0 ~ 5 사이의 서로 다른 6개의 숫자(임의의 순서)들을 연속적으로 입력 받으면서
      // 학생 객체를 생성한 후 manager에 등록한다.
      for(int i = 0; i < Manager.name.length; i++)  {
          int j = in.nextInt();
          // manager 객체의 append 메소드를 실행하여 학생 객체 등록
          // append()는 manager내의 학생 객체 배열에 순서적으로 삽입한다.
          manager.append(new Student(name[j], tall[j]));
      }
      return manager;
  }

  public void displayAll(){
    System.out.printf("name\ttall\tdifference\n");
    for(int i=0; i<students.length; i++){
      this.students[i].printStudent();
    }
  }

  public void calculateMean(){
    double total = 0;
    for(int i=0; i<students.length; i++){ //total 구하기
      total += this.students[i].getTall();
    }
    total /= this.students.length;
    for(int i=0; i<students.length; i++){ //diff 구하기
      this.students[i].setDiff(this.students[i].getTall() - total);
    }
    
    System.out.printf("tall mean:%.2f\n\n",total);
    
    this.displayAll();
  }

  public void append(Student s){
    students[curIndex++] = s;
  }

  public void findStudent(String name){
    boolean findFlag = true;
    for(int i=0; i<students.length; i++){
      if(students[i].getName().equals(name)){
        findFlag = false;
        students[i].printStudent();
      }
    }
    if(findFlag){
      System.out.println(name+": not found.");
    }
  }
  
  public void findStudent(String name, int tall) {
     boolean findFlag = true;
       for(int i=0; i<students.length; i++){
         if(students[i].getName().equals(name) && students[i].getTall()==tall){
           findFlag = false;
           students[i].printStudent();
         }
       }
       if(findFlag){
         System.out.println(name+": not found.");
       }
  }
  
  
}

public class Main {

    public static void main(String[] args) 
    {
       Scanner in = new Scanner(System.in);
        Manager manager = Manager.makeManager(in);
        // manager = new Manager(3); 
        // 위 문장의 주석을 제거하면 Manager 생성자 접근할 수 없다는 에러가 발생하여야 한다.

        while(true) {
            System.out.print("\n0.Exit 1.DisplayAll 2.CalculateMean\n");
            System.out.print("3.FindStudent 4.FindStudent2 5.MakeManager >> ");
            int input = in.nextInt();
            if (input == 0)
               break;
            switch (input) {
            case 1: manager.displayAll();       
                    break;
            case 2: manager.calculateMean();    
                    break;
            case 3: System.out.print("name? ");
                    String pname = in.next();
                    manager.findStudent(pname);
                    break;
            case 4: System.out.print("name, tall? ");
                    pname = in.next();
                    int tall = in.nextInt();
                    manager.findStudent(pname, tall);
                    break;
            case 5: manager = Manager.makeManager(in);
                    break;
            }
        }
        in.close();

    }
}

 

3. 대충 풀이

1) 기존의 main() 함수 내에 있던 String[] name, int[] tall 변수를 Manager 클래스의 static private 멤버로 옮겨라. 

이건 너무 쉬우니까 패스...

2) 아래 main() 함수에서 호출하는 Manager.makeManager(in) 문장을 참조하여 Manager 클래스에 해당 함수를 구현하라. 기존 [문제 4-1]의 main 함수에 있던 manager 객체 생성하는 코드들(while 문장 앞까지의 코드)를 makeManager(in) 함수로 옮기면 된다. 그리고 생성된 manager 객체를 리턴하면 된다.

public static Manager makeManager(Scanner in) {
     Manager manager = new Manager(Manager.name.length);
     System.out.print("input continuously 6 indices(index) of array: ");
      
      // 0 ~ 5 사이의 서로 다른 6개의 숫자(임의의 순서)들을 연속적으로 입력 받으면서
      // 학생 객체를 생성한 후 manager에 등록한다.
      for(int i = 0; i < Manager.name.length; i++)  {
          int j = in.nextInt();
          // manager 객체의 append 메소드를 실행하여 학생 객체 등록
          // append()는 manager내의 학생 객체 배열에 순서적으로 삽입한다.
          manager.append(new Student(name[j], tall[j]));
      }
      return manager;
  }

2번 풀이

Manager.makeManager로 호출하였으므로 해당 메소드는 static 이어야하므로 static으로 선언해준다.

①  Manager 객체를 생성한다.

② 생성된 Manager 객체에 append 메소드를 통해 학생 정보를 넣어서 학생객체 배열을 관리할 수 있도록 해준다.

③ 설정이 끝난 Manager 객체를 반환해준다.

 

 

3) Manager 객체는 항상 makeManager(in) 함수를 사용하여 생성하고 사용자가 직접 new Manager(3) 형태로 호출하여 객체를 생성할 수 없게 하라.

3번 풀이

① 사용자가 직접 new 키워드를 사용하여 객체를 생성하지 못하도록 생성자를 private로 선언해준다.

 

4) 기존 main() 함수를 아래 main() 함수로 교체하라. (너무 쉬우니 패스)

5) 메뉴 항목 "4.FindStudent2"를 선택할 경우 manager.findStudent(pname, tall)가 호출된다.이 함수를 구현하라. 이 함수는 Manager가 관리하는 학생 중에 입력된 이름과 키가 각각 pname과 tall과 동일한 학생을 찾아 출력한다. 찾지 못한 경우 적절한 에러 메시지를 출력한다.

5번 풀이

기본적으로 기존 findStudent 메소드와 같다.

① 기존의 findStudent이다. 

② 새로 생성된 findStudent이다. Main 메소드를 보면 3번 또는 4번 모두 manager.findStudent를 호출하고 있다. 이는 바로 메소드 오버로딩을 이용하라는 의미이다. (같은 메소드 이름이지만 메소드 시그니처를 다르게 하여 서로 구분하는 것) 매개변수 갯수를 다르게 하여 메소드 오버라이딩을 구현하였다.

③ 새로 생성된 findStudent 로직 중 기존과 다른 점은 그저 키까지 같이 비교하는 부분이다. AND(&&) 조건을 이용하여 구현하면 끝~

'코딩이야기 > 연습문제' 카테고리의 다른 글

[라이브코딩 연습] JAVA 실습문제 4-1  (0) 2022.11.01
JAVA 실습문제 3-2  (0) 2022.10.28
JAVA 실습문제 3-1  (0) 2022.10.28
JAVA 실습문제 3-3  (0) 2022.10.25

1. 문제

/******************************************************************************
 * 문제 4-1
 ******************************************************************************/
// 새로운 프로젝트를 만든 후 새로운 클래스 Main를 만들어 Main.java 소스파일을 만들어라.
// 그런 후 아래 main 메소드를 복사해 소스파일에 넣어라.

 

// 클래스 정의, 생성자, 접근자, 객체배열 및 정적클래스와 관련된 문제이다.
// 아래 프로그램은 Student, Manager, Main으로 구성된다.
//
// 프로그램의 실행결과를 먼저 확인하라.
// 먼저 0 ~ 5 사이의 서로 다른 6개의 숫자를 임의의 순서로 연속적으로 입력 받는다.
// 이는 Manager에 추가할 학생들의 인덱스 순서이다.
// 그런 후 5명의 학생 객체를 생성하여 Manager에 추가한다.
// Manager는 5명의 학생 객체를 객체 배열에 저장하여 관리한다.
//
// Student, Manager 클래스의 멤버는 필요에 따라 추가해야 한다.
//
// 메뉴의 각 항목의 기능은 다음과 같으며, 이 순서로 구현하라.
// 1.DisplayAll: Manager가 관리하는 모든 학생 정보를 출력해야 한다.
//   Student의 printStudent()를 활용하라. 오타를 줄이기 위해 아래 문장도 사용하라.
       //System.out.printf("name\ttall\tdifference\n");
//
// 2.CalculateMean: Manager가 관리하는 모든 학생들의 키의 평균 값을 구해서 출력하고
//   이때 오타를 줄이기 위해 아래 문장을 사용하라.
        //System.out.printf("tall mean: %.2f\n\n", mean);
//   각 학생의 키와 평균과의 차이 값을 각 학생 객체의 diff 멤버에 저장하라. (키가 평균보다 작으면 음수 값이 된다.)
//   그리고 학생 전체를 다시 디스플레이하라.
//
// 3.FindStudent: Manager가 관리하는 학생 중에 입력된 이름과 동일한 이름을 가진 학생을 찾아 출력한다.
//                찾지 못한 경우 아래의 에러 메시지를 출력한다.
       //System.out.println(name+": not found.");
//
//=============================================================================

 

2. 전체코드

class Student { 
    // 아래 name, tall, diff는 반드시 private로 하라.
    private String name;
    private int tall;
    private double diff;

    public Student(String name, int tall){
      this.name = name;
      this.tall = tall;
    }
  
    public void printStudent() {
       System.out.printf("%s\t%d\t%6.2f\n", name, tall, diff);
    }
    // 필요한 경우 멤버 값을 설정하고 구해오는 메소드(함수)를 만들어 멤버에 접근하라.
    public int getTall(){
      return this.tall;
    }

    public void setDiff(double diff){
      this.diff = diff;
    }
    public String getName(){
      return this.name;
    }
}

// 필요한 메소드(함수)를 구현하라.
class Manager {
  private int curIndex;
  private Student[] students;
  
  public Manager(int length){
    this.curIndex = 0;
    students = new Student[length];
  }

  public void displayAll(){
    System.out.printf("name\ttall\tdifference\n");
    for(int i=0; i<students.length; i++){
      this.students[i].printStudent();
    }
  }

  public void calculateMean(){
    double total = 0;
    for(int i=0; i<students.length; i++){ //total 구하기
      total += this.students[i].getTall();
    }
    total /= this.students.length;
    for(int i=0; i<students.length; i++){ //diff 구하기
      this.students[i].setDiff(this.students[i].getTall() - total);
    }
    
    System.out.printf("tall mean:%.2f\n\n",total);
    
    this.displayAll();
  }

  public void append(Student s){
    students[curIndex++] = s;
  }

  public void findStudent(String name){
    boolean findFlag = true;
    for(int i=0; i<students.length; i++){
      if(students[i].getName().equals(name)){
        findFlag = false;
        students[i].printStudent();
      }
    }
    if(findFlag){
      System.out.println(name+": not found.");
    }
  }
}

public class Main {

    public static void main(String[] args) 
    {
        Scanner in = new Scanner(System.in);
        String[] name = {"bob", "john", "alice", "nana", "tom", "sandy"};
        int[] tall = {172, 183, 168, 161, 171, 172};

        // Manager 클래스의 객체변수 manager 선언 및 객체 생성
        // name.length는 manager내에 생성될 학생배열의 길이임
        Manager manager = new Manager(name.length);

        System.out.print("input continuously 6 indices(index) of array: ");
        
        // 0 ~ 5 사이의 서로 다른 6개의 숫자(임의의 순서)들을 연속적으로 입력 받으면서
        // 학생 객체를 생성한 후 manager에 등록한다.
        for(int i = 0; i < name.length; i++)  {
            int j = in.nextInt();
            // manager 객체의 append 메소드를 실행하여 학생 객체 등록
            // append()는 manager내의 학생 객체 배열에 순서적으로 삽입한다.
            manager.append(new Student(name[j], tall[j]));
        }

        while(true) {
            System.out.print("\n0.Exit 1.DisplayAll 2.CalculateMean 3.FindStudent >> ");
            int input = in.nextInt();
            if (input == 0)
               break;
            switch (input) {
            case 1: manager.displayAll();       
                    break;
            case 2: manager.calculateMean();    
                    break;
            case 3: System.out.print("name? ");
                    String pname = in.next();
                    manager.findStudent(pname);
                    break;
            }
        }
        in.close();
    }
}

 

객체 배열을 사용하는것이 포인트!

'코딩이야기 > 연습문제' 카테고리의 다른 글

[라이브코딩 연습] JAVA 실습문제 4-2  (0) 2022.11.01
JAVA 실습문제 3-2  (0) 2022.10.28
JAVA 실습문제 3-1  (0) 2022.10.28
JAVA 실습문제 3-3  (0) 2022.10.25

고정 레이아웃과 canvas에 이미지 불러오는 부분은 따로 정리해두었으니 참고!!

 

이 예제에는 드래그모드와 클릭모드 총 2가지 모드와 지우개가 구현되어있다.

드래그모드는 마우스 누름 → 드래그 → 마우스 놓음 순서로 이벤트를 잡아서 누른순간부터 놓는 순간의 영역만큼 모자이크를 하는 것이고, 클릭 모드는 미리 정해진 영역에 클릭을 하면 그 영역만 모자이크가 되는 원리이다.

 

예제 설명은 드래그모드 위주로!! (드래그 모드가 더 어려웠음.. ㅠㅠ)

 

공통사항

1. 캔버스는 모두 3개가 필요하다.

  • 원본이 그려질 캔버스(originCanvas)
  • 모자이크가 되어질 캔버스(mozaicCanvas)
  • 마우스의 움직임(드래그, 호버)에 따라 사각형을 그려줄 캔버스(hoverCanvas)

2. 지우개와 모자이크가 되는 방식은 모두 동일하다. (모자이크 되는 영역이 다를뿐이다.)

3. 이미지 불러오기와 고정 레이아웃은 다른 게시글에 설명이 있다.

 

드래그 모드의 핵심

드래그모드의 이벤트 순서

  1. 마우스 누름 (mousedown) → 시작좌표 획득
  2. 드래그 (mousemove)   → hover영역에 영역을 알려주는 빨간색 네모상자를 그려주는 역할
  3. 마우스 놓음 (mouseup) → 끝좌표 획득 및 width와 height를 구하여 모자이크 실행

좌표 확득
width, heigth 구하기 (초록색, 파란색)

래스터 정보와 getImageData

이미지는 수많은 픽셀로 구성되어 있다. 이미지를 구성하는 픽셀 정보를 래스터(Raster)라고 하며 이미지 표면에 어떤 그림이 그려져 있는지를 저장한다. 래스터 데이터를 직접 조작하면 그리기 메서드로는 불가능한 효과를 낼 수 있다.

 

좌표와 width,height를 구하는 이유는 래스터 정보를 얻을 수 있는 getImageData(x, y, w, h) 메소드의 파라미터이기 때문이다.

전체코드

[HTML 코드 + CSS코드]

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>테스트</title>
    <link rel="stylesheet" href="reset.css">
    <style>
        html,body{
            height: 100%;
        }
        .wrap{
            min-width: 800px; /*전체 사이트의 길이가 800px보다 작아지지 않도록 설정*/
            height: 100%;
        }
        .header{
            height: 100px;
            position: fixed;
            top: 0; left: 0; right: 0;
            background-color: aqua;
            z-index: 100;
        }
        .container{
            /* height를 %로 지정하기 위해서는 부모요소로 부터 높이값을 상속받아야한다. */
            min-height: 100%;
            margin: 0 auto;
            margin-top: -100px;
            padding-top: 200px;  /* padding으로 해야 border-box를 사용하여 원하는 레이아웃을 만들 수 있다. */
            box-sizing: border-box;
        }
        .content{
            margin: 0 auto;
            max-width: 1200px;
            background-color: aliceblue;
        }
        .footer{
            width: 100%;
            min-height: 100px;
            background-color: blue;
        }
        #canvas_area{
            position: relative;
            display: inline-block;
            width: 100%;
            height: 600px;
            overflow: auto;
        }
        #canvas_area canvas{
            position: absolute;
            left: 0;
        }
    </style>
</head>
<body>
    <div class="wrap">
        <div class="header">
            <div>
                <button id="mode_change">모드변경</button>
                <button id="eraser">지우개</button>
            </div>
            <div>
                <input type="file" id="img_loading"></button>
            </div>
            
        </div>
        <div class="container">
            <div class="content">
                <div id="canvas_area">
                    <canvas id="origin"></canvas> <!--원본-->
                    <canvas id="mosaic"></canvas> <!--모자이크 영역-->
                    <canvas id="hover"></canvas> <!--마우스영역-->
                </div>
            </div>
        </div>
        <div class="footer">footer</div>
    </div>
</body>
<script>
...
</script>
</html>

[JS코드]

<script>
    class Mozaic{

        constructor(){
            window.mode = 0; //드래그 모드

            this.$originCanvas = document.querySelector("#origin");
            this.$mosaiCanvasc = document.querySelector("#mosaic");
            this.$hoverCanvas = document.querySelector("#hover");

            this.$imgLoading = document.querySelector("#img_loading");
            this.$eraser = document.querySelector("#eraser");
            this.$modeChange = document.querySelector("#mode_change");
            
            this.originCtx = this.$originCanvas.getContext('2d');
            this.mosaicCtx = this.$mosaiCanvasc.getContext('2d');
            this.hoverCtx = this.$hoverCanvas.getContext('2d');
            
            this.eventBinding();
            this.init();
        }

        //초기화
        init(mode=0){
            window.isErase = false;
            window.isDrag = false;
            window.sx=0, window.ex=0;
            window.sy=0, window.ey=0;
            this.hoverCtx.clearRect(0,0,this.$hoverCanvas.width, this.$hoverCanvas.height); //그려진 호버 영역 지우기
            if(mode===1){ //클릭모드 초기화 
                //모자이크 영역 초기화
                window.mozXSize = 15;
                window.mozYSize = 15;
            }
        }

        eventBinding(){
            this.$imgLoading.addEventListener('change',this.loadImg.bind(this));
            //드래그 ↔ 클릭 모드 변경
            this.$modeChange.addEventListener('click',()=>{
                window.mode = Number(!window.mode); //모드 체인지 (0:드래그[기본], 1:클릭)
                this.isErase = false; //지우개 선택되었을 시 지우개 해제
                this.init(window.mode);
                console.log('현재 모드 : ', window.mode);
            });
            //지우개 클릭 : 지우개 모드 활성화
            this.$eraser.addEventListener('click',()=>{
                window.isErase = true;
            });
            
            this.$hoverCanvas.addEventListener('mousedown',(e)=>this.hoverCanvasMouseDown.call(this,e));
            this.$hoverCanvas.addEventListener('mousemove',(e)=>this.hoverCanvasMouseMove.call(this,e));
            this.$hoverCanvas.addEventListener('mouseup',(e)=>this.hoverCanvasMouseUp.call(this,e));
            this.$hoverCanvas.addEventListener('mouseout',(e)=>this.hoverCanvasMouseOut.call(this,e));
            this.$hoverCanvas.addEventListener('click',(e)=>this.hoverCanvasMouseClick.call(this,e));
        }
        
        //호버영역 마우스 벗어났을 때 핸들링
        hoverCanvasMouseOut(e){

        }

        //호버영역 마우스 드래그 시작 (드래그 모드)
        hoverCanvasMouseDown(e){
            if(window.mode===0){ //드래그 모드인지 확인
                window.isDrag = true;
                window.sx = e.layerX;
                window.sy = e.layerY;
                this.hoverCtx.strokeRect(sx,sy,0,0);
            }
        }
        
        //호버영역 마우스 클릭(클릭모드)
        hoverCanvasMouseClick(e){
            if(window.mode === 1){
                //좌표가져오기
                window.ex = Math.max(0, e.layerX);
                window.ey = Math.max(0, e.layerY);
                const imgData = this.originCtx.getImageData(window.ex,window.ey,window.mozXSize,window.mozYSize);
                this.doMosaic(imgData,ex,ey);
            }
        }

        //호버영역 마우스 드래그 끝 (드래그 모드)
        hoverCanvasMouseUp(e){
            if(window.mode === 0){ //드래그 모드 
                isDrag = false; //드래그끝을 알린다.
                this.hoverCtx.clearRect(0,0,this.$hoverCanvas.width, this.$hoverCanvas.height); //표시된 드래그 영역 삭제

                window.ex = e.layerX;
                window.ey = e.layerY;

                const startX = Math.min(window.sx, window.ex);
                const startY = Math.min(window.sy, window.ey);
                const endX = Math.max(window.sx,window.ex);
                const endY = Math.max(window.sy,window.ey);

                const imgData = this.originCtx.getImageData(startX,startY, endX - startX, endY - startY);
                this.doMosaic(imgData,startX,startY);
            }
        }

        //호버영역 마우스 이동 (드래그모드, 클릭 모드)
        hoverCanvasMouseMove(e){
            if(window.mode === 0){ //드래그 모드 확인
                if(isDrag){ //드래그 중일때만 동작
                    this.hoverCtx.clearRect(0,0,e.target.width, e.target.height);
                    this.hoverCtx.strokeStyle = "#FF0000"; //빨간색으로 드래그 영역 잡히게 설정
                    this.hoverCtx.strokeRect(sx,sy, e.layerX - sx, e.layerY - sy);
                }
            }else if(window.mode === 1){ //클릭 모드
                //좌표 가져오기
                const x = Math.max(e.layerX,0);
                const y = Math.max(e.layerY,0);
                //기존 호버영역 그려진 것들 삭제
                this.hoverCtx.clearRect(0,0,e.target.width, e.target.height);
                this.hoverCtx.strokeStyle = 'black';
                this.hoverCtx.strokeWidth = 30;
                this.hoverCtx.fillStyle = 'rgba(0,255,255,0.5)';
                this.hoverCtx.fillRect(x,y,window.mozXSize, window.mozYSize);
            }
        }

        //이미지 불러오기
        loadImg(){
            const file = this.$imgLoading.files[0];
            console.log(file);
            if(!file.type.match(/image.*/)){
                alert('이미지 파일이 아닙니다.');
                return;
            }
            
            const reader = new FileReader();
            reader.onload = (e)=>{
                const img = new Image();
                img.onload = ()=>{
                    this.$originCanvas.width = img.width;
                    this.$originCanvas.height = img.height;
                    
                    this.$mosaiCanvasc.width = img.width;
                    this.$mosaiCanvasc.height = img.height;

                    this.$hoverCanvas.width = img.width;
                    this.$hoverCanvas.height = img.height;

                    this.originCtx.drawImage(img,1,1);
                    this.mosaicCtx.drawImage(img,1,1);
                }
                img.src = e.target.result;
            }
            reader.readAsDataURL(file);
        }

    }
    new Mozaic();
</script>

reset.css
0.00MB

reset.css를 다운로드 받아서 같은 경로에 놔두면 된다.

 

[결과물]

drag 모드

 

클릭모드

 

참고사이트

http://www.soen.kr/html5/html3/3-2-2.htm

 

HTML5 매뉴얼

3-2-2.이미지 데이터 이미지는 수많은 픽셀로 구성되어 있다. 이미지를 구성하는 픽셀 정보를 래스터(Raster)라고 하며 이미지 표면에 어떤 그림이 그려져 있는지를 저장한다. 래스터 데이터를 직

www.soen.kr

 

+ Recent posts