jichoi / lms_front star
dajeong 08-12
240812 정다정 단어 입력 그림AI 프롬포트 구현
@434d1c186a0351189e11659584c6f5b90ffdd20c
 
client/resources/img/jumpingRabbit.gif (Binary) (added)
+++ client/resources/img/jumpingRabbit.gif
Binary file is not shown
 
client/views/component/TextToImage.vue (added)
+++ client/views/component/TextToImage.vue
@@ -0,0 +1,244 @@
+<template>
+    <div class="flex justify-center align-center" style="margin-top : 30px">
+        <div class="content title-box aibox">
+            <p class="title mt25 title-bg">모르는 단어를 물어봐~!</p>
+            <div class="propmt-container">
+                <div class="input-conatiner">
+                    <input v-model="word" @keyup.enter="startProgress(word)"/>
+                    <button @click="startProgress(word)"> <p> 생성하기 </p> </button>
+                </div>
+                <div class="progress-container">
+                    <div class="progress-bar" :style="{ width: progressWidth + '%' }">{{ Math.floor(progressWidth) }}%</div>
+                    
+                    <!-- 로딩 이미지 -->
+                    <div v-if="progressWidth < 100 && progressWidth > 1" class="loading-container">
+                        <img src="../../resources/img/jumpingRabbit.gif" alt="Loading" class="loading-gif"/>
+                        <p> 잠깐만 기다려봐~ </p>
+                    </div>
+
+                </div>
+                <div v-if="visibleWord" class="result-container">
+                    <img :src="imageSrc"/>
+                    <div class="word-container">
+                        <h2> {{ inputWord }}  </h2>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    
+</template>
+
+<script>
+import axios from 'axios';
+
+export default {
+    data() {
+        return {
+            progressWidth: 0,
+            inputWord : "",
+
+            // 하드 코딩 -> 수정 필요 : API
+            word : "",
+            imageSrc : "",
+            imageData: null, // 서버에서 받아온 이미지 데이터 저장
+
+            visibleWord : false,
+        };
+    },
+    mounted() {
+        
+    },
+    methods: {
+        // 상태 진행 바(progress bar)
+        startProgress(word) {
+            if (this.progressWidth == 100) {
+                this.resetProgress();
+            }
+
+            if (this.progressWidth > 0) return; // 이미 진행 중이면 중복 실행 방지
+
+            this.setWord(word);
+
+            const interval = 300; // 30ms
+            const totalDuration = 3000; // 총 시간 : 10초
+            const steps = totalDuration / interval;
+            const increment = 100 / steps;
+
+            const progressInterval = setInterval(() => {
+                this.progressWidth += increment;
+                if (this.progressWidth >= 100) {
+                    this.progressWidth = 100;
+                    clearInterval(progressInterval);
+                    this.visibleWord = true;
+
+                     // 진행이 완료된 후에 이미지 데이터 렌더링
+                    if (this.imageData) {
+                        this.imageSrc = this.imageUrl;
+                    }
+                }
+            }, interval);
+
+            this.getAiImage();
+        },
+        setWord(word) {
+            if (this.progressWidth > 0 && this.progressWidth < 100) return; // progressWidth가 0 또는 100이 아니면 실행 중지
+            this.inputWord = word;
+            this.visibleWord = false;
+        },
+        
+        resetProgress() {
+            this.progressWidth = 0;
+            this.visibleWord = false;
+            this.imageSrc = ""; // 이미지 URL 초기화
+            this.imageData = null; // 이미지 데이터 초기화
+        },
+
+        // 이미지 API
+        async getAiImage(){
+            const url = "http://takensoftai.iptime.org:20200/generate_json";
+            // console.log(`word : ${this.word}`);
+            try {
+                const response = await axios({
+                    url: url,
+                    method: "post",
+                    headers: {
+                        "Content-Type": "application/json; charset=UTF-8",
+                    },
+                    responseType: 'arraybuffer',
+                    data: {
+                        text: this.word
+                    },
+                });
+                
+                // console.log(`응답 : ${response}`);
+
+                // 바이너리 데이터 -> Blob으로 변환
+                const blob = new Blob([response.data], { type: 'image/png' });
+
+                // Blob에서 객체 URL 생성
+                const imageUrl = URL.createObjectURL(blob);
+
+                // 이미지 URL 설정
+                this.imageSrc = imageUrl;
+            } catch (err) {
+                console.log(err);
+            }
+        }
+    }
+}
+</script>
+
+<style>
+.propmt-container{
+    padding: 0px 50px 30px 50px;
+}
+/* 입력 컨테이너  */
+.input-conatiner{
+    display: flex;
+    align-items: center;
+    gap: 30px;
+    height: 50px;
+}
+.input-conatiner input{
+    width: 90%;
+    height: 100%;
+    padding: 10px 30px;
+    border: none;
+    border-radius: 10px;
+    box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;
+    outline: none;
+    font-size : 28px;
+}
+.input-conatiner button{
+    width: 15%;
+    height: 100%;
+    border: none;
+    border-radius: 10px;
+    cursor: pointer;
+    background-color: #ffba08;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+
+.input-conatiner button p{
+    font-size : 28px;
+}
+
+/* 진행 상태바 */
+.progress-container {
+    width: 100%;
+    background-color: #ffffff;
+    border-radius: 5px;
+    overflow: hidden;
+    margin-top: 20px;
+    display : flex;
+    flex-direction: column;
+    gap :30px;
+}
+
+.progress-bar {
+    height: 30px;
+    width: 0;
+    background-color: #4caf50;
+    text-align: center;
+    line-height: 30px;
+    color: white;
+    border : none;
+    border-radius: 5px;
+    transition: width 0.3s;
+    font-size : 20px;
+}
+
+/* 로딩 gif */
+.loading-container{
+    display : flex;
+    flex-direction: column;
+    align-items: center;
+    gap: 30px;
+    text-align: center;
+    margin-top : 30px;
+    padding-bottom : 40px;
+}
+.loading-gif{
+    width: 25%;
+    border-radius: 500px;
+}
+.loading-container p {
+    font-size : 25px;
+}
+
+/* 결과 container */
+.result-container{
+    margin-top: 30px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    gap: 30px;
+}
+.result-container img{
+    width : 30%;
+}
+.word-container{
+    width: 30%;
+    text-align: center;
+    padding: 20px 0px;
+    border: 3px solid #4caf50;
+    border-radius: 8px;
+    display: flex;
+    flex-direction: column;
+    gap: 15px;
+}
+.word-container h2 {
+    font-size : 28px;
+}
+
+.aibox{
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    height: auto;
+    padding: 30px 0px;
+}
+</style>
Add a comment
List