Skip to content

hangul-typist

ManualTypist

문자(한글) 입력기

ts
import { typingMatrix } from '@jood/helpdesk-module/hangul-core';
import { ManualTypist } from '@jood/helpdesk-module/hangul-typist';

const source = `안녕하세요. Hello~ 😎
타이핑 애니메이션 입니다.`;

const manual = new ManualTypist();
manual.observe().subscribe((evt) => {
  console.log(evt);
});
manual.setSourceMatrix(typingMatrix(source));
manual.setTypingSpeed(40, 60);
manual.addDelayByEqual('\n', 120);
manual.addDelayByEqual('.', 100);
manual.start();
// manual.pause();
// manual.resume();
// manual.destroy();
0 / 0
입력 속도
~
vue
<template>
  <div class="typist-container">
    <div class="actions">
      <button class="action" @click="onStart">start</button>
      <button class="action" @click="onPause">pause</button>
      <button class="action" @click="onResume">resume</button>
    </div>
    <div class="output-area">
      <div class="count">{{ state.typingIndex }} / {{ state.typingTotal }}</div>
      <div class="output">{{ state.output }}</div>
    </div>
    <div class="input-area">
      <textarea class="input" v-model="source"></textarea>
    </div>
    <div class="options">
      <dl class="opt">
        <dt class="dt">입력 속도</dt>
        <dd class="dd">
          <input class="speed-put" type="number" :min="0" :max="state.max" v-model="state.min" /> ~
          <input class="speed-put" type="number" :min="state.min" :max="9000" v-model="state.max" />
        </dd>
      </dl>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { reactive, ref } from 'vue';
import { typingMatrix } from '@jood/helpdesk-module/hangul-core';
import { ManualTypist } from '@jood/helpdesk-module/hangul-typist';

const source = ref(`안녕하세요. Hello~ 😎
타이핑 애니메이션 입니다.`);

const state = reactive({
  output: '',
  typingIndex: 0,
  typingTotal: 0,
  min: 40,
  max: 60,
});

const manual = new ManualTypist();
// manual.addDelayByEqual('\n', 120);
// manual.addDelayByEqual('.', 100);

manual.observe().subscribe((evt) => {
  const { value, typingTotal, typingIndex } = evt;
  state.output = value;
  state.typingTotal = typingTotal;
  state.typingIndex = typingIndex;
});

const onStart = () => {
  manual.setSourceMatrix(typingMatrix(source.value));
  manual.setTypingSpeed(state.min, state.max);
  manual.start();
};

const onPause = () => {
  manual.pause();
};

const onResume = () => {
  manual.resume();
};
</script>

<style lang="scss" scoped>
.typist-container {
  margin: 0 auto;
  padding: 10px 10px 60px 10px;
  max-width: 760px;
}
.input-area {
  padding: 10px;
  box-sizing: border-box;
  .input {
    display: block;
    padding: 10px;
    width: 100%;
    min-height: 90px;
    font-size: 14px;
    color: #333;
    box-sizing: border-box;
    border: 1px solid #ddd;
  }
}
.output-area {
  padding: 10px;
  word-break: break-all;
  border-top: 3px double #e0e0e0;
  .count {
    font-size: 16px;
    font-weight: bold;
    text-align: right;
  }
  .output {
    font-size: 24px;
    font-weight: bold;
    line-height: 1.6;
    text-align: center;
    white-space: pre-line;
  }
}
.options {
  margin-top: -20px;
  display: flex;
  justify-content: flex-end;
  .opt {
    display: flex;
    align-items: center;
    padding: 2px 12px;
    .dt {
      padding-right: 10px;
      font-size: 14px;
      font-weight: bold;
    }
    .dd {
      display: flex;
      align-items: center;
    }
    .speed-put {
      display: block;
      padding: 0;
      height: 32px;
      width: 80px;
      text-align: center;
      border: 1px solid #ddd;
      appearance: none;
    }
  }
}
.actions {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px;
  .action {
    margin: 2px;
    background-color: #ffffff;
    border: 1px solid rgb(209, 213, 219);
    border-radius: 0.5rem;
    box-sizing: border-box;
    color: #111827;
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.25rem;
    padding: 0.75rem 1rem;
    text-align: center;
    text-decoration: none #d1d5db solid;
    text-decoration-thickness: auto;
    box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
    touch-action: manipulation;
    &:hover {
      background-color: rgb(249, 250, 251);
    }
    &:focus {
      outline: 2px solid transparent;
      outline-offset: 2px;
    }
    &:focus-visible {
      box-shadow: none;
    }
  }
}
</style>