diff --git a/src/iscs_new/config/defaultState.js b/src/iscs_new/config/defaultState.js new file mode 100644 index 000000000..03048022a --- /dev/null +++ b/src/iscs_new/config/defaultState.js @@ -0,0 +1,3 @@ +export default { + +} diff --git a/src/iscs_new/controller.js b/src/iscs_new/controller.js index 788200e12..66fdedb23 100644 --- a/src/iscs_new/controller.js +++ b/src/iscs_new/controller.js @@ -253,7 +253,7 @@ export default class Controller extends Eventful { this.setCursorStyle('auto'); } - // this._locking = false; 设置false时,拖动完成后,需要重新激活 + // this.setLocking(false); 设置false时,拖动完成后,需要重新激活 this._target = null; } @@ -286,7 +286,7 @@ export default class Controller extends Eventful { click(e) { const event = new MouseEvent(e); if (event.code) { - this._locking = true; + this.setLocking(true) } else { this.selectHandle.clear(); this.selectingHandle.clear(); @@ -340,6 +340,10 @@ export default class Controller extends Eventful { this._locking = false; } + setLocking(lock=false) { + this._locking = lock; + } + destroy () { this.dispose(); } diff --git a/src/iscs_new/core/abstractShape.js b/src/iscs_new/core/abstractShape.js index de0c1afcb..77b0f4a5b 100644 --- a/src/iscs_new/core/abstractShape.js +++ b/src/iscs_new/core/abstractShape.js @@ -2,10 +2,9 @@ import shapeType from '../constant/shapeType'; // 图形抽象层 class AbstractShape { - constructor({model, defaultStyle, option, shapeFactory}) { + constructor({model, option, shapeFactory}) { this.model = model; this.option = option; - this.defaultStyle = defaultStyle; this.shapeFactory = shapeFactory; } @@ -30,6 +29,12 @@ class AbstractShape { // 销毁图形 destroy() {} + + // 获取包围框 + getBoundingRect() {} + + // 获取依赖图形 + getDepShapes() {} } export default AbstractShape; diff --git a/src/iscs_new/core/form/form2Base.js b/src/iscs_new/core/form/form2Base.js index d19b1d533..404c257b2 100644 --- a/src/iscs_new/core/form/form2Base.js +++ b/src/iscs_new/core/form/form2Base.js @@ -6,6 +6,9 @@ export default { // number 0 控制图形的前后顺序。z2 值小的图形会被 z2 值大的图形覆盖。z2 相比 z1 优先级更低,而且不会创建新的 Canvas。 z2: { prop: 'z', label: '层级 z2', type: 'select', defValue: 10, + }, + name: { + }, // boolean false 是否进行裁剪。 culling: { diff --git a/src/iscs_new/core/form/formBuilder.js b/src/iscs_new/core/form/formBuilder.js index 1aff3c1f1..7b9da0b1c 100644 --- a/src/iscs_new/core/form/formBuilder.js +++ b/src/iscs_new/core/form/formBuilder.js @@ -34,4 +34,4 @@ class FormBuilder { } } -export default formBuilder; +export default FormBuilder; diff --git a/src/iscs_new/draggable/Image.js b/src/iscs_new/draggable/Image.js index e917c3cce..840e4cfd8 100644 --- a/src/iscs_new/draggable/Image.js +++ b/src/iscs_new/draggable/Image.js @@ -96,7 +96,7 @@ export default class ImageDraggable extends graphic.Group { this.handle.e.target && this.offset) { if (!eventTool.isMiddleOrRightButtonOnMouseUpDown(e)) { - const type = this.handle.e.target.model._type; + const type = this.handle.e.target.model.type; const dx = Math.round(e.offsetX-this.offset.x); const dy = Math.round(e.offsetY-this.offset.y); @@ -112,7 +112,7 @@ export default class ImageDraggable extends graphic.Group { if (this.target && this.handle.e.target && this.offset) { - const type = this.handle.e.target.model._type; + const type = this.handle.e.target.model.type; const dx = Math.round(e.offsetX-this.offset.x); const dy = Math.round(e.offsetY-this.offset.y); this.setShape(...this.handle.normalizedDiff(dx, dy)); diff --git a/src/iscs_new/factory/compose.js b/src/iscs_new/factory/compose.js index bb7cb0a1e..8f97e054a 100644 --- a/src/iscs_new/factory/compose.js +++ b/src/iscs_new/factory/compose.js @@ -19,15 +19,7 @@ class Compose extends AbstractShape { // 设置高亮 active() { - let unionRect = null; - this.model.elementCodes.forEach(code => { - const element = this.shapeFactory.getShapeByCode(code) - if (element && element.instance && !element.instance.invisible) { - const rect = element.instance.getBoundingRect().clone(); - unionRect ? unionRect.union(rect): (unionRect = rect); - } - }) - + const unionRect = this.getBoundingRect(); if (unionRect) { this.shapeFactory.trigger(shapeEvent.ShowHightLight, unionRect); } @@ -35,7 +27,7 @@ class Compose extends AbstractShape { // 取消高亮 inactive() { - this.shapeFactory.trigger(shapeEvent.HideHightLight, new BoundingRect(0,0,0,0)); + this.shapeFactory.trigger(shapeEvent.HideHightLight); } // 设置获取焦点 @@ -50,7 +42,35 @@ class Compose extends AbstractShape { setState(state) {} // 销毁图形 - destroy() {} + destroy() { + this.model.elementCodes.forEach(code => { + const element = this.shapeFactory.getShapeByCode(code); + if (element && + element.model) { + element.model.composeCode = ''; + element.instance.attr(element.model) + } + }) + this.model.elementCodes = []; + } + + // 获取依赖图形 + getDepShapes() { + return this.model.elementCodes.map(code => this.shapeFactory.getShapeByCode(code)).filter(el => el) + } + + // 获取包围框 + getBoundingRect() { + let unionRect = null; + this.model.elementCodes.forEach(code => { + const element = this.shapeFactory.getShapeByCode(code) + if (element && element.instance && !element.instance.invisible) { + const rect = element.instance.getBoundingRect().clone(); + unionRect ? unionRect.union(rect): (unionRect = rect); + } + }) + return unionRect; + } } export default Compose; diff --git a/src/iscs_new/factory/element.js b/src/iscs_new/factory/element.js index d915a7bb8..235016eeb 100644 --- a/src/iscs_new/factory/element.js +++ b/src/iscs_new/factory/element.js @@ -82,7 +82,7 @@ class Element extends AbstractShape { // 取消高亮 inactive() { - this.shapeFactory.trigger(shapeEvent.HideHightLight, this.instance.getBoundingRect()); + this.shapeFactory.trigger(shapeEvent.HideHightLight); } // 设置获取焦点 @@ -97,7 +97,28 @@ class Element extends AbstractShape { setState(state) {} // 销毁图形 - destroy() {} + destroy() { + const compose = this.shapeFactory.getShapeByCode(this.model.composeCode); + if (compose && + compose.model && + compose.model.elementCodes) { + const index = compose.model.elementCodes.findIndex(this.model.code); + if (index >= 0) { + compose.model.elementCodes.splice(index, 1); + } + } + } + + // 获取依赖图形 + getDepShapes() { + return [] + } + + + // 获取包围框 + getBoundingRect() { + return this.instance.getBoundingRect(); + } } export default Element; diff --git a/src/iscs_new/factory/index.js b/src/iscs_new/factory/index.js index c0cbefaa4..e015f6407 100644 --- a/src/iscs_new/factory/index.js +++ b/src/iscs_new/factory/index.js @@ -7,6 +7,7 @@ import Element from './element'; import shapeType from '../constant/shapeType'; import shapeRender from '../constant/shapeRender'; import shapeEvent from '../constant/shapeEvent'; +import orders from '../utils/orders'; const None = e => null; const shapeBuilderMap = { @@ -14,6 +15,28 @@ const shapeBuilderMap = { [shapeType.Compose]: Compose } +function update2List(source, model, action, name='') { + const list = source[name]; + + if (!list) { source[name] = []; } + + let updateModel = model; + const i = list.findIndex(elem => { return elem.code == model.code; }) + switch(action.order) { + case orders.ADD: + list.push(model); + break; + case orders.UNBINDING: + case orders.DELETE: + i >= 0 && list.splice(i, 1); + break; + case orders.UPDATE: + Object.assign(list[i]||{}, model) + break; + } + + return updateModel; +} class ShapeFactory extends Eventful { constructor(map) { super(); @@ -53,30 +76,21 @@ class ShapeFactory extends Eventful { return this; } - parse(source={}, defaultStyle={}, walk=None) { + parse(source={}, walk=None) { try { this.source = source; - zrUtil.each(source.elementList ||[], el => { - walk(this.storageShape(this.createShape(el, defaultStyle, {...shapeRender, _type: shapeType.Element}))); + zrUtil.each(source.elementList ||[], model => { + walk(this.storageShape(this.createShape(model, {...shapeRender, shapeType: shapeType.Element}))); }, this); - zrUtil.each(source.composeList ||[], el => { - this.storageShape(this.createShape(el, defaultStyle, {...shapeRender, _type: shapeType.Compose})); + zrUtil.each(source.composeList ||[], model => { + this.storageShape(this.createShape(model, {...shapeRender, shapeType: shapeType.Compose})); }, this); } catch (error) { console.error('[ERROR] ', error); } } - createShape(model={}, defaultStyle={}, option={}) { - let shape = null; - const shapeBuilder = shapeBuilderMap[option._type]; - if (shapeBuilder) { - shape = new shapeBuilder({model, defaultStyle, option, shapeFactory: this}); - } - return shape; - } - storageShape(shape) { if (shape && shape.model) { this.mapShape[shape.model.code] = shape; @@ -84,42 +98,32 @@ class ShapeFactory extends Eventful { return shape; } + createShape(model={}, option={}) { + let shape = null; + const shapeBuilder = shapeBuilderMap[option.shapeType]; + if (shapeBuilder) { + shape = new shapeBuilder({model, option, shapeFactory: this}); + } + return shape; + } + removeShape(shape) { if (shape && shape.model) { + this.trigger(shapeEvent.HideHightLight); + shape.destroy(); delete this.mapShape[shape.model.code]; } return shape; } - updateSource(model={}) { - switch (model._type) { - case shapeType.Compose: return { model: update2List(model, 'composeList'), option: {...shapeRender, _type: shapeType.Compose}}; - case shapeType.Element: return { model: update2List(model, 'elementList'), option: {...shapeRender, _type: shapeType.Element}}; + updateSource(model={}, action={}) { + switch (action.shapeType) { + case shapeType.Compose: return update2List(this.source, model, action, 'composeList'); + case shapeType.Element: return update2List(this.source, model, action, 'elementList'); } return null; } - update2List(model={}, name='') { - const list = this.source[name]; - const dispose = model._dispose; - const entries = Object.entries(model).filter(el => !['_type', '_dispose'].includes(el[0])); - const cleanModel = Object.fromEntries(entries); - let retModel = cleanModel; - - if (list && list instanceof Array) { - const i = list.findIndex(elem => { return elem.code == model.code; }); - if (i < 0) { - list.push(cleanModel) - } else { - retModel = dispose ? list.splice(i, 1) : Object.assign(list[i], cleanModel); - } - } else { - source[name] = [cleanModel]; - } - - return retModel; - } - getSource() { return this.source; } diff --git a/src/iscs_new/map.js b/src/iscs_new/map.js index 0d105ee73..6908c3d38 100644 --- a/src/iscs_new/map.js +++ b/src/iscs_new/map.js @@ -8,7 +8,9 @@ import Option from './option'; import Controller from './controller'; import StateHandle from './stateHandle'; import ShapeFactory from './factory'; -import defaultStyle from './config/defaultStyle'; +import orders from './utils/orders'; +import shapeRender from './constant/shapeRender'; +import shapeType from './constant/shapeType'; const renderer = 'canvas'; const devicePixelRatio = 1; @@ -31,12 +33,6 @@ class JMap { __Keydown: '__keydown__' }; - // 默认状态 - this.defaultState = this.loadDefaultState(); - - // 默认皮肤 - this.defaultStyle = this.loadDefaultStyle(); - // 初始化Map实例 this.initMapInstance(opts); } @@ -75,14 +71,6 @@ class JMap { }; } - loadDefaultState(state) { - return {}; - } - - loadDefaultStyle(style) { - return defaultStyle; - } - setMap(templates=[], source={}, eventOpts={}) { // 绑定事件 this.$controller.enable(eventOpts); @@ -154,7 +142,7 @@ class JMap { repaint(source={}) { this.$shapeFactory.clear(); this.$painter.clear(); - this.$shapeFactory.parse(source, this.defaultStyle, shape => { + this.$shapeFactory.parse(source, shape => { if (shape) { this.$painter.add(shape); } @@ -162,19 +150,35 @@ class JMap { } render(list=[]) { - list.forEach(el => { - const dispose = el._dispose; - const oldShape = this.$shapeFactory.getShapeByCode(el.code); - const block = this.$shapeFactory.updateSource(el); + list.forEach(({model, action}) => { + const updateModel = this.$shapeFactory.updateSource(model, action); + const shape = this.$shapeFactory.getShapeByCode(updateModel.code); + const deps = shape.getDepShapes(); + const oldShape = this.$shapeFactory.removeShape(shape); + const newShape = this.$shapeFactory.createShape(updateModel, {...shapeRender, ...action}); - if (dispose) { - this.$painter.remove(oldShape); - this.$shapeFactory.removeShape(oldShape); - } else if (block) { - const createShape = this.$shapeFactory.createShape(block.model, block.option); - this.$painter.remove(oldShape); - this.$shapeFactory.storageShape(createShape) - this.$painter.add(createShape); + if (updateModel) { + switch(action.order) { + case orders.ADD: + this.$shapeFactory.storageShape(newShape) + this.$painter.add(newShape); + break; + case orders.DELETE: + this.$painter.remove(oldShape); + deps.forEach(shape => { + this.$shapeFactory.updateSource(shape.model, {...action, shapeType: shapeType.Element}); + this.$painter.remove(shape); + }); + break; + case orders.UPDATE: + this.$painter.remove(oldShape); + this.$shapeFactory.storageShape(newShape) + this.$painter.add(newShape); + break; + case orders.UNBINDING: + this.$painter.remove(oldShape); + break; + } } }); @@ -228,10 +232,6 @@ class JMap { return this.defaultState; } - getDefaultStyle() { - return this.defaultStyle; - } - getShapeByCode(code) { return this.$shapeFactory.getShapeByCode(code); } diff --git a/src/iscs_new/painter.js b/src/iscs_new/painter.js index 09e2e03eb..ac067a625 100644 --- a/src/iscs_new/painter.js +++ b/src/iscs_new/painter.js @@ -47,28 +47,26 @@ class Painter extends Group { } add(shape) { - try { + if (shape && shape.model) { const shapeLevel = this.mapShapeLevel[shape.model.type]; - shapeLevel.add(shape.instance); - } catch (err) { - console.error(err); + if (shapeLevel && shape.instance) { + shapeLevel.add(shape.instance); + } } } remove(shape) { - try { + if (shape && shape.model) { const shapeLevel = this.mapShapeLevel[shape.model.type]; - shapeLevel.remove(shape.instance); - } catch (err) { - console.error(err); + if (shapeLevel && shape.instance) { + shapeLevel.remove(shape.instance); + } } } update(shape) { - try { + if (shape && shape.model) { // - } catch (err) { - console.error(err); } } diff --git a/src/iscs_new/selectHandle.js b/src/iscs_new/selectHandle.js index d5e219ba0..897077603 100644 --- a/src/iscs_new/selectHandle.js +++ b/src/iscs_new/selectHandle.js @@ -15,16 +15,16 @@ export default class SelectHandle { onSelected(e) { if (e.target) { - this.e = {...e }; + this.e = {...e}; if (['Control'].includes(this.$controller.getKeyStr())) { + console.log(this.$controller.isSelected(e.target.model.code)); if (this.$controller.isSelected(e.target.model.code)) { this.delSelected(e.target); } else { this.addSelected(e.target); } - } else if (this.$controller.selectingHandle.isSelecting()) { - this.addSelected(e.target); } else { + console.log(2222) this.clear(); this.addSelected(e.target); } @@ -33,23 +33,11 @@ export default class SelectHandle { addSelected(target) { this.$controller.storage.set(target.model.code, target); - target.active(); - - if (!target.highLightInstance) { - target.highLightInstance = this.createSelected(target); - this.$painter.addToLevel(shapeLayer.HightLight)(target.highLightInstance); - } } delSelected(target) { target.inactive(); - - if (target.highLightInstance) { - this.$painter.removeFromLevel(shapeLayer.HightLight)(target.highLightInstance); - target.highLightInstance = null; - } - this.$controller.storage.delete(target.model.code); } @@ -61,7 +49,7 @@ export default class SelectHandle { createSelected(target) { if (this.$map.draggle) { - switch (target.model._type) { + switch (target.model.type) { case graphic.Line: return new LineDraggable(this); case graphic.Image: diff --git a/src/iscs_new/selectingHandle.js b/src/iscs_new/selectingHandle.js index 5c3cdd06f..b21a732c7 100644 --- a/src/iscs_new/selectingHandle.js +++ b/src/iscs_new/selectingHandle.js @@ -1,6 +1,7 @@ import * as graphic from './core/graphic.js'; import shapeRender from './constant/shapeRender'; import shapeLayer from './constant/shapeLayer'; +import shapeType from './constant/shapeType.js'; function shapeStyleBuilder() { return { @@ -56,11 +57,11 @@ export default class SelectingHandle { const selectingRect = this.selecting.getBoundingRect(); Object.values(this.$map.getMapShape()).forEach(el => { - if (el.instance && selectingRect.intersect(el.instance.getBoundingRect())) { - if (el.model.composeCode) { - this.setSelected(this.$map.getShapeByCode(el.model.composeCode)); - } else { + if (el.model && this.checkSelectingRectContainShape(selectingRect, el)) { + console.log(1111111); + if (!el.model.composeCode) { this.setSelected(el); + this.$controller.setLocking(true); } } }); @@ -78,6 +79,11 @@ export default class SelectingHandle { this.$painter.removeFromLevel(shapeLayer.SelectIng)(this.selecting); } + checkSelectingRectContainShape(rect, shape) { + const shapeRect = shape.getBoundingRect(); + return shapeRect? rect.intersect(shapeRect): false; + } + normalizedArea(begin, end) { const options = this.$map.getOption(); const x = (begin.x + options.offsetX) / options.scaleRate; diff --git a/src/iscs_new/utils/orders.js b/src/iscs_new/utils/orders.js new file mode 100644 index 000000000..560498317 --- /dev/null +++ b/src/iscs_new/utils/orders.js @@ -0,0 +1,7 @@ +export default { + ADD: '__ADD__', + DELETE: '__DEL__', + UPDATE: '__UPT__', + BINDING: '__BINDING__', + UNBINDING: '__UNBINDING__', +} diff --git a/src/views/test/index.vue b/src/views/test/index.vue index b1721132c..5467ee670 100644 --- a/src/views/test/index.vue +++ b/src/views/test/index.vue @@ -4,6 +4,7 @@ 删除 + 解绑 源数据 @@ -14,9 +15,12 @@