优化代码

This commit is contained in:
ival 2021-03-31 18:13:58 +08:00
parent 134ccdaded
commit 62cd098bdd
15 changed files with 202 additions and 123 deletions

View File

@ -0,0 +1,3 @@
export default {
}

View File

@ -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();
}

View File

@ -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;

View File

@ -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: {

View File

@ -34,4 +34,4 @@ class FormBuilder {
}
}
export default formBuilder;
export default FormBuilder;

View File

@ -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));

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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:

View File

@ -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;

View File

@ -0,0 +1,7 @@
export default {
ADD: '__ADD__',
DELETE: '__DEL__',
UPDATE: '__UPT__',
BINDING: '__BINDING__',
UNBINDING: '__UNBINDING__',
}

View File

@ -4,6 +4,7 @@
<el-row>
<el-input type="textarea" :rows="4" v-model="json" />
<el-button @click="doRemove"> 删除 </el-button>
<el-button @click="doUnbinding">解绑</el-button>
<el-button @click="doSource"> 源数据 </el-button>
</el-row>
</div>
@ -14,9 +15,12 @@
<script>
import Vue from 'vue';
import Iscs from '@/iscs_new/map';
import orders from '@/iscs_new/utils/orders';
import shapeType from '@/iscs_new/constant/shapeType';
import { mapGetters } from 'vuex';
import { exitFullscreen } from '@/utils/screen';
export default {
data() {
return {
@ -173,6 +177,7 @@ export default {
onSelected(em) {
if (em) {
this.selected = this.$iscs.getShapeByCode(em.code)
console.log(em, this.selected);
}
},
//
@ -208,7 +213,22 @@ export default {
},
doRemove() {
if (this.selected) {
this.$iscs.render({...model, _dispose: true});
this.$iscs.render([
{
model: this.selected.model,
action: { order: orders.DELETE, shapeType: shapeType.Compose }
}
]);
}
},
doUnbinding() {
if (this.selected) {
this.$iscs.render([
{
model: this.selected.model,
action: { order: orders.UNBINDING, shapeType: shapeType.Compose }
}
]);
}
},
doSource() {