Commit d039dcbafbf0e160b175f7fea52a27ae7bb4cf44

Authored by shihongzhi
Committed by GitHub
1 parent a9a71231

feat: 添加快捷键+更完整的辅助线提示 (#148) add shortcuts for editor and more guidelines

* fix scrollbar show when h-line&v-line visible

* remove unused text code

* add hotkey to menu tools

* 除了left和top,其他四条线(midx,right,midy,bottom)也提示辅助线

* change width and height when point move situation

* rename argument and optimize some experience

* Fix typo

thanks @shihongzhi
front-end/h5/package.json
... ... @@ -23,6 +23,7 @@
23 23 "core-js": "^2.6.5",
24 24 "element-ui": "^2.13.0",
25 25 "font-awesome": "4.7.0",
  26 + "hotkeys-js": "^3.7.6",
26 27 "html2canvas": "^1.0.0-rc.3",
27 28 "proxy-agent": "^3.1.0",
28 29 "qrcode": "^1.4.1",
... ...
front-end/h5/src/components/core/editor/canvas/edit.js
... ... @@ -23,73 +23,97 @@ export default {
23 23 // TODO #!zh: 优化代码
24 24 // generate vertical line
25 25 drawVLine (newLeft) {
26   - // this.editingElement.commonStyle.left = newLeft
27   - this.setElementPosition({ left: newLeft })
28 26 this.vLines = [{ left: newLeft }]
29 27 },
  28 + clearVLine () {
  29 + this.vLines = []
  30 + },
30 31 // generate horizontal line
31 32 drawHLine (newTop) {
32   - // this.editingElement.commonStyle.top = newTop
33   - this.setElementPosition({ top: newTop })
34 33 this.hLines = [{ top: newTop }]
35 34 },
36   - calcX (newLeft) {
  35 + clearHLine () {
  36 + this.hLines = []
  37 + },
  38 + calcVHLine (isPointMove) {
37 39 const uuid = this.editingElement.uuid
38   - let xCoords = []
39   - this.elements.filter(e => e.uuid !== uuid).forEach(e => {
  40 + const referElements = this.elements.filter(e => e.uuid !== uuid)
  41 + let referElementsXCoords = []
  42 + let referElementsYCoords = []
  43 + referElements.forEach(e => {
40 44 const width = e.commonStyle.width
41 45 const left = e.commonStyle.left
42   - xCoords = [
43   - ...xCoords,
  46 + const height = e.commonStyle.height
  47 + const top = e.commonStyle.top
  48 +
  49 + referElementsXCoords = [
  50 + ...referElementsXCoords,
44 51 left,
45 52 left + (width / 2),
46 53 left + width
47 54 ]
48   - })
49   -
50   - xCoords.some(x => {
51   - if (Math.abs(newLeft - x) <= 5) {
52   - this.drawVLine(x)
53   - return true
54   - } else {
55   - this.vLines = []
56   - }
57   - })
58   - },
59   - calcY (newTop) {
60   - const uuid = this.editingElement.uuid
61   - let yCoords = []
62   - this.elements.filter(e => e.uuid !== uuid).forEach(e => {
63   - const height = e.commonStyle.height
64   - const top = e.commonStyle.top
65   - yCoords = [
66   - ...yCoords,
  55 + referElementsYCoords = [
  56 + ...referElementsYCoords,
67 57 top,
68 58 top + (height / 2),
69 59 top + height
70 60 ]
71 61 })
72 62  
73   - yCoords.some(y => {
74   - if (Math.abs(newTop - y) <= 5) {
75   - this.drawHLine(y)
76   - return true
77   - } else {
78   - this.hLines = []
79   - }
  63 + // e代表 editingElement
  64 + const eleft = this.editingElement.commonStyle.left
  65 + const etop = this.editingElement.commonStyle.top
  66 + const ewidth = this.editingElement.commonStyle.width
  67 + const eheight = this.editingElement.commonStyle.height
  68 + const exCoords = [eleft + ewidth, eleft + (ewidth / 2), eleft]
  69 + const eyCoords = [etop + eheight, etop + (eheight / 2), etop]
  70 + let hasVLine = false
  71 + let hasHLine = false
  72 + exCoords.forEach(eX => {
  73 + referElementsXCoords.forEach(referX => {
  74 + let offset = referX - eX
  75 + if (Math.abs(offset) <= 5) {
  76 + if (isPointMove) {
  77 + this.setElementPosition({ width: ewidth + offset })
  78 + } else {
  79 + this.setElementPosition({ left: eleft + offset })
  80 + }
  81 + this.drawVLine(referX)
  82 + hasVLine = true
  83 + }
  84 + })
  85 + })
  86 + eyCoords.forEach(eY => {
  87 + referElementsYCoords.forEach(referY => {
  88 + let offset = referY - eY
  89 + if (Math.abs(offset) <= 5) {
  90 + if (isPointMove) {
  91 + this.setElementPosition({ height: eheight + offset })
  92 + } else {
  93 + this.setElementPosition({ top: etop + offset })
  94 + }
  95 + this.drawHLine(referY)
  96 + hasHLine = true
  97 + }
  98 + })
80 99 })
  100 + if (!hasVLine) {
  101 + this.clearVLine()
  102 + }
  103 + if (!hasHLine) {
  104 + this.clearHLine()
  105 + }
81 106 },
82 107 /**
83 108 * #!zh: 在元素移动过程中,计算和生成辅助线
84 109 */
85 110 handleElementMove (pos) {
86 111 this.setElementPosition(pos)
87   - this.calcX(pos.left)
88   - this.calcY(pos.top)
  112 + this.calcVHLine(false)
89 113 },
90   - handlePointMove ({ top, left }) {
91   - this.calcX(left)
92   - this.calcY(top)
  114 + handlePointMove (pos) {
  115 + this.setElementPosition(pos)
  116 + this.calcVHLine(true)
93 117 },
94 118 bindContextMenu (e) {
95 119 // 优化右击菜单的显示,去除冗余的无效逻辑
... ... @@ -185,14 +209,16 @@ export default {
185 209 this.setEditingElement(element)
186 210 }}
187 211 // TODO 矩形四周的点叫什么?暂时叫 Point 吧
188   - handlePointMoveProp={pos => {
189   - this.setElementPosition(pos)
190   - }}
  212 + handlePointMoveProp={this.handlePointMove}
191 213 handleElementMoveProp={this.handleElementMove}
192 214 handleElementMouseUpProp={() => {
  215 + this.clearHLine()
  216 + this.clearVLine()
193 217 this.recordElementRect()
194 218 }}
195 219 handlePointMouseUpProp={() => {
  220 + this.clearHLine()
  221 + this.clearVLine()
196 222 this.recordElementRect()
197 223 }}
198 224 nativeOnContextmenu={e => {
... ...
front-end/h5/src/components/core/editor/index.js
1 1 import { mapState, mapActions } from 'vuex'
  2 +import hotkeys from 'hotkeys-js'
2 3 import undoRedoHistory from '../../../store/plugins/undo-redo/History'
3 4  
4 5 import '../styles/index.scss'
... ... @@ -44,58 +45,47 @@ import Feedback from &#39;@/components/common/feedback/index&#39;
44 45 const fixedTools = [
45 46 {
46 47 i18nTooltip: 'editor.fixedTool.undo',
47   - 'tooltip': '撤消', // TODO 支持快捷键
48   - 'text': '撤消',
49 48 'icon': 'mail-reply',
50   - 'action': () => undoRedoHistory.undo()
  49 + 'action': () => undoRedoHistory.undo(),
  50 + 'hotkey': 'ctrl&z,⌘&z'
51 51 },
52 52 {
53 53 i18nTooltip: 'editor.fixedTool.redo',
54   - 'tooltip': '恢复',
55   - 'text': '恢复',
56 54 'icon': 'mail-forward',
57   - 'action': () => undoRedoHistory.redo()
  55 + 'action': () => undoRedoHistory.redo(),
  56 + 'hotkey': 'ctrl&y,⌘&u'
58 57 },
59 58 {
60 59 i18nTooltip: 'editor.fixedTool.preview',
61   - 'tooltip': '刷新预览',
62   - 'text': '刷新预览',
63 60 'icon': 'eye',
64 61 'action': function () { this.previewVisible = true }
65 62 },
66 63 {
67 64 i18nTooltip: 'editor.fixedTool.copyCurrentPage',
68   - 'tooltip': '复制当前页',
69   - 'text': '复制当前页',
70 65 'icon': 'copy',
71   - 'action': function () { this.pageManager({ type: 'copy' }) }
  66 + 'action': function () { this.pageManager({ type: 'copy' }) },
  67 + 'hotkey': 'ctrl&c,⌘&c'
72 68 },
73 69 {
74 70 i18nTooltip: 'editor.fixedTool.importPSD',
75   - 'tooltip': '导入PSD',
76   - 'text': 'Ps',
77 71 'icon': '',
78 72 'action': '',
79 73 'disabled': true
80 74 },
81 75 {
82 76 i18nTooltip: 'editor.fixedTool.zoomOut',
83   - 'tooltip': '放大画布',
84   - 'text': '放大画布',
85 77 'icon': 'plus',
86   - 'action': function () { this.scaleRate += 0.25 }
  78 + 'action': function () { this.scaleRate += 0.25 },
  79 + 'hotkey': 'ctrl&=,⌘&='
87 80 },
88 81 {
89 82 i18nTooltip: 'editor.fixedTool.zoomIn',
90   - 'tooltip': '缩小画布',
91   - 'text': '缩小画布',
92 83 'icon': 'minus',
93   - 'action': function () { this.scaleRate -= 0.25 }
  84 + 'action': function () { this.scaleRate -= 0.25 },
  85 + 'hotkey': 'ctrl&-,⌘&-'
94 86 },
95 87 {
96 88 i18nTooltip: 'editor.fixedTool.issues',
97   - 'tooltip': 'issues',
98   - 'text': '常见问题',
99 89 'icon': 'question',
100 90 'action': function () { window.open('https://github.com/ly525/luban-h5/issues/110') }
101 91 }
... ... @@ -237,6 +227,15 @@ export default {
237 227 // }
238 228 }
239 229 },
  230 + mounted () {
  231 + fixedTools.map(tool => {
  232 + tool.hotkey && hotkeys(tool.hotkey, { splitKey: '&' }, (event, handler) => {
  233 + event.preventDefault()
  234 + event.stopPropagation()
  235 + tool.action && tool.action.call(this)
  236 + })
  237 + })
  238 + },
240 239 render (h) {
241 240 return (
242 241 <a-layout id="luban-editor-layout" style={{ height: '100vh' }}>
... ... @@ -340,10 +339,9 @@ export default {
340 339 <a-button-group style={{ display: 'flex', flexDirection: 'column' }}>
341 340 {
342 341 fixedTools.map(tool => (
343   - // <a-tooltip effect="dark" placement="left" title={tool.tooltip}>
344 342 <a-tooltip effect="dark" placement="left" title={this.$t(tool.i18nTooltip)}>
345 343 <a-button block class="transparent-bg" type="link" size="small" style={{ height: '40px', color: '#000' }} onClick={() => tool.action && tool.action.call(this) } disabled={!!tool.disabled}>
346   - { tool.icon ? <i class={['shortcut-icon', 'fa', `fa-${tool.icon}`]} aria-hidden='true'/> : tool.text }
  344 + { tool.icon ? <i class={['shortcut-icon', 'fa', `fa-${tool.icon}`]} aria-hidden='true'/> : this.$t(tool.i18nTooltip) }
347 345 </a-button>
348 346 { tool.icon === 'minus' && <div style={{ fontSize: '12px', textAlign: 'center' }}>{this.scaleRate * 100}%</div> }
349 347 </a-tooltip>
... ...
front-end/h5/yarn.lock
... ... @@ -5071,6 +5071,11 @@ hosted-git-info@^2.1.4:
5071 5071 resolved "https://registry.npm.taobao.org/hosted-git-info/download/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c"
5072 5072 integrity sha1-dZz88sTRVq3lmwst+r3cQqa5xww=
5073 5073  
  5074 +hotkeys-js@^3.7.6:
  5075 + version "3.7.6"
  5076 + resolved "https://registry.npm.taobao.org/hotkeys-js/download/hotkeys-js-3.7.6.tgz#b90ae3453a7be2f2b2bed6ee55cb96443944c77b"
  5077 + integrity sha1-uQrjRTp74vKyvtbuVcuWRDlEx3s=
  5078 +
5074 5079 hpack.js@^2.1.6:
5075 5080 version "2.1.6"
5076 5081 resolved "https://registry.npm.taobao.org/hpack.js/download/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2"
... ...