chartx3d
Version:
Data Visualization Chart Library
246 lines (215 loc) • 8.24 kB
JavaScript
import { global } from 'mmvis';
import { GraphObject, _ } from '../graph';
import { findNearPointX } from "../../../../utils/tools";
import { Vector3, MeshBasicMaterial, MeshLambertMaterial, FrontSide, DoubleSide, MeshPhongMaterial, Color, CatmullRomCurve3 } from 'mmgl/src/index';
let renderOrder = 100;
let __lastPosition = null;
class Line extends GraphObject {
constructor(chart3d, opt) {
super(chart3d);
this.name = 'Line';
this.type = "line";
this._type = "line3d";
this.line = { //线
enabled: 1,
shapeType: "brokenLine",//折线
strokeStyle: null,
lineWidth: 2,
lineType: "solid",
smooth: true
};
this.icon = { //节点
enabled: 1, //是否有
shapeType: "circle",
corner: false, //模式[false || 0 = 都有节点 | true || 1 = 拐角才有节点]
radius: 3, //半径 icon 圆点的半径
fillStyle: '#ffffff',
strokeStyle: null
};
this.area = { //填充
// shapeType : "path",
enabled: 1,
fillStyle: null,
alpha: 0.3
};
_.extend(true, this, opt);
this.init();
}
init() {
this.lineGroup = this._root.app.addGroup({ name: 'line_lines_gruop' });
this.areaGroup = this._root.app.addGroup({ name: 'line_areas_gruop' });
this.nodeGroup = this._root.app.addGroup({ name: 'line_nodes_gruop' });
this.group.add(this.lineGroup);
this.group.add(this.areaGroup);
this.group.add(this.nodeGroup);
}
_getColor(c, dataOrg) {
var color = this._coordSystem.getColor(dataOrg.field);
//field对应的索引,, 取颜色这里不要用i
if (_.isString(c)) {
color = c
};
if (_.isArray(c)) {
color = _.flatten(c)[_.indexOf(_flattenField, field)];
};
if (_.isFunction(c)) {
color = c.apply(this, [rectData]);
};
return color;
}
dataProcess() {
super.dataProcess();
}
draw() {
let me = this;
let app = this._root.app;
this.dataProcess();
const DIVISONS = 200;
for (let field in this.drawData) {
let _color = this._getColor(this.line.strokeStyle, { field: field }) || "red";
let fieldObj = this.drawData[field];
let points = null, bottomPoints = [];
let poses = fieldObj.map(item => {
if (item.vInd > 0) {
bottomPoints.push(item.fromPos);
return new Vector3().copy(item.pos).setY(item.pos.y + item.fromPos.y);
}
return item.pos;
});
if (me.line.smooth) {
let curve = new CatmullRomCurve3(poses);
points = curve.getSpacedPoints(DIVISONS);
if (bottomPoints.length > 0) {
let curve2 = new CatmullRomCurve3(bottomPoints);
bottomPoints = curve2.getSpacedPoints(DIVISONS);
}
} else {
points = poses;
}
let line = app.createBrokenLine(points, this.line.lineWidth, _color, true);
line.visible = !!this.line.enabled;
this.lineGroup.add(line);
//绘制区域
let pointArr = [];
points.forEach(point => {
pointArr = pointArr.concat(point.toArray());
});
if (bottomPoints.length > 0) {
//绘制堆叠区域
for (let i = bottomPoints.length - 1; i >= 0; i--) {
pointArr = pointArr.concat(bottomPoints[i].toArray());
}
} else {
//绘制普通的区域
pointArr.unshift(pointArr[0], 0, pointArr[2]);
pointArr.push(pointArr[(points.length - 1) * 3], 0, pointArr[(points.length - 1) * 3 + 2]);
}
let polygon = app.createPolygonPlane(pointArr, { fillStyle: _color });
polygon.userData = fieldObj;
polygon.visible = !!this.area.enabled;
this.areaGroup.add(polygon);
//绘制node 点
poses.forEach(point => {
//let node = app.createSphere(10,{fillStyle:_color});
let node = app.createCirclePlane(10, { fillStyle: _color });
node.position.copy(point);
node.visible = !!this.icon.enabled
this.nodeGroup.add(node);
});
}
this.bindEvent();
}
bindEvent() {
this.__mousemove = (e) => {
let currObj = e.intersects[0];
let target = e.target;
if (currObj) {
let pos = currObj.point.clone();
let locPos = this._coordSystem.group.worldToLocal(pos);
let positions = target.userData.map(obj => {
if (obj.vInd > 0) {
return new Vector3().copy(obj.pos).setY(obj.pos.y + obj.fromPos.y)
}
return obj.pos;
});
let currPoint = findNearPointX(positions, locPos);
let currInfo = _.find(target.userData, item => {
let _pos = item.pos.clone();
if (item.vInd > 0) {
_pos = new Vector3().copy(item.pos).setY(item.pos.y + item.fromPos.y)
}
return _pos.equals(currPoint);
})
if (!__lastPosition || !currPoint.equals(__lastPosition)) {
//this._showLabel(currInfo);
this._root.fire({
type: 'tipShow',
event: e.event,
data: currInfo
})
__lastPosition = currPoint;
this.fire({ type: 'showLable', data: currInfo });
}
this.fire({ type: 'mousemove' })
// console.log(currPoint);
}
};
this.__mouseout = (e) => {
if (this.textTempGroup) {
// this.textTempGroup.traverse(item => {
// item.on('removed', (e) => {
// this.fire({ type: 'hideLable', data: e.target.userData });
// })
// })
// this.dispose(this.textTempGroup);
}
this._root.fire({
type: 'tipHide',
event: e.event,
data: null
})
this.fire({ type: 'mouseout' });
}
this.areaGroup.traverse(obj => {
obj.on('mousemove', this.__mousemove);
obj.on("mouseout", this.__mouseout);
})
this.on('showLable', (e) => {
this.nodeGroup.traverse(obj => {
if (obj.userData.isScale) {
obj.userData.isScale = false;
obj.scale.multiplyScalar(0.5);
}
let _pos = e.data.pos.clone();
if (e.data.vInd > 0) {
_pos = new Vector3().copy(e.data.pos).setY(e.data.pos.y + e.data.fromPos.y)
}
if (!obj.userData.isScale && obj.position.equals(_pos)) {
obj.userData.isScale = true;
obj.scale.multiplyScalar(2);
}
})
})
this.on('mouseout', (e) => {
this.nodeGroup.traverse(obj => {
if (obj.userData.isScale) {
obj.userData.isScale = false;
obj.scale.multiplyScalar(0.5);
}
})
})
}
dispose() {
this.areaGroup.traverse(obj => {
obj.off('mousemove', this.__mousemove);
obj.off("mouseout", this.__mouseout);
});
super.dispose();
}
resetData() {
this.dispose();
this.draw();
}
}
global.registerComponent(Line, 'graphs', 'line', 3);
export default Line;