본문 바로가기

WebApp/WebApp

WebApp_동물상앱 - 웹어플 디자인(최종)

1.  By 조코딩 유튜브 채널[이미지] 개선

 (1). hover

 - By 조코딩 유튜브 채널 텍스트가 있는 a태그를 찾아서 개발자 도구의 Filter 우측 :hov를 클릭

  *:hober = 마우스를 올려놨을때 변함 

 - hover를 체크하면 아 래 a:hover{}가 생기는데 그 안의 속성color를 주황색으로 바꿔준다

 

(2). container, mt-숫자 

*mt-숫자 : margin-top을 적절히 주는 BootStrap class

*pt-숫자 : padding-top을 적절히 주는 BootStrap class

*container : 적절히 안쪽으로 넣어주는 BootStrap class

 - youtube-cover class에 container 와 mt-5 BootStrap class를 주어 위치와 마진를 조정해준다

 

 

(3). img 크기 축소

  - img태그를 찾아서 element.style{}안에 width속성을 추가하여 추가된 속성으로 인한 변화를 살핀다

  - width = 8%로 이미지 크기를 줄인다

 

 

 

(4). 위 3가지의 미리보기를 구현하기 위해 모두 나의 App 코드상에 직접 적용시킨다

 

 

 

2. 회색 박스 구현

* margin 0 auto : margin값 양 옆을 같은 비율로 하여 텍스트 및 이미지를 중앙으로 위치

* padding 10% 5% : padding 위아래% 양옆% 

 - container 추가

*height : 50vw;  = 1vw는 화면가로너비의 1%

 

 

3. 회색 박스 안 흰색점선 박스 구현

 

 - 반응형으로 할꺼기에 width, height px값은 지워준다

 - boder : dashed = 점선

 - hover 일때도 다듬어 준다

 

4. 이미지

 - 다운로드를 받아서 링크를 걸어 주고 index.html에 링크를 걸어준다

 

5. 얼굴사진을 올려놓고나 눌러서 업로드하세요! 텍스트

- 해당텍스트를 index.html에 붙여놓고 css작업을한다

 

 

****이런 작업들을 반복하고 수정하여 만들어낸 코드..****

 

○index.html

<!DOCTYPE html>
<html>
    <head>
        <!-- Required meta tags -->
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />

        <!-- Bootstrap CSS -->
        <link
            href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css"
            rel="stylesheet"
            integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1"
            crossorigin="anonymous"
        />

        <title>Hello, world!</title>
        <link rel="stylesheet" href="style.css" />
    </head>
    <body>
        <nav class="navbar navbar-expand-lg navbar-light nav-padding">
            <div class="container-fluid">
                <a class="navbar-brand" href="#">동물상테스트</a>
                <button
                    class="navbar-toggler"
                    type="button"
                    data-bs-toggle="collapse"
                    data-bs-target="#navbarNav"
                    aria-controls="navbarNav"
                    aria-expanded="false"
                    aria-label="Toggle navigation"
                >
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse" id="navbarNav">
                    <ul class="navbar-nav">
                        <li class="nav-item">
                            <a class="nav-link active" aria-current="page" href="#">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" href="#">Features</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" href="#">Pricing</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true"
                                >Disabled</a
                            >
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
        <section class="section">
            <h1 class="title">인공지능 동물상 테스트 (남자)</h1>
            <h2 class="subtitle">나는 어떤 동물과 닮았을까?</h2>
        </section>

        <section class="youtube">
            <div class="container mt-5 youtube-cover d-flex flex-row-reverse">
                <img src="./img/youtube-copy.jpg" alt="" class="youtube-icon" /><a
                    href=""
                    class="youtube-link"
                    >By 조코딩 유튜브 채널</a
                >
            </div>
        </section>

        <div>Teachable Machine Image Model</div>
        <button type="button" onclick="init()">Start</button>
        <button type="button" onclick="predict()">예측</button>
        <script
            class="jsbin"
            src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"
        ></script>
        <div class="container file-upload">
            <div class="image-upload-wrap">
                <input
                    class="file-upload-input"
                    type="file"
                    onchange="readURL(this);"
                    accept="image/*"
                />
                <div class="drag-text">
                    <img src="img/upload.svg" class="mt-4 upload" style="width: 30%;" />
                    <h3 class="pt-5 upload-text">얼굴 사진을 올려놓거나 눌러서 업로드하세요!</h3>
                </div>
            </div>
            <div class="file-upload-content">
                <img class="file-upload-image" id="face-image" src="#" alt="your image" />
                <div class="image-title-wrap">
                    <button type="button" onclick="removeUpload()" class="remove-image">
                        Remove <span class="image-title">Uploaded Image</span>
                    </button>
                </div>
            </div>
        </div>
        <div id="webcam-container"></div>
        <div id="label-container"></div>
        <!-- Optional JavaScript; choose one of the two! -->

        <!-- Option 1: Bootstrap Bundle with Popper -->
        <script
            src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js"
            integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW"
            crossorigin="anonymous"
        ></script>

        <!-- Option 2: Separate Popper and Bootstrap JS -->
        <!--
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js" integrity="sha384-q2kxQ16AaE6UbzuKqyBE9/u/KzioAlnx2maXQHiDX9d4/zp8Ok3f+M7DPm+Ib6IU" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.min.js" integrity="sha384-pQQkAEnwaBkjpqZ8RU1fF1AKtTcHJwFl3pblpTlHXybJjHpMYo79HY3hIi4NKxyj" crossorigin="anonymous"></script>
    -->

        <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.3.1/dist/tf.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/@teachablemachine/image@0.8/dist/teachablemachine-image.min.js"></script>
        <script>
            function readURL(input) {
                if (input.files && input.files[0]) {
                    var reader = new FileReader();

                    reader.onload = function (e) {
                        $('.image-upload-wrap').hide();

                        $('.file-upload-image').attr('src', e.target.result);
                        $('.file-upload-content').show();

                        $('.image-title').html(input.files[0].name);
                    };

                    reader.readAsDataURL(input.files[0]);
                } else {
                    removeUpload();
                }
            }

            function removeUpload() {
                $('.file-upload-input').replaceWith($('.file-upload-input').clone());
                $('.file-upload-content').hide();
                $('.image-upload-wrap').show();
            }
            $('.image-upload-wrap').bind('dragover', function () {
                $('.image-upload-wrap').addClass('image-dropping');
            });
            $('.image-upload-wrap').bind('dragleave', function () {
                $('.image-upload-wrap').removeClass('image-dropping');
            });
        </script>
        <script type="text/javascript">
            // More API functions here:
            // https://github.com/googlecreativelab/teachablemachine-community/tree/master/libraries/image

            // the link to your model provided by Teachable Machine export panel
            const URL = 'https://teachablemachine.withgoogle.com/models/MXDx7GlIj/';

            let model, webcam, labelContainer, maxPredictions;

            // Load the image model and setup the webcam
            async function init() {
                const modelURL = URL + 'model.json';
                const metadataURL = URL + 'metadata.json';

                // load the model and metadata
                // Refer to tmImage.loadFromFiles() in the API to support files from a file picker
                // or files from your local hard drive
                // Note: the pose library adds "tmImage" object to your window (window.tmImage)
                model = await tmImage.load(modelURL, metadataURL);
                maxPredictions = model.getTotalClasses();

                labelContainer = document.getElementById('label-container');
                for (let i = 0; i < maxPredictions; i++) {
                    // and class labels
                    labelContainer.appendChild(document.createElement('div'));
                }
            }

            // run the webcam image through the image model
            async function predict() {
                // predict can take in an image, video or canvas html element
                var image = document.getElementById('face-image');
                const prediction = await model.predict(image, false);
                for (let i = 0; i < maxPredictions; i++) {
                    const classPrediction =
                        prediction[i].className + ': ' + prediction[i].probability.toFixed(2);
                    labelContainer.childNodes[i].innerHTML = classPrediction;
                }
            }
        </script>
    </body>
    <!-- Copyright (c) 2020 by Aaron Vanston (https://codepen.io/aaronvanston/pen/yNYOXR)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -->
</html>

 

 

○style.css

body {
    font-family: sans-serif;
    background-color: #ffffff;
}
@media screen and (min-width:484px) and (max-width:600px){
    html{
        font-size: 11px;
    }
    .navbar-brand{
        font-size: 2rem;
    }
}
@media screen and (min-width:0px) and (max-width:483px){
    html{
        font-size: 8px;
    }
    .navbar-brand{
        font-size: 2rem;
    }
}

.file-upload-btn {
    width: 100%;
    margin: 0;
    color: #fff;
    background: #1fb264;
    border: none;
    padding: 10px;
    border-radius: 4px;
    border-bottom: 4px solid #15824b;
    transition: all 0.2s ease;
    outline: none;
    text-transform: uppercase;
    font-weight: 700;
}

.file-upload-btn:hover {
    background: #1aa059;
    color: #ffffff;
    transition: all 0.2s ease;
    cursor: pointer;
}

.file-upload-btn:active {
    border: 0;
    transition: all 0.2s ease;
}

.file-upload-content {
    display: none;
    text-align: center;
}

.file-upload-input {
    position: absolute;
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
    outline: none;
    opacity: 0;
    cursor: pointer;
}

.image-upload-wrap {
    margin-top: 20px;
    border: 4px dashed #1fb264;
    position: relative;
}

.image-dropping,
.image-upload-wrap:hover {
    background-color: #1fb264;
    border: 4px dashed #ffffff;
}

.image-title-wrap {
    padding: 0 15px 15px 15px;
    color: #222;
}

.drag-text {
    text-align: center;
}

.drag-text h3 {
    font-weight: 100;
    text-transform: uppercase;
    color: #15824b;
    padding: 60px 0;
}

.file-upload-image {
    max-height: 200px;
    max-width: 200px;
    margin: auto;
    padding: 20px;
}

.remove-image {
    width: 200px;
    margin: 0;
    color: #fff;
    background: #cd4535;
    border: none;
    padding: 10px;
    border-radius: 4px;
    border-bottom: 4px solid #b02818;
    transition: all 0.2s ease;
    outline: none;
    text-transform: uppercase;
    font-weight: 700;
}

.remove-image:hover {
    background: #c13b2a;
    color: #ffffff;
    transition: all 0.2s ease;
    cursor: pointer;
}

.remove-image:active {
    border: 0;
    transition: all 0.2s ease;
}
.nav-padding {
    padding-top: 2.1%;
    padding-left: 7.7%;
}
.navbar-light .navbar-brand{
  
  font-family: NanumSquareR;
  line-height: 1.68;
  text-align: left;
  color: #35465d;
}
.navbar-light .navbar-toggler {
    
    border-color: #ffffff;
}
.section{
    margin-top : 100px;
}
.title{
  font-family: NanumSquareR;
  
  line-height: 1.67;
  text-align: center;
  color: #35465d;
}
 .subtitle{
  font-family: NanumSquareR;
  
  line-height: 1.53;
  text-align: center;
  color: #35465d;
}
.youtube-link{
    font-family: NanumSquareR;
    font-size: 1.5rem;
    line-height: 1.71;
    text-align: center;
    color: #f73737;
}
.youtube-link:hover{
    
    color: #f73737;
}
.youtube-icon{
    width : 8%
}
.file-upload {
    background-color: #ffffff;
    /* width: 600px; */
    margin: 0 auto;
    padding: 20px;
    /* width: 914px; */
    height: 50vw;
    /* margin: 19px 83px 110px; */
    border-radius: 10px;
    border: solid 1.5px #f6f7fa;
    background-color: #f6f7fa;
    padding-right: 10px;
    padding-left: 10px;
}
.image-upload-wrap {
    /* margin-top: 20px; */
    /* border: 4px dashed #1fb264; */
    position: relative;
    /* padding: 99px 105px 94px 104px; */
    object-fit: contain;
    border-radius: 10px;
    border: dashed 1.5px #35465d;
    background-color: #ffffff;
    width: 50;
    width: 50%;
    margin: 0 auto;
}
.image-upload-wrap:hover {
        border: dashed 1.5px #35465d;
    background-color: #35465d;
}
.drag-text h3 {
    font-weight: 100;
    text-transform: uppercase;
    color: #15824b;
    padding: 60px 0;
    font-family: NanumSquareR;
    font-size: 1.2rem;
    line-height: 1.53;
    text-align: center;
    color: #35465d;
    width: 90%;
    margin: 0 auto;



/* .subtitle{
  font-family: NanumSquareR;
  
  line-height: 1.53;
  text-align: center;
  color: #35465d;
}
.youtube-link{
   
  font-family: NanumSquareR;
  line-height: 1.71;
  text-align: center;
  color: #f73737;
}
.youtube-copy {
  width: 60px;
  height: 51px;
  margin: 78px 83px 19px 14px;
  object-fit: contain;
  box-shadow: 10.1px 16.1px 20px 0 rgba(194, 194, 194, 0.9);
} */