Vue.js로 회고 프레임 라벨을 실현하는 방법

개막사


HTML5 이전 시대에는 flame 태그가 존재했습니다.
웹 페이지에 여러 WEB 페이지를 위아래 좌우로 나란히 표시하는 레이블을 포함합니다.
2000년대 초반에는 프레임 라벨을 활용한 개인 사이트가 많았다고 생각해요.
(index.}에는 프레임 set을, 프레임 왼쪽에는 menu.>를, 오른쪽에는 top.}를 씁니다.)
HTML5가 등장한 후 프레임 라벨과 프레임 set 라벨이 함께 추천되지 않아 현재는 이 라벨을 사용하는 사이트가 거의 없다.
하지만 지금도 프레임 라벨을 좋아하는 사람들이 대안으로 Vue가 있다고 생각합니다.js로 프레임 표시와 유사한 것을 재현했다.
(실제 수요가 있는지 없는지는 아직 특별한 조사가 없으니 개의치 마세요.)

데모


vue-frame
(frame의 경계를 드래그하여 내용의 폭을 변경할 수 있음)

동작 이미지



대략적인 해설


프로비저닝



좌측


LeftFrame.vue
<template>
  <div class="left-frame" v-bind:style="{width:width + 'px'}">
    <div class="left-frame-content">ヒダリー</div>
    <div class="frame-border" @mousedown="$emit('startResize')"></div>
  </div>
</template>

<script>
export default {
  props: {
    width: Number
  }
};
</script>

<style scoped>
.left-frame {
  background-color: rgb(240, 240, 255);
  display: flex;
}

.left-frame-content {
  flex-grow: 1;
  padding-left: 10px;
}

.frame-border {
  width: 3px;
  background-color: rgb(208, 208, 208);
  border-left: solid 0.5px rgb(170, 170, 170);
  border-right: solid 0.5px black;
}

.frame-border:hover {
  cursor: col-resize;
}
</style>
  • 내용의 폭이 변할 수 있기 때문에 변수로 유지
  • 프레임의 경계선에서 드래그 이벤트를 가지기 위해
  • border의div요소(frame-border)와 비슷하게 배치한다.

    우측


    jRightFrame.vue
    <template>
      <div class="right-frame">ミギー</div>
    </template>
    
    <style scoped>
    .right-frame {
      background-color: white;
      flex-grow: 1;
      padding-left: 10px;
    }
    </style>
    
  • 화면 오른쪽에 표시할 항목만 구성
  • 본체


    Frame.vue
    <template>
      <div
        class="frame"
        v-bind:class="{dragged: isDragged}"
        @mousemove="resizeFrame"
        @mouseup="endResizeFrame">
        <left-frame v-bind:width="leftWidth" @startResize="startResize"></left-frame>
        <right-frame></right-frame>
      </div>
    </template>
    
    <script>
    import LeftFrame from "./LeftFrame.vue";
    import RightFrame from "./RightFrame.vue";
    
    const LEFT_FRAME_MIN_WIDTH = 45;
    const FRAME_ADJUSTED_SETTING = 2;
    
    export default {
      components: {
        LeftFrame,
        RightFrame
      },
      data() {
        return {
          isDragged: false,
          leftWidth: 200
        };
      },
      methods: {
        startResize() {
          this.isDragged = true;
        },
        resizeFrame(event) {
          if (event.buttons === 0) {
            this.endResizeFrame();
            return;
          }
          if (this.isDragged) {
            if (event.clientX + FRAME_ADJUSTED_SETTING < LEFT_FRAME_MIN_WIDTH) {
              this.leftWidth = LEFT_FRAME_MIN_WIDTH;
              return;
            }
            this.leftWidth = event.clientX + FRAME_ADJUSTED_SETTING;
          }
        },
        endResizeFrame() {
          this.isDragged = false;
        }
      }
    };
    </script>
    
    <style scoped>
    .frame {
      display: flex;
      flex-direction: row;
      height: 100vh;
    }
    
    .dragged * {
      cursor: col-resize;
    }
    </style>
    
    
  • 드래그 시작(startResize())LeftFrame에서 점화
  • mousemove 이벤트에서 마우스 위치 감시
  • event.buttons의 값으로 마우스의 눌린 상태를 판단합니다(=0이면 마우스를 누르지 않습니다)
  • 마우스 위치(event.clientX)에서 leftFrame의 폭을 변경(프레임의 스타일에 따라 적당히 조정)
  • 전체 소스 코드


    vue-frame(GitHub)

    참고 자료


    <frame> - HTML: HyperText Markup Language | MDN
    jQuery 아날로그 프레임 사용(하이 기능 버전)

    좋은 웹페이지 즐겨찾기