SVG 및 Vue.js로 스프레드시트 작성

9613 단어 vuesvgjavascript


나는 handsontable 을 좋아하지만 처음부터 직접 작성하고 싶습니다.

데모



여기에서 시도해 보세요.
  • https://anydown-example-vue-spreadsheet-lite.netlify.com/

  • 레포:
  • https://github.com/anydown/vue-spreadsheet-lite

  • 구현 방법



    구현해야 할 것이 너무 많습니다. 나는 그들 모두를 할 수 없습니다.

    선택 UI





    현재 SVG Spec에는 z-index가 없기 때문에 UI와 콘텐츠 레이어를 두 개의 svg 요소로 분할하기로 결정했습니다.

    UI 레이어에는 경계 상자 또는 선택 사각형과 같은 시각적 요소가 있습니다. 그들은 항상 위에 있어야 합니다.

    내부 편집





    선택한 셀에 숨겨진 텍스트 필드가 있습니다. 처음에는 불투명도가 0으로 설정됩니다. 셀을 클릭하면 불투명도가 1로 변경됩니다.

    이 숨겨진 텍스트 필드는 항상 입력 방법을 처리하기 위해 키 입력을 캡처합니다. 이는 한자를 사용하는 사용자에게 중요합니다.

    SVG



    SVG는 복잡한 GUI를 구현하는 데 매우 유용합니다. DOM일 뿐이며 Vue의 ViewModel과 바인딩할 수 있습니다. 특히 저는 계산으로 SVG를 다루는 것을 좋아합니다.

    <template>
      <div class="grid" @mouseup="onMouseUpSvg()" @mousemove="headerResizeMove">
        <svg :width="positionLeft(data.length + 1) + 1" height=24>
          <g v-for="(col, ci) in headerObj" :key="ci" :transform="translateCol(ci)" @mousedown="startColumnSelect(ci)" @mousemove="changeColumnSelect(ci)" @mouseup="endColumnSelect">
            <rect class="col-header" x=0 y=0 :width="widthAt(ci)" :height="rowHeight">
            </rect>
            <text class="col-header__text" text-anchor="middle" :x="widthAt(ci) / 2" y=12 :width="widthAt(ci)" :height="rowHeight">{{col.name}}</text>
            <rect class="col-header__resize" :class="{'active': ci === headerResizeAt}" :x="widthAt(ci) - 5" :y=0 :width="5" :height="rowHeight" @mousedown.stop="headerResizeStart(ci)"></rect>
          </g>
        </svg>
    
        <div ref="wrapper" style="height: 400px; overflow: scroll; position:relative;">
          <svg :width="positionLeft(data.length + 1) + 1" :height="data.length * 24" >
            <g v-for="(row, ri) in data" :key="ri" :transform="translateRow(ri)">
              <g v-for="(col, ci) in row" :key="ci" :transform="translateCol(ci)" @mousedown="onMouseDownCell(ci, ri)" @mousemove="onMouseMoveCell(ci, ri)">
                <rect x=0 y=0 :width="widthAt(ci)" :height="rowHeight">
                </rect>
                <text x=2 y=12 :width="widthAt(ci)" :height="rowHeight">{{col}}</text>
              </g>
            </g>
            <rect :transform="selectionTransform" class="selection" x=0 y=0 :width="selectionSize.w" :height="selectionCount.h * rowHeight"></rect>
          </svg>
          <div class="editor__frame" :style="editorStyleObj">
            <input ref="hiddenInput"  @mousedown="onMouseDownCell(selection.c, selection.r)" class="editor__textarea" v-model="editingText" @blur="onBlur" :class="{'editor--visible': editing}" autofocus />
          </div>
        </div>
      </div>
    </template>
    

    이것은 단일 파일 템플릿이며 just 413 lines . 이를 구현하기 위해 canvas나 div를 사용하면 LOC가 두 배가 될 것이라고 생각합니다.

    빌리와 번들



    bili은 SFC를 배포하는 데 유용한 도구입니다.
    vue create로 이 프로젝트를 만들었지만 기본값.babelrc은 bili로 빌드하는 것을 방지하는 것 같습니다.

    this issue에 따르면 다음을 사용해야 합니다.

    bili --plugin vue --no-babel.babelrc
    

    업데이트 2018년 3월 14일

    이 문제는 오늘 해결되었습니다. 더 이상 필요하지 않습니다--no-babel.babelrc. 감사합니다EGOIST !

    그런 다음 이것을 npm에 게시할 수 있습니다.

    https://www.npmjs.com/package/@anydown/vue-spreadsheet-lite

    결론



    SVG로 GUI를 작성하는 것은 정말 재미있습니다!

    좋은 웹페이지 즐겨찾기