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 | import Shape from '../../support/shape' | 1 | import Shape from '../../support/shape' |
| 2 | export default { | 2 | export default { |
| 3 | props: ['elements', 'editingElement', 'handleClickElementProp', 'handleClickCanvasProp'], | 3 | props: ['elements', 'editingElement', 'handleClickElementProp', 'handleClickCanvasProp'], |
| 4 | + data: () => ({ | ||
| 5 | + vLines: [], | ||
| 6 | + hLines: [] | ||
| 7 | + }), | ||
| 4 | methods: { | 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 | * #!zh: renderCanvas 渲染中间画布 | 74 | * #!zh: renderCanvas 渲染中间画布 |
| 7 | * elements | 75 | * elements |
| @@ -39,12 +107,23 @@ export default { | @@ -39,12 +107,23 @@ export default { | ||
| 39 | // 这样,就不用等到鼠标抬起的时候,也就是 plugin 的 onClick 生效的时候,才给选中的元素添加边框等选中效果 | 107 | // 这样,就不用等到鼠标抬起的时候,也就是 plugin 的 onClick 生效的时候,才给选中的元素添加边框等选中效果 |
| 40 | this.handleClickElementProp(element) | 108 | this.handleClickElementProp(element) |
| 41 | }} | 109 | }} |
| 110 | + handleElementMoveProp={this.handleElementMove} | ||
| 42 | > | 111 | > |
| 43 | {h(element.name, data)} | 112 | {h(element.name, data)} |
| 44 | </Shape> | 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 | </div> | 127 | </div> |
| 49 | ) | 128 | ) |
| 50 | } | 129 | } |
front-end/h5/src/components/core/styles/index.scss
| @@ -43,6 +43,21 @@ | @@ -43,6 +43,21 @@ | ||
| 43 | z-index: 1; | 43 | z-index: 1; |
| 44 | border-radius: 50%; | 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,7 +13,7 @@ const directionKey = { | ||
| 13 | const points = ['lt', 'rt', 'lb', 'rb', 'l', 'r', 't', 'b'] | 13 | const points = ['lt', 'rt', 'lb', 'rb', 'l', 'r', 't', 'b'] |
| 14 | 14 | ||
| 15 | export default { | 15 | export default { |
| 16 | - props: ['element', 'active', 'editingElement', 'handleMousedownProp'], | 16 | + props: ['element', 'active', 'editingElement', 'handleMousedownProp', 'handleElementMoveProp'], |
| 17 | methods: { | 17 | methods: { |
| 18 | /** | 18 | /** |
| 19 | * 通过方位计算样式,主要是 top、left、鼠标样式 | 19 | * 通过方位计算样式,主要是 top、left、鼠标样式 |
| @@ -116,6 +116,7 @@ export default { | @@ -116,6 +116,7 @@ export default { | ||
| 116 | let currY = moveEvent.clientY | 116 | let currY = moveEvent.clientY |
| 117 | pos.top = currY - startY + startTop | 117 | pos.top = currY - startY + startTop |
| 118 | pos.left = currX - startX + startLeft | 118 | pos.left = currX - startX + startLeft |
| 119 | + this.handleElementMoveProp(pos) | ||
| 119 | } | 120 | } |
| 120 | 121 | ||
| 121 | let up = moveEvent => { | 122 | let up = moveEvent => { |