Commit 9e44e40af1a7005c68b3de8e10b06ca597454e5c
1 parent
42c972ba
feat: support copy plugin on canvas
Showing
4 changed files
with
99 additions
and
21 deletions
front-end/h5/src/components/core/editor/canvas/edit.js
| 1 | import { mapState, mapActions } from 'vuex' | 1 | import { mapState, mapActions } from 'vuex' |
| 2 | import Shape from '../../support/shape' | 2 | import Shape from '../../support/shape' |
| 3 | 3 | ||
| 4 | +const contextmenuOptions = [ | ||
| 5 | + { | ||
| 6 | + label: '复制', | ||
| 7 | + value: 'copy' | ||
| 8 | + }, | ||
| 9 | + { | ||
| 10 | + label: '删除', | ||
| 11 | + value: 'delete' | ||
| 12 | + }, | ||
| 13 | + { | ||
| 14 | + label: '置顶', | ||
| 15 | + value: 'bring2Top' | ||
| 16 | + }, | ||
| 17 | + { | ||
| 18 | + label: '置底', | ||
| 19 | + value: 'bring2Bottom' | ||
| 20 | + }, | ||
| 21 | + { | ||
| 22 | + label: '上移', | ||
| 23 | + value: 'addZindex' | ||
| 24 | + }, | ||
| 25 | + { | ||
| 26 | + label: '下移', | ||
| 27 | + value: 'minusZindex' | ||
| 28 | + } | ||
| 29 | +] | ||
| 30 | + | ||
| 4 | export default { | 31 | export default { |
| 5 | props: ['elements', 'handleClickElementProp', 'handleClickCanvasProp'], | 32 | props: ['elements', 'handleClickElementProp', 'handleClickCanvasProp'], |
| 6 | data: () => ({ | 33 | data: () => ({ |
| @@ -17,7 +44,8 @@ export default { | @@ -17,7 +44,8 @@ export default { | ||
| 17 | ...mapActions('element', [ | 44 | ...mapActions('element', [ |
| 18 | 'setEditingElement', // -> this.foo() | 45 | 'setEditingElement', // -> this.foo() |
| 19 | 'setElementPosition', // -> this.foo() | 46 | 'setElementPosition', // -> this.foo() |
| 20 | - 'setElementShape' // -> this.foo() | 47 | + 'setElementShape', // -> this.foo() |
| 48 | + 'elementManager' | ||
| 21 | ]), | 49 | ]), |
| 22 | // TODO #!zh: 优化代码 | 50 | // TODO #!zh: 优化代码 |
| 23 | // generate vertical line | 51 | // generate vertical line |
| @@ -187,6 +215,9 @@ export default { | @@ -187,6 +215,9 @@ export default { | ||
| 187 | { | 215 | { |
| 188 | this.contextmenuPos.length | 216 | this.contextmenuPos.length |
| 189 | ? <a-menu | 217 | ? <a-menu |
| 218 | + onSelect={({ item, key, selectedKeys }) => { | ||
| 219 | + this.elementManager({ type: key }) | ||
| 220 | + }} | ||
| 190 | style={{ | 221 | style={{ |
| 191 | left: this.contextmenuPos[0] + 'px', | 222 | left: this.contextmenuPos[0] + 'px', |
| 192 | top: this.contextmenuPos[1] + 'px', | 223 | top: this.contextmenuPos[1] + 'px', |
| @@ -195,12 +226,7 @@ export default { | @@ -195,12 +226,7 @@ export default { | ||
| 195 | zIndex: 999 | 226 | zIndex: 999 |
| 196 | }} | 227 | }} |
| 197 | > | 228 | > |
| 198 | - <a-menu-item data-command='copyEditingElement'>复制</a-menu-item> | ||
| 199 | - <a-menu-item data-command="deleteEditingElement">删除</a-menu-item> | ||
| 200 | - <a-menu-item data-command="bringLayer2Front">置顶</a-menu-item> | ||
| 201 | - <a-menu-item data-command="bringLayer2End">置底</a-menu-item> | ||
| 202 | - <a-menu-item data-command="addLayerZindex">上移</a-menu-item> | ||
| 203 | - <a-menu-item data-command="subtractLayerZindex">下移</a-menu-item> | 229 | + { contextmenuOptions.map(option => <a-menu-item key={option.value} data-command={option.value}>{option.label}</a-menu-item>) } |
| 204 | </a-menu> | 230 | </a-menu> |
| 205 | : null | 231 | : null |
| 206 | } | 232 | } |
front-end/h5/src/components/core/editor/index.js
| 1 | import Vue from 'vue' | 1 | import Vue from 'vue' |
| 2 | -import Element from '../models/element' | 2 | +import { mapState, mapActions } from 'vuex' |
| 3 | +// import Element from '../models/element' | ||
| 4 | + | ||
| 3 | import '../styles/index.scss' | 5 | import '../styles/index.scss' |
| 4 | 6 | ||
| 5 | import RenderEditCanvas from './canvas/edit' | 7 | import RenderEditCanvas from './canvas/edit' |
| @@ -30,10 +32,19 @@ export default { | @@ -30,10 +32,19 @@ export default { | ||
| 30 | data: () => ({ | 32 | data: () => ({ |
| 31 | activeMenuKey: 'pluginList', | 33 | activeMenuKey: 'pluginList', |
| 32 | pages: [], | 34 | pages: [], |
| 33 | - elements: [], | 35 | + // elements: [], |
| 34 | isPreviewMode: false | 36 | isPreviewMode: false |
| 35 | }), | 37 | }), |
| 38 | + computed: { | ||
| 39 | + ...mapState('element', { | ||
| 40 | + editingElement: state => state.editingElement, | ||
| 41 | + elements: state => state.elementsOfCurrentPage | ||
| 42 | + }) | ||
| 43 | + }, | ||
| 36 | methods: { | 44 | methods: { |
| 45 | + ...mapActions('element', [ | ||
| 46 | + 'elementManager' | ||
| 47 | + ]), | ||
| 37 | getEditorConfig (pluginName) { | 48 | getEditorConfig (pluginName) { |
| 38 | // const pluginCtor = Vue.options[pluginName] | 49 | // const pluginCtor = Vue.options[pluginName] |
| 39 | // const pluginCtor = this.$options.components[pluginName] | 50 | // const pluginCtor = this.$options.components[pluginName] |
| @@ -49,7 +60,11 @@ export default { | @@ -49,7 +60,11 @@ export default { | ||
| 49 | const zindex = this.elements.length + 1 | 60 | const zindex = this.elements.length + 1 |
| 50 | // const defaultPropsValue = this.getPropsDefaultValue(name) | 61 | // const defaultPropsValue = this.getPropsDefaultValue(name) |
| 51 | const editorConfig = this.getEditorConfig(name) | 62 | const editorConfig = this.getEditorConfig(name) |
| 52 | - this.elements.push(new Element({ name, zindex, editorConfig })) | 63 | + // this.elements.push(new Element({ name, zindex, editorConfig })) |
| 64 | + this.elementManager({ | ||
| 65 | + type: 'add', | ||
| 66 | + value: { name, zindex, editorConfig } | ||
| 67 | + }) | ||
| 53 | } | 68 | } |
| 54 | }, | 69 | }, |
| 55 | render (h) { | 70 | render (h) { |
front-end/h5/src/components/core/models/element.js
| @@ -16,28 +16,34 @@ class Element { | @@ -16,28 +16,34 @@ class Element { | ||
| 16 | this.name = ele.name | 16 | this.name = ele.name |
| 17 | this.uuid = +new Date() | 17 | this.uuid = +new Date() |
| 18 | this.editorConfig = ele.editorConfig || {} | 18 | this.editorConfig = ele.editorConfig || {} |
| 19 | - this.pluginProps = {} | ||
| 20 | - this.commonStyle = {} | ||
| 21 | - this.init() | 19 | + /** |
| 20 | + * 之前版本代码:https://github.com/ly525/luban-h5/blob/a7875cbc73c0d18bc2459985ca3ce1d4dc44f141/front-end/h5/src/components/core/models/element.js#L21 | ||
| 21 | + * 1.之前的版本为:this.pluginProps = {}, 改为下面的版本 | ||
| 22 | + * 是因为要支持[复制画布上的元素],所以需要先使用 ele.pluginProps 进行初始化(也就是拷贝之前的元素的值) | ||
| 23 | + * | ||
| 24 | + * 2. 移除 this.init() 原因是:如果是 复制元素,则 init 会把 copy 的值重新覆盖为初始值,copy 无效 | ||
| 25 | + */ | ||
| 26 | + this.pluginProps = ele.pluginProps || this.getDefaultPluginProps() | ||
| 27 | + this.commonStyle = ele.commonStyle || this.getDefaultCommonStyle() | ||
| 22 | } | 28 | } |
| 23 | 29 | ||
| 24 | - init () { | ||
| 25 | - const commonStyle = this.commonStyle | ||
| 26 | - // init common props | ||
| 27 | - Object.keys(defaultProps).forEach(key => { | ||
| 28 | - commonStyle[key] = defaultProps[key] | ||
| 29 | - }) | 30 | + getDefaultCommonStyle () { |
| 31 | + return { ...defaultProps } | ||
| 32 | + } | ||
| 30 | 33 | ||
| 34 | + getDefaultPluginProps () { | ||
| 31 | // init prop of plugin | 35 | // init prop of plugin |
| 32 | const propConf = this.editorConfig.propsConfig | 36 | const propConf = this.editorConfig.propsConfig |
| 37 | + const pluginProps = {} | ||
| 33 | Object.keys(propConf).forEach(key => { | 38 | Object.keys(propConf).forEach(key => { |
| 34 | // #6 | 39 | // #6 |
| 35 | if (key === 'name') { | 40 | if (key === 'name') { |
| 36 | console.warn('Please do not use {name} as plugin prop') | 41 | console.warn('Please do not use {name} as plugin prop') |
| 37 | return | 42 | return |
| 38 | } | 43 | } |
| 39 | - this.pluginProps[key] = propConf[key].defaultPropValue | 44 | + pluginProps[key] = propConf[key].defaultPropValue |
| 40 | }) | 45 | }) |
| 46 | + return pluginProps | ||
| 41 | } | 47 | } |
| 42 | 48 | ||
| 43 | getStyle (position = 'static') { | 49 | getStyle (position = 'static') { |
| @@ -64,6 +70,19 @@ class Element { | @@ -64,6 +70,19 @@ class Element { | ||
| 64 | getData () { | 70 | getData () { |
| 65 | 71 | ||
| 66 | } | 72 | } |
| 73 | + | ||
| 74 | + clone () { | ||
| 75 | + return new Element({ | ||
| 76 | + name: this.name, | ||
| 77 | + editorConfig: this.editorConfig, | ||
| 78 | + pluginProps: JSON.parse(JSON.stringify(this.pluginProps)), | ||
| 79 | + commonStyle: { | ||
| 80 | + ...this.commonStyle, | ||
| 81 | + top: this.commonStyle.top + 20, | ||
| 82 | + left: this.commonStyle.left + 20 | ||
| 83 | + } | ||
| 84 | + }) | ||
| 85 | + } | ||
| 67 | } | 86 | } |
| 68 | 87 | ||
| 69 | export default Element | 88 | export default Element |
front-end/h5/src/store/modules/element.js
| 1 | // initial state | 1 | // initial state |
| 2 | +import Element from '../../components/core/models/element' | ||
| 3 | + | ||
| 2 | const state = { | 4 | const state = { |
| 3 | - editingElement: null | 5 | + editingElement: null, |
| 6 | + elementsOfCurrentPage: [] | ||
| 4 | } | 7 | } |
| 5 | 8 | ||
| 6 | // getters | 9 | // getters |
| @@ -18,6 +21,9 @@ const actions = { | @@ -18,6 +21,9 @@ const actions = { | ||
| 18 | }, | 21 | }, |
| 19 | setElementShape ({ commit }, payload) { | 22 | setElementShape ({ commit }, payload) { |
| 20 | commit('setElementCommonStyle', payload) | 23 | commit('setElementCommonStyle', payload) |
| 24 | + }, | ||
| 25 | + elementManager ({ commit }, payload) { | ||
| 26 | + commit('elementManager', payload) | ||
| 21 | } | 27 | } |
| 22 | } | 28 | } |
| 23 | 29 | ||
| @@ -31,6 +37,18 @@ const mutations = { | @@ -31,6 +37,18 @@ const mutations = { | ||
| 31 | ...state.editingElement.commonStyle, | 37 | ...state.editingElement.commonStyle, |
| 32 | ...payload | 38 | ...payload |
| 33 | } | 39 | } |
| 40 | + }, | ||
| 41 | + elementManager (state, { type, value }) { | ||
| 42 | + switch (type) { | ||
| 43 | + case 'add': | ||
| 44 | + const element = new Element(value) | ||
| 45 | + state.elementsOfCurrentPage.push(element) | ||
| 46 | + break | ||
| 47 | + case 'copy': | ||
| 48 | + state.elementsOfCurrentPage.push(state.editingElement.clone()) | ||
| 49 | + break | ||
| 50 | + default: | ||
| 51 | + } | ||
| 34 | } | 52 | } |
| 35 | } | 53 | } |
| 36 | 54 |