반응형

 

https://github.com/huinalam/mole-virtual-keyboard 

 

GitHub - huinalam/mole-virtual-keyboard: 한글 입력이 가능한 웹 전용 가상 키보드입니다.

한글 입력이 가능한 웹 전용 가상 키보드입니다. Contribute to huinalam/mole-virtual-keyboard development by creating an account on GitHub.

github.com

해당 소스를 참고하여 Vue 버전으로 만들었습니다.

 

CustomKeyboard.vue (가상키보드 컴포넌트)

<template>
    <div ref="keyboardZone" class="keyboard-container">
        <div v-for="(rows, index) in form[nowLang]" :key="index" class="keyboard-row">
            <button v-for="(key, keyIndex) in rows" :key="keyIndex" class="keyboard-key" @click="handleKeyClick(key)">
                {{ key }}
            </button>
        </div>
    </div>
</template>

<script>
    import Hangul from 'hangul-js'

    export default {
        props: {
            inputValue: String,
            onClick: Function,
            onESC: Function,
            onEnter: Function
        },
        data() {
            return {
                nowLang: 'koNormal',
                charlist: [],
                form: {
                    koNormal: [
                        ['뒤로', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'backspace'],
                        ['ㅂ', 'ㅈ', 'ㄷ', 'ㄱ', 'ㅅ', 'ㅛ', 'ㅕ', 'ㅑ', 'ㅐ', 'ㅔ'],
                        ['ㅁ', 'ㄴ', 'ㅇ', 'ㄹ', 'ㅎ', 'ㅗ', 'ㅓ', 'ㅏ', 'ㅣ', 'enter'],
                        ['shift', 'ㅋ', 'ㅌ', 'ㅊ', 'ㅍ', 'ㅠ', 'ㅜ', 'ㅡ', '한/영'],
                        ['space']
                    ],
                    koShift: [
                        ['뒤로', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', 'backspace'],
                        ['ㅃ', 'ㅉ', 'ㄸ', 'ㄲ', 'ㅆ', 'ㅛ', 'ㅕ', 'ㅑ', 'ㅒ', 'ㅖ'],
                        ['ㅁ', 'ㄴ', 'ㅇ', 'ㄹ', 'ㅎ', 'ㅗ', 'ㅓ', 'ㅏ', 'ㅣ', 'enter'],
                        ['shift', 'ㅋ', 'ㅌ', 'ㅊ', 'ㅍ', 'ㅠ', 'ㅜ', 'ㅡ', '한/영'],
                        ['space']
                    ],
                    enNormal: [
                        ['뒤로', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'backspace'],
                        ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'],
                        ['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'enter'],
                        ['shift', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '한/영'],
                        ['space']
                    ],
                    enShift: [
                        ['뒤로', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', 'backspace'],
                        ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
                        ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'enter'],
                        ['shift', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '한/영'],
                        ['space']
                    ]
                }
            }
        },
        methods: {
            handleKeyClick(key) {
                if (key === '뒤로') {
                    this.onESC && this.onESC()
                } else if (key === 'enter') {
                    this.onEnter && this.onEnter(this.getText())
                } else if (key === '한/영') {
                    this.toggleLanguage()
                } else if (key === 'shift') {
                    this.toggleShift()
                } else if (key === 'backspace') {
                    this.charlist.pop()
                } else if (key === 'space') {
                    this.charlist.push(' ')
                } else {
                    this.charlist.push(key)
                }

                this.$emit('update:inputValue', this.getText())
                this.onClick && this.onClick(this.getText())
            },
            getText() {
                return Hangul.assemble(this.charlist)
            },
            toggleLanguage() {
                if (this.nowLang === 'koNormal') this.nowLang = 'enNormal'
                else if (this.nowLang === 'enNormal') this.nowLang = 'koNormal'
                else if (this.nowLang === 'koShift') this.nowLang = 'enShift'
                else if (this.nowLang === 'enShift') this.nowLang = 'koShift'
            },
            toggleShift() {
                if (this.nowLang === 'koNormal') this.nowLang = 'koShift'
                else if (this.nowLang === 'enNormal') this.nowLang = 'enShift'
                else if (this.nowLang === 'koShift') this.nowLang = 'koNormal'
                else if (this.nowLang === 'enShift') this.nowLang = 'enNormal'
            }
        }
    }
</script>

<style scoped>
    .keyboard-container {
        position: absolute;
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction: column;
        align-items: center;
        font-size: 25px;
        background: #f5f5f5;
        padding: 10px;
        border-radius: 10px;
    }

    .keyboard-row {
        display: flex;
        width: 100%;
        justify-content: center;
        margin-bottom: 5px;
    }

    .keyboard-key {
        padding: 10px 15px;
        font-size: 20px;
        margin: 2px;
        border: 1px solid #ccc;
        background: white;
        cursor: pointer;
        border-radius: 5px;
    }

    .keyboard-key:active {
        background: #ddd;
    }
</style>

 

부모 컴포넌트

<template>
	<div>
		<custom-keyboard v-model="name" :onClick="onClick" :onESC="onESC" :onEnter="onEnter" />
	</div>
</template>

<script>
    import CustomKeyboard from '@/components/CustomKeyboard.vue'

    export default {
        name: 'keyBoardParent',        
        components: { 
            CustomKeyboard, 
        },
        data() {
            return {
                name: null,
            }
        },
        methods: {
            onClick(val) {
                this.name = val;
            },
            onESC() {
                console.log("뒤로가기");
            },
            onEnter(val) {
                console.log("엔터 입력됨:", val);
            }
        },
        watch:{
        },
        mounted() {            
        }
    }
</script>

 

반응형

모바일에서 Input 박스 클릭 시 가상키보드가 무조건적으로 뜨는데 foucs를 주면 뜨지않게 하기 위한 HTML 태그입니다.

 

Input 박스에 inputmode="none" 를 사용하면 가상 키보드가 뜨지 않습니다.

 

단, 계속 뜨지 않기 떄문에 복사 붙혀넣기 할때만 사용 하시는게 좋습니다.

+ Recent posts