增加鼠标处理

This commit is contained in:
ival 2019-07-09 19:04:45 +08:00
parent 7441b41a51
commit 0360b10a79
9 changed files with 264 additions and 80 deletions

View File

@ -1,7 +0,0 @@
class EventController {
constructor(jmap) {
}
}

View File

@ -1,15 +1,28 @@
import * as zrUtil from 'zrender/src/core/util'; import * as zrUtil from 'zrender/src/core/util';
import zrender from 'zrender';
import Painter from './painter'; import Painter from './painter';
import ProxyHandle from './proxyHandle'; import ProxyHandle from './proxyHandle';
import MouseController from './mouseController';
import deviceState from './config/deviceState'; import deviceState from './config/deviceState';
import deviceStyle from './config/deviceStyle'; import deviceStyle from './config/deviceStyle';
import deviceType from './config/deviceType'; import deviceType from './config/deviceType';
import { parser, deviceFactory } from './utils/parser'; import { parser, deviceFactory } from './utils/parser';
const renderer = 'canvas';
const devicePixelRatio = 2;
class Jmap { class Jmap {
constructor(opts) { 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; this.methods = opts.methods;
@ -18,7 +31,7 @@ class Jmap {
this.data = {}; this.data = {};
// 默认初始状态 // 默认初始状态
this.defaultStateDict = this.loaddefaultState(); this.defaultStateDict = this.loadDefaultState();
// 皮肤参数 // 皮肤参数
this.skinStyle = ''; this.skinStyle = '';
@ -29,11 +42,16 @@ class Jmap {
// 设备数据 // 设备数据
this.mapDevice = {}; this.mapDevice = {};
// 设备代理数据 // 代理数据
this.proxyData = {}; 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 * @param {*} data
*/ */
loadData(skinStyle, data) { loadData(skinStyle, data) {
// 保存皮肤类型
this.skinStyle = skinStyle;
// 保存原始数据 // 保存原始数据
this.data = data; this.data = data;
// 加载皮肤 // 加载皮肤
this.styleDict = this.loadStyle(skinStyle); this.styleDict = this.loadStyle(skinStyle);
console.log('开始解析');
// 解析地图数据 // 解析地图数据
this.mapDevice = parser(data, this.defaultStateDict); 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) { loadStyle(skinStyle) {
return deviceStyle; return deviceStyle;
} }
loaddefaultState() { loadDefaultState() {
const defaultStateDict = {}; const defaultStateDict = {};
zrUtil.each(Object.keys(deviceState), (type) => { zrUtil.each(Object.keys(deviceState), (type) => {
@ -81,6 +101,18 @@ class Jmap {
return defaultStateDict; 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) { syncData(model) {
let code = model.code; let code = model.code;
let type = model.type; let type = model.type;
@ -113,7 +145,7 @@ class Jmap {
device = this.proxyData[code] = Object.assign(device, { model }); 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() { getPainter() {
return this.$painter; return this.painter;
}
getEvents() {
return this.events;
} }
getSkinStyle() { getSkinStyle() {
@ -151,11 +191,11 @@ class Jmap {
} }
refresh() { refresh() {
this.$painter.refresh(); this.painter.refresh();
} }
clear() { clear() {
this.$painter.clear(); this.painter.clear();
} }
dispose() { dispose() {
@ -163,7 +203,8 @@ class Jmap {
this.styleDict = {}; this.styleDict = {};
this.mapDevice = {}; this.mapDevice = {};
this.proxyData = {}; this.proxyData = {};
this.$painter.dispose(); this.zr && zrender.dispose(this.zr);
this.painter.dispose();
} }
} }

170
src/jmap/mouseController.js Normal file
View File

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

View File

@ -1,20 +1,13 @@
import zrender from 'zrender';
import * as zrUtil from 'zrender/src/core/util'; import * as zrUtil from 'zrender/src/core/util';
import Group from 'zrender/src/container/Group'; import Group from 'zrender/src/container/Group';
import deviceType from './config/deviceType'; import deviceType from './config/deviceType';
import shapefactory from './shape/factory'; import shapefactory from './shape/factory';
import ZoomController from './zoomController'; import ZoomHandle from './zoomHandle';
const renderer = 'canvas';
const devicePixelRatio = 2;
class Painter { class Painter {
constructor(jamp, opts) { constructor(jamp) {
// 父级实例 // 父级实例
this.$jamp = jamp; this.jmap = jamp;
// zrender实例
this.$zr = null;
// 图层数据 // 图层数据
this.viewLevelMap = {}; this.viewLevelMap = {};
@ -26,24 +19,21 @@ class Painter {
this.parentLevel = null; 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 {*} dom
* @param {*} config * @param {*} config
*/ */
mount(dom, config) { initPainterInstance() {
// 挂载页面视图
this.$zr = zrender.init(dom, config);
// 添加父级图层 // 添加父级图层
this.parentLevel = new Group({ name: '__parent__' }); this.parentLevel = new Group({ name: '__parent__' });
this.$zr.add(this.parentLevel); this.jmap.getZr().add(this.parentLevel);
// 添加子级图层 // 添加子级图层
zrUtil.each(Object.values(deviceType), (type) => { zrUtil.each(Object.values(deviceType), (type) => {
@ -51,9 +41,6 @@ class Painter {
this.viewLevelMap[type] = level; this.viewLevelMap[type] = level;
this.parentLevel.add(level); this.parentLevel.add(level);
}); });
// 视图控制器
this.zoomController = new ZoomController(this);
} }
/** /**
@ -77,9 +64,9 @@ class Painter {
add(device) { add(device) {
const type = device._type; const type = device._type;
const code = device._code; const code = device._code;
const view = shapefactory(type, device, this.$jamp.getStyleDict()); const view = shapefactory(type, device, this.jmap.getStyleDict());
if (view) { if (view) {
this.zoomController.transformView(view); this.zoomHandle.transformView(view);
this.viewInstance[code] = view; this.viewInstance[code] = view;
this.viewLevelMap[type].add(view); this.viewLevelMap[type].add(view);
} }
@ -116,7 +103,7 @@ class Painter {
* @param {*} zoom * @param {*} zoom
*/ */
updateZoomTransform(zoom) { updateZoomTransform(zoom) {
this.zoomController.updateTransform(zoom); this.zoomHandle.updateTransform(zoom);
} }
/** /**
@ -131,7 +118,7 @@ class Painter {
* 刷新画布将在下一个渲染帧的时候被刷新 * 刷新画布将在下一个渲染帧的时候被刷新
*/ */
refresh() { refresh() {
this.$zr && this.$zr.refresh(); this.jmap.getZr() && this.jmap.getZr().refresh();
} }
/** /**
@ -153,10 +140,9 @@ class Painter {
* 销毁 ZRender 实例 * 销毁 ZRender 实例
*/ */
dispose() { dispose() {
this.$zr && zrender.dispose(this.$zr);
this.$zr = null;
this.viewInstance = {}; this.viewInstance = {};
this.viewLevelMap = {}; this.viewLevelMap = {};
this.parentLevel = null;
} }
} }

View File

@ -1,13 +1,13 @@
class ProxyHandle { class ProxyHandle {
constructor(jmap) { constructor(painter) {
this.$painter = jmap.getPainter(); this.painter = painter;
} }
set(target, code, device) { set(target, code, device) {
if (this.$painter.hasViewInstance(code)) { if (this.painter.hasViewInstance(code)) {
this.$painter.update(device); this.painter.update(device);
} else { } else {
this.$painter.add(device); this.painter.add(device);
} }
return Reflect.set(target, code, device); return Reflect.set(target, code, device);
} }
@ -15,18 +15,10 @@ class ProxyHandle {
deleteProperty(target, code) { deleteProperty(target, code) {
let device = target[code]; let device = target[code];
if (device) { if (device) {
this.$painter.delete(target[code]); this.painter.delete(target[code]);
} }
return Reflect.deleteProperty(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; export default ProxyHandle;

View File

@ -1,5 +1,6 @@
import Line from 'zrender/src/graphic/shape/Line'; import Line from 'zrender/src/graphic/shape/Line';
import Group from 'zrender/src/container/Group'; import Group from 'zrender/src/container/Group';
import { stat } from 'fs';
class Link extends Group { class Link extends Group {
constructor({ _code, _type, zlevel, model, state }, style, styleGlobal) { constructor({ _code, _type, zlevel, model, state }, style, styleGlobal) {
@ -44,7 +45,10 @@ class Link extends Group {
} }
setState({ _code, _type, zlevel, model, state }) { 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() { tipBasePoint() {

View File

@ -7,7 +7,8 @@ export function deviceFactory(type, defaultStateDict, elem) {
_type: type, _type: type,
_code: elem.code, _code: elem.code,
model: elem, model: elem,
state: Object.assign({}, defaultStateDict[type]) state: {},
// state: Object.assign({}, defaultStateDict[type])
}, deviceRender[type]); }, deviceRender[type]);
} }

View File

@ -19,12 +19,12 @@ function createBoundingRect(view) {
return rect; return rect;
} }
class ZoomController { class ZoomHandle {
constructor(painter) { constructor(painter) {
this.$zr = painter.$zr; this.zr = painter.jmap.getZr();
this.parentLevel = painter.parentLevel; 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 }); this.transform = createTransform({ scale: 1, offsetX: 0, offsetY: 0 });
} }
@ -74,4 +74,4 @@ class ZoomController {
} }
} }
export default ZoomController; export default ZoomHandle;

View File

@ -25,6 +25,7 @@
}, },
methods: { methods: {
dataLoaded() { console.log('dataLoaded'); }, dataLoaded() { console.log('dataLoaded'); },
viewLoaded() { console.log('viewLoaded'); },
stateLoaded() { console.log('stateLoaded'); }, stateLoaded() { console.log('stateLoaded'); },
stateUpdated() { console.log('stateUpdated'); } stateUpdated() { console.log('stateUpdated'); }
} }
@ -40,11 +41,9 @@
} }
} }
this.jmap.loadData('01', this.jmap.loadData('01', { linkList: list });
{
linkList: list this.jmap.setDefaultState();
}
);
// this.jmap.render([ // this.jmap.render([
// {code: '11', type: 'Link', beg: { x: 20 , y: 100}, end: { x: 120, y: 100 }} // {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 }} // {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([]); // this.jmap.update([]);
}, },
methods: { methods: {