diff --git a/src/jmap/eventController.js b/src/jmap/eventController.js deleted file mode 100644 index 43a7e575f..000000000 --- a/src/jmap/eventController.js +++ /dev/null @@ -1,7 +0,0 @@ -class EventController { - constructor(jmap) { - - } - - -} \ No newline at end of file diff --git a/src/jmap/map.js b/src/jmap/map.js index 13d3ce723..00289ecec 100644 --- a/src/jmap/map.js +++ b/src/jmap/map.js @@ -1,15 +1,28 @@ import * as zrUtil from 'zrender/src/core/util'; +import zrender from 'zrender'; import Painter from './painter'; import ProxyHandle from './proxyHandle'; +import MouseController from './mouseController'; import deviceState from './config/deviceState'; import deviceStyle from './config/deviceStyle'; import deviceType from './config/deviceType'; import { parser, deviceFactory } from './utils/parser'; +const renderer = 'canvas'; +const devicePixelRatio = 2; + class Jmap { constructor(opts) { - // 挂载的dom节点 - this.$dom = opts.dom; + // 绘图句柄 + this.zr = zrender.init(opts.dom, Object.assign({ + renderer, + devicePixelRatio, + width: opts.dom.clientWidth, + height: opts.dom.clientHeight + }, opts.config)); + + // 鼠标事件 + this.events = { Pan: 'pan', Zoom: 'zoom', Selected: 'selected', Contextmenu: 'contextmenu' }; // 回调事件 this.methods = opts.methods; @@ -18,7 +31,7 @@ class Jmap { this.data = {}; // 默认初始状态 - this.defaultStateDict = this.loaddefaultState(); + this.defaultStateDict = this.loadDefaultState(); // 皮肤参数 this.skinStyle = ''; @@ -29,11 +42,16 @@ class Jmap { // 设备数据 this.mapDevice = {}; - // 设备代理数据 + // 代理数据 this.proxyData = {}; // 绘图模块 - this.$painter = new Painter(this, opts); + this.painter = new Painter(this); + + // 鼠标事件 + this.mouseController = new MouseController(this); + + this.mouseController.enable(); } /** @@ -41,34 +59,36 @@ class Jmap { * @param {*} data */ loadData(skinStyle, data) { + // 保存皮肤类型 + this.skinStyle = skinStyle; + // 保存原始数据 this.data = data; // 加载皮肤 this.styleDict = this.loadStyle(skinStyle); - console.log('开始解析'); - // 解析地图数据 this.mapDevice = parser(data, this.defaultStateDict); - console.log('解析数据完成'); // 生成代理对象 - this.proxyData = new Proxy(this.mapDevice, new ProxyHandle(this)); + this.proxyData = new Proxy(this.mapDevice, new ProxyHandle(this.painter)); - this.methods.dataLoaded(); + // 数据加载完成回调 + (this.methods.dataLoaded instanceof Function) && this.methods.dataLoaded(); // 初次渲染视图 - this.$painter.repaint(this.mapDevice, this.styleDict); + this.painter.repaint(this.mapDevice, this.styleDict); - this.methods.stateLoaded(); + // 视图渲染完成回调 + (this.methods.viewLoaded instanceof Function) && this.methods.viewLoaded(); } loadStyle(skinStyle) { return deviceStyle; } - loaddefaultState() { + loadDefaultState() { const defaultStateDict = {}; zrUtil.each(Object.keys(deviceState), (type) => { @@ -81,6 +101,18 @@ class Jmap { return defaultStateDict; } + setDefaultState() { + let list = []; + + Object.values(this.mapDevice).forEach(elem => { + let code = elem._code; + let type = elem._type; + list.push(Object.assign({ code, type }, this.defaultStateDict[type])); + }) + + this.update(list); + } + syncData(model) { let code = model.code; let type = model.type; @@ -113,7 +145,7 @@ class Jmap { device = this.proxyData[code] = Object.assign(device, { model }); } - // this.syncData(model); + this.syncData(model); }) } @@ -130,8 +162,16 @@ class Jmap { }) } + getZr() { + return this.zr; + } + getPainter() { - return this.$painter; + return this.painter; + } + + getEvents() { + return this.events; } getSkinStyle() { @@ -151,11 +191,11 @@ class Jmap { } refresh() { - this.$painter.refresh(); + this.painter.refresh(); } clear() { - this.$painter.clear(); + this.painter.clear(); } dispose() { @@ -163,7 +203,8 @@ class Jmap { this.styleDict = {}; this.mapDevice = {}; this.proxyData = {}; - this.$painter.dispose(); + this.zr && zrender.dispose(this.zr); + this.painter.dispose(); } } diff --git a/src/jmap/mouseController.js b/src/jmap/mouseController.js new file mode 100644 index 000000000..197f98a54 --- /dev/null +++ b/src/jmap/mouseController.js @@ -0,0 +1,170 @@ +import deviceType from './config/deviceType'; +import Eventful from 'zrender/src/mixin/Eventful'; +import * as eventTool from 'zrender/src/core/event'; + +class EventModel { + constructor(e) { + this.clientX = e.event.clientX; + this.clientY = e.event.clientY; + + debugger + let view = e.target; + if (view) { + if (view._subType) { + this.subType = view._subType; + } + if (view._val) { + this.val = view._val; + } + } + + while (view) { + if (view._type in Object.values(deviceType)) { + this.code = view._code; + this.type = view._type; + break; + } + + if (!this.val) { + if (view._subType) { + this.subType = view._subType; + } + if (view._val) { + this.val = view._val; + } + } + + view = view.parent; + } + } +} + +class MouseController extends Eventful { + constructor(jmap) { + super(); + this.zr = jmap.getZr(); + this.events = jmap.getEvents(); + this.throttle = 100; // 刷新频率 + + let clickHandler = this.click.bind(this); + let contextmenuHandler = this.contextmenu.bind(this); + let moveEventHandler = this.moveEvent.bind(this); + + this.zr.on('click', clickHandler); + this.zr.on('contextmenu', contextmenuHandler); + this.zr.on('mousemove', moveEventHandler); + + let mousedownHandler = this.mousedown.bind(this); + let mousemoveHandler = this.mousemove.bind(this); + let mouseupHandler = this.mouseup.bind(this); + let mousewheelHandler = this.mousewheel.bind(this); + + this.enable = function (opts) { + opts = opts || {}; + this._moveOnMouseMove = opts.moveOnMouseMove || true; + this._zoomOnMouseWheel = opts.zoomOnMouseWheel || false; + this._preventDefaultMouseMove = opts.preventDefaultMouseMove || true; + + this.disable(); + + this.zr.on('mousedown', mousedownHandler); + this.zr.on('mousemove', mousemoveHandler); + this.zr.on('mouseup', mouseupHandler); + this.zr.on('mousewheel', mousewheelHandler); + } + + this.disable = function () { + this.zr.off('mousedown', mousedownHandler); + this.zr.off('mousemove', mouseupHandler); + this.zr.off('mouseup', mousemoveHandler); + this.zr.off('mousewheel', mousewheelHandler); + } + + this.isDragging = function () { return this._dragging; } + } + + mousedown(e) { + if (eventTool.notLeftMouse(e)) { + return; + } + + this._x = e.offsetX; + this._y = e.offsetY; + this._dragging = true; + } + + mousemove(e) { + if (eventTool.notLeftMouse(e) + || !this._moveOnMouseMove + || !this._dragging + ) { + return; + } + + let oldX = this._x; + let oldY = this._y; + + let dx = e.offsetX - oldX; + let dy = e.offsetY - oldY; + + this._x = e.offsetX; + this._y = e.offsetY; + + this._preventDefaultMouseMove && eventTool.stop(e.event); + + this.trigger(this.events.Pan, { + dx: dx, dy: dy, oldX: oldX, oldY: oldY, newX: this._x, newY: this._y + }); + } + + mouseup(e) { + if (!eventTool.notLeftMouse(e)) { + this._dragging = false; + } + } + + mousewheel(e) { + let shouldZoom = this._zoomOnMouseWheel; + let wheelDelta = e.wheelDelta; + let originX = e.offsetX; + let originY = e.offsetY; + + if (wheelDelta === 0 || !shouldZoom) { + return; + } + if (shouldZoom) { + eventTool.stop(e.event); + let scale = 1; + if (wheelDelta > 0) { + scale = 1; + } else if (wheelDelta < 0) { + scale = -1; + } + + this.trigger(this.events.Zoom, { + type: 'zoom', scale: scale, originX: originX, originY: originY + }); + } + } + + click(e) { + var em = this.checkEvent(e); + this.trigger(this.events.Selected, em); + } + + contextmenu(e) { + var em = this.checkEvent(e); + this.trigger(this.events.Contextmenu, em); + } + + moveEvent(e) { + return new EventModel(e); + } + + checkEvent(e) { + return new EventModel(e); + } + +} + +export default MouseController; \ No newline at end of file diff --git a/src/jmap/painter.js b/src/jmap/painter.js index 8b843a062..85514a2b8 100644 --- a/src/jmap/painter.js +++ b/src/jmap/painter.js @@ -1,20 +1,13 @@ -import zrender from 'zrender'; import * as zrUtil from 'zrender/src/core/util'; import Group from 'zrender/src/container/Group'; import deviceType from './config/deviceType'; import shapefactory from './shape/factory'; -import ZoomController from './zoomController'; - -const renderer = 'canvas'; -const devicePixelRatio = 2; +import ZoomHandle from './zoomHandle'; class Painter { - constructor(jamp, opts) { + constructor(jamp) { // 父级实例 - this.$jamp = jamp; - - // zrender实例 - this.$zr = null; + this.jmap = jamp; // 图层数据 this.viewLevelMap = {}; @@ -26,24 +19,21 @@ class Painter { this.parentLevel = null; // 视图控制器 - this.zoomController = null; + this.zoomHandle = new ZoomHandle(this); - // 挂载视图 - this.mount(opts.dom, Object.assign({ renderer, devicePixelRatio, width: opts.dom.width, height: opts.dom.clientHeight }, opts.config)); + // 初始绘图实例 + this.initPainterInstance(); } /** - * 挂载视图 + * 初始绘图实例 * @param {*} dom * @param {*} config */ - mount(dom, config) { - // 挂载页面视图 - this.$zr = zrender.init(dom, config); - + initPainterInstance() { // 添加父级图层 this.parentLevel = new Group({ name: '__parent__' }); - this.$zr.add(this.parentLevel); + this.jmap.getZr().add(this.parentLevel); // 添加子级图层 zrUtil.each(Object.values(deviceType), (type) => { @@ -51,9 +41,6 @@ class Painter { this.viewLevelMap[type] = level; this.parentLevel.add(level); }); - - // 视图控制器 - this.zoomController = new ZoomController(this); } /** @@ -77,9 +64,9 @@ class Painter { add(device) { const type = device._type; const code = device._code; - const view = shapefactory(type, device, this.$jamp.getStyleDict()); + const view = shapefactory(type, device, this.jmap.getStyleDict()); if (view) { - this.zoomController.transformView(view); + this.zoomHandle.transformView(view); this.viewInstance[code] = view; this.viewLevelMap[type].add(view); } @@ -116,7 +103,7 @@ class Painter { * @param {*} zoom */ updateZoomTransform(zoom) { - this.zoomController.updateTransform(zoom); + this.zoomHandle.updateTransform(zoom); } /** @@ -131,7 +118,7 @@ class Painter { * 刷新画布,将在下一个渲染帧的时候被刷新。 */ refresh() { - this.$zr && this.$zr.refresh(); + this.jmap.getZr() && this.jmap.getZr().refresh(); } /** @@ -153,10 +140,9 @@ class Painter { * 销毁 ZRender 实例 */ dispose() { - this.$zr && zrender.dispose(this.$zr); - this.$zr = null; this.viewInstance = {}; this.viewLevelMap = {}; + this.parentLevel = null; } } diff --git a/src/jmap/proxyHandle.js b/src/jmap/proxyHandle.js index a404d370f..e3316afff 100644 --- a/src/jmap/proxyHandle.js +++ b/src/jmap/proxyHandle.js @@ -1,13 +1,13 @@ class ProxyHandle { - constructor(jmap) { - this.$painter = jmap.getPainter(); + constructor(painter) { + this.painter = painter; } set(target, code, device) { - if (this.$painter.hasViewInstance(code)) { - this.$painter.update(device); + if (this.painter.hasViewInstance(code)) { + this.painter.update(device); } else { - this.$painter.add(device); + this.painter.add(device); } return Reflect.set(target, code, device); } @@ -15,18 +15,10 @@ class ProxyHandle { deleteProperty(target, code) { let device = target[code]; if (device) { - this.$painter.delete(target[code]); + this.painter.delete(target[code]); } return Reflect.deleteProperty(target, code); } - - // has(target, code) { - // return Reflect.has(target, code); - // } - - // get(target, code) { - // return Reflect.get(target, code); - // } } export default ProxyHandle; diff --git a/src/jmap/shape/Link.js b/src/jmap/shape/Link.js index 8496ae9be..1799d4937 100644 --- a/src/jmap/shape/Link.js +++ b/src/jmap/shape/Link.js @@ -1,5 +1,6 @@ import Line from 'zrender/src/graphic/shape/Line'; import Group from 'zrender/src/container/Group'; +import { stat } from 'fs'; class Link extends Group { constructor({ _code, _type, zlevel, model, state }, style, styleGlobal) { @@ -44,7 +45,10 @@ class Link extends Group { } setState({ _code, _type, zlevel, model, state }) { - this.link.setStyle('stroke', 'green'); + switch (state.status) { + case '01': this.link.setStyle('stroke', 'green'); break; + case '02': this.link.setStyle('stroke', 'yellow'); break; + } } tipBasePoint() { diff --git a/src/jmap/utils/parser.js b/src/jmap/utils/parser.js index 618adbc42..c111fa7cd 100644 --- a/src/jmap/utils/parser.js +++ b/src/jmap/utils/parser.js @@ -7,7 +7,8 @@ export function deviceFactory(type, defaultStateDict, elem) { _type: type, _code: elem.code, model: elem, - state: Object.assign({}, defaultStateDict[type]) + state: {}, + // state: Object.assign({}, defaultStateDict[type]) }, deviceRender[type]); } diff --git a/src/jmap/zoomController.js b/src/jmap/zoomHandle.js similarity index 90% rename from src/jmap/zoomController.js rename to src/jmap/zoomHandle.js index c328bddb7..df946b016 100644 --- a/src/jmap/zoomController.js +++ b/src/jmap/zoomHandle.js @@ -19,12 +19,12 @@ function createBoundingRect(view) { return rect; } -class ZoomController { +class ZoomHandle { constructor(painter) { - this.$zr = painter.$zr; + this.zr = painter.jmap.getZr(); this.parentLevel = painter.parentLevel; - this.rect = { x: 0, y: 0, width: this.$zr.getWidth(), height: this.$zr.getHeight() }; + this.rect = { x: 0, y: 0, width: this.zr.getWidth(), height: this.zr.getHeight() }; this.transform = createTransform({ scale: 1, offsetX: 0, offsetY: 0 }); } @@ -74,4 +74,4 @@ class ZoomController { } } -export default ZoomController; \ No newline at end of file +export default ZoomHandle; \ No newline at end of file diff --git a/src/views/jmap/index.vue b/src/views/jmap/index.vue index 0bef5bff7..31ee4673e 100644 --- a/src/views/jmap/index.vue +++ b/src/views/jmap/index.vue @@ -25,6 +25,7 @@ }, methods: { dataLoaded() { console.log('dataLoaded'); }, + viewLoaded() { console.log('viewLoaded'); }, stateLoaded() { console.log('stateLoaded'); }, stateUpdated() { console.log('stateUpdated'); } } @@ -40,11 +41,9 @@ } } - this.jmap.loadData('01', - { - linkList: list - } - ); + this.jmap.loadData('01', { linkList: list }); + + this.jmap.setDefaultState(); // this.jmap.render([ // {code: '11', type: 'Link', beg: { x: 20 , y: 100}, end: { x: 120, y: 100 }} @@ -58,8 +57,6 @@ // {code: '11', type: 'Link', beg: { x: 0 , y: 0}, end: { x: 200, y: 200 }} // ]); - console.log(this.jmap.mapDevice, this.jmap.proxyData, this.jmap.data); - // this.jmap.update([]); }, methods: {