Commit c3059469f0d21376c85cbc4f6b50ee07c204df20
1 parent
fabad377
feat(guideline) en: support guideline, zh: 支持辅助线和吸附效果
Showing
3 changed files
with
96 additions
and
1 deletions
front-end/h5/src/components/core/editor/canvas/edit.js
| 1 | 1 | import Shape from '../../support/shape' |
| 2 | 2 | export default { |
| 3 | 3 | props: ['elements', 'editingElement', 'handleClickElementProp', 'handleClickCanvasProp'], |
| 4 | + data: () => ({ | |
| 5 | + vLines: [], | |
| 6 | + hLines: [] | |
| 7 | + }), | |
| 4 | 8 | methods: { |
| 9 | + // TODO #!zh: 优化代码 | |
| 10 | + // generate vertical line | |
| 11 | + drawVLine (newLeft) { | |
| 12 | + this.editingElement.commonStyle.left = newLeft | |
| 13 | + this.vLines = [{ left: newLeft }] | |
| 14 | + }, | |
| 15 | + // generate horizontal line | |
| 16 | + drawHLine (newTop) { | |
| 17 | + this.editingElement.commonStyle.top = newTop | |
| 18 | + this.hLines = [{ top: newTop }] | |
| 19 | + }, | |
| 20 | + calcX (newLeft) { | |
| 21 | + const uuid = this.editingElement.uuid | |
| 22 | + let xCoords = [] | |
| 23 | + this.elements.filter(e => e.uuid !== uuid).forEach(e => { | |
| 24 | + const width = e.commonStyle.width | |
| 25 | + const left = e.commonStyle.left | |
| 26 | + xCoords = [ | |
| 27 | + ...xCoords, | |
| 28 | + left, | |
| 29 | + left + (width / 2), | |
| 30 | + left + width | |
| 31 | + ] | |
| 32 | + }) | |
| 33 | + | |
| 34 | + xCoords.some(x => { | |
| 35 | + if (Math.abs(newLeft - x) <= 5) { | |
| 36 | + this.drawVLine(x) | |
| 37 | + return true | |
| 38 | + } else { | |
| 39 | + this.vLines = [] | |
| 40 | + } | |
| 41 | + }) | |
| 42 | + }, | |
| 43 | + calcY (newTop) { | |
| 44 | + const uuid = this.editingElement.uuid | |
| 45 | + let yCoords = [] | |
| 46 | + this.elements.filter(e => e.uuid !== uuid).forEach(e => { | |
| 47 | + const height = e.commonStyle.height | |
| 48 | + const top = e.commonStyle.top | |
| 49 | + yCoords = [ | |
| 50 | + ...yCoords, | |
| 51 | + top, | |
| 52 | + top + (height / 2), | |
| 53 | + top + height | |
| 54 | + ] | |
| 55 | + }) | |
| 56 | + | |
| 57 | + yCoords.some(y => { | |
| 58 | + if (Math.abs(newTop - y) <= 5) { | |
| 59 | + this.drawHLine(y) | |
| 60 | + return true | |
| 61 | + } else { | |
| 62 | + this.hLines = [] | |
| 63 | + } | |
| 64 | + }) | |
| 65 | + }, | |
| 66 | + /** | |
| 67 | + * #!zh: 在元素移动过程中,计算和生成辅助线 | |
| 68 | + */ | |
| 69 | + handleElementMove ({ top, left }) { | |
| 70 | + this.calcX(left) | |
| 71 | + this.calcY(top) | |
| 72 | + }, | |
| 5 | 73 | /** |
| 6 | 74 | * #!zh: renderCanvas 渲染中间画布 |
| 7 | 75 | * elements |
| ... | ... | @@ -39,12 +107,23 @@ export default { |
| 39 | 107 | // 这样,就不用等到鼠标抬起的时候,也就是 plugin 的 onClick 生效的时候,才给选中的元素添加边框等选中效果 |
| 40 | 108 | this.handleClickElementProp(element) |
| 41 | 109 | }} |
| 110 | + handleElementMoveProp={this.handleElementMove} | |
| 42 | 111 | > |
| 43 | 112 | {h(element.name, data)} |
| 44 | 113 | </Shape> |
| 45 | 114 | ) |
| 46 | 115 | }) |
| 47 | 116 | } |
| 117 | + { | |
| 118 | + this.vLines.map(line => ( | |
| 119 | + <div class="v-line" style={{ left: `${line.left}px` }}></div> | |
| 120 | + )) | |
| 121 | + } | |
| 122 | + { | |
| 123 | + this.hLines.map(line => ( | |
| 124 | + <div class="h-line" style={{ top: `${line.top}px` }}></div> | |
| 125 | + )) | |
| 126 | + } | |
| 48 | 127 | </div> |
| 49 | 128 | ) |
| 50 | 129 | } | ... | ... |
front-end/h5/src/components/core/styles/index.scss
| ... | ... | @@ -43,6 +43,21 @@ |
| 43 | 43 | z-index: 1; |
| 44 | 44 | border-radius: 50%; |
| 45 | 45 | } |
| 46 | + // TODO #!zh: 写一个辅助线基类: base-line | |
| 47 | + .v-line { | |
| 48 | + position: absolute; | |
| 49 | + height: 100vh; | |
| 50 | + width: 1px; | |
| 51 | + top: 0; | |
| 52 | + background-color: #94f5ff; | |
| 53 | + } | |
| 54 | + .h-line { | |
| 55 | + position: absolute; | |
| 56 | + height: 1px; | |
| 57 | + width: 100vh; | |
| 58 | + left: 0; | |
| 59 | + background-color: #94f5ff; | |
| 60 | + } | |
| 46 | 61 | } |
| 47 | 62 | } |
| 48 | 63 | ... | ... |
front-end/h5/src/components/core/support/shape.js
| ... | ... | @@ -13,7 +13,7 @@ const directionKey = { |
| 13 | 13 | const points = ['lt', 'rt', 'lb', 'rb', 'l', 'r', 't', 'b'] |
| 14 | 14 | |
| 15 | 15 | export default { |
| 16 | - props: ['element', 'active', 'editingElement', 'handleMousedownProp'], | |
| 16 | + props: ['element', 'active', 'editingElement', 'handleMousedownProp', 'handleElementMoveProp'], | |
| 17 | 17 | methods: { |
| 18 | 18 | /** |
| 19 | 19 | * 通过方位计算样式,主要是 top、left、鼠标样式 |
| ... | ... | @@ -116,6 +116,7 @@ export default { |
| 116 | 116 | let currY = moveEvent.clientY |
| 117 | 117 | pos.top = currY - startY + startTop |
| 118 | 118 | pos.left = currX - startX + startLeft |
| 119 | + this.handleElementMoveProp(pos) | |
| 119 | 120 | } |
| 120 | 121 | |
| 121 | 122 | let up = moveEvent => { | ... | ... |