573 lines
18 KiB
JavaScript
573 lines
18 KiB
JavaScript
|
|
// TODO orthographic camera
|
||
|
|
import * as echarts from 'echarts/lib/echarts';
|
||
|
|
import { createTextStyle } from 'echarts/lib/label/labelStyle';
|
||
|
|
import graphicGL from '../../util/graphicGL';
|
||
|
|
import OrbitControl from '../../util/OrbitControl';
|
||
|
|
import Lines3DGeometry from '../../util/geometry/Lines3D';
|
||
|
|
import retrieve from '../../util/retrieve';
|
||
|
|
var firstNotNull = retrieve.firstNotNull;
|
||
|
|
import ZRTextureAtlasSurface from '../../util/ZRTextureAtlasSurface';
|
||
|
|
import SceneHelper from '../common/SceneHelper';
|
||
|
|
import Grid3DFace from './Grid3DFace';
|
||
|
|
import Grid3DAxis from './Grid3DAxis';
|
||
|
|
import LabelsMesh from '../../util/mesh/LabelsMesh';
|
||
|
|
import lines3DGLSL from '../../util/shader/lines3D.glsl.js';
|
||
|
|
graphicGL.Shader.import(lines3DGLSL);
|
||
|
|
var dimIndicesMap = {
|
||
|
|
// Left to right
|
||
|
|
x: 0,
|
||
|
|
// Far to near
|
||
|
|
y: 2,
|
||
|
|
// Bottom to up
|
||
|
|
z: 1
|
||
|
|
};
|
||
|
|
export default echarts.ComponentView.extend({
|
||
|
|
type: 'grid3D',
|
||
|
|
__ecgl__: true,
|
||
|
|
init: function (ecModel, api) {
|
||
|
|
var FACES = [// planeDim0, planeDim1, offsetDim, dir on dim3 axis(gl), plane.
|
||
|
|
['y', 'z', 'x', -1, 'left'], ['y', 'z', 'x', 1, 'right'], ['x', 'y', 'z', -1, 'bottom'], ['x', 'y', 'z', 1, 'top'], ['x', 'z', 'y', -1, 'far'], ['x', 'z', 'y', 1, 'near']];
|
||
|
|
var DIMS = ['x', 'y', 'z'];
|
||
|
|
var quadsMaterial = new graphicGL.Material({
|
||
|
|
// transparent: true,
|
||
|
|
shader: graphicGL.createShader('ecgl.color'),
|
||
|
|
depthMask: false,
|
||
|
|
transparent: true
|
||
|
|
});
|
||
|
|
var linesMaterial = new graphicGL.Material({
|
||
|
|
// transparent: true,
|
||
|
|
shader: graphicGL.createShader('ecgl.meshLines3D'),
|
||
|
|
depthMask: false,
|
||
|
|
transparent: true
|
||
|
|
});
|
||
|
|
quadsMaterial.define('fragment', 'DOUBLE_SIDED');
|
||
|
|
quadsMaterial.define('both', 'VERTEX_COLOR');
|
||
|
|
this.groupGL = new graphicGL.Node();
|
||
|
|
this._control = new OrbitControl({
|
||
|
|
zr: api.getZr()
|
||
|
|
});
|
||
|
|
|
||
|
|
this._control.init(); // Save mesh and other infos for each face.
|
||
|
|
|
||
|
|
|
||
|
|
this._faces = FACES.map(function (faceInfo) {
|
||
|
|
var face = new Grid3DFace(faceInfo, linesMaterial, quadsMaterial);
|
||
|
|
this.groupGL.add(face.rootNode);
|
||
|
|
return face;
|
||
|
|
}, this); // Save mesh and other infos for each axis.
|
||
|
|
|
||
|
|
this._axes = DIMS.map(function (dim) {
|
||
|
|
var axis = new Grid3DAxis(dim, linesMaterial);
|
||
|
|
this.groupGL.add(axis.rootNode);
|
||
|
|
return axis;
|
||
|
|
}, this);
|
||
|
|
var dpr = api.getDevicePixelRatio(); // Texture surface for label.
|
||
|
|
|
||
|
|
this._axisLabelSurface = new ZRTextureAtlasSurface({
|
||
|
|
width: 256,
|
||
|
|
height: 256,
|
||
|
|
devicePixelRatio: dpr
|
||
|
|
});
|
||
|
|
|
||
|
|
this._axisLabelSurface.onupdate = function () {
|
||
|
|
api.getZr().refresh();
|
||
|
|
};
|
||
|
|
|
||
|
|
this._axisPointerLineMesh = new graphicGL.Mesh({
|
||
|
|
geometry: new Lines3DGeometry({
|
||
|
|
useNativeLine: false
|
||
|
|
}),
|
||
|
|
material: linesMaterial,
|
||
|
|
castShadow: false,
|
||
|
|
// PENDING
|
||
|
|
ignorePicking: true,
|
||
|
|
renderOrder: 3
|
||
|
|
});
|
||
|
|
this.groupGL.add(this._axisPointerLineMesh);
|
||
|
|
this._axisPointerLabelsSurface = new ZRTextureAtlasSurface({
|
||
|
|
width: 128,
|
||
|
|
height: 128,
|
||
|
|
devicePixelRatio: dpr
|
||
|
|
});
|
||
|
|
this._axisPointerLabelsMesh = new LabelsMesh({
|
||
|
|
ignorePicking: true,
|
||
|
|
renderOrder: 4,
|
||
|
|
castShadow: false
|
||
|
|
});
|
||
|
|
|
||
|
|
this._axisPointerLabelsMesh.material.set('textureAtlas', this._axisPointerLabelsSurface.getTexture());
|
||
|
|
|
||
|
|
this.groupGL.add(this._axisPointerLabelsMesh);
|
||
|
|
this._lightRoot = new graphicGL.Node();
|
||
|
|
this._sceneHelper = new SceneHelper();
|
||
|
|
|
||
|
|
this._sceneHelper.initLight(this._lightRoot);
|
||
|
|
},
|
||
|
|
render: function (grid3DModel, ecModel, api) {
|
||
|
|
this._model = grid3DModel;
|
||
|
|
this._api = api;
|
||
|
|
var cartesian = grid3DModel.coordinateSystem; // Always have light.
|
||
|
|
|
||
|
|
cartesian.viewGL.add(this._lightRoot);
|
||
|
|
|
||
|
|
if (grid3DModel.get('show')) {
|
||
|
|
cartesian.viewGL.add(this.groupGL);
|
||
|
|
} else {
|
||
|
|
cartesian.viewGL.remove(this.groupGL);
|
||
|
|
} // cartesian.viewGL.setCameraType(grid3DModel.get('viewControl.projection'));
|
||
|
|
|
||
|
|
|
||
|
|
var control = this._control;
|
||
|
|
control.setViewGL(cartesian.viewGL);
|
||
|
|
var viewControlModel = grid3DModel.getModel('viewControl');
|
||
|
|
control.setFromViewControlModel(viewControlModel, 0);
|
||
|
|
|
||
|
|
this._axisLabelSurface.clear();
|
||
|
|
|
||
|
|
control.off('update');
|
||
|
|
|
||
|
|
if (grid3DModel.get('show')) {
|
||
|
|
this._faces.forEach(function (face) {
|
||
|
|
face.update(grid3DModel, ecModel, api);
|
||
|
|
}, this);
|
||
|
|
|
||
|
|
this._axes.forEach(function (axis) {
|
||
|
|
axis.update(grid3DModel, this._axisLabelSurface, api);
|
||
|
|
}, this);
|
||
|
|
}
|
||
|
|
|
||
|
|
control.on('update', this._onCameraChange.bind(this, grid3DModel, api), this);
|
||
|
|
|
||
|
|
this._sceneHelper.setScene(cartesian.viewGL.scene);
|
||
|
|
|
||
|
|
this._sceneHelper.updateLight(grid3DModel); // Set post effect
|
||
|
|
|
||
|
|
|
||
|
|
cartesian.viewGL.setPostEffect(grid3DModel.getModel('postEffect'), api);
|
||
|
|
cartesian.viewGL.setTemporalSuperSampling(grid3DModel.getModel('temporalSuperSampling'));
|
||
|
|
|
||
|
|
this._initMouseHandler(grid3DModel);
|
||
|
|
},
|
||
|
|
afterRender: function (grid3DModel, ecModel, api, layerGL) {
|
||
|
|
// Create ambient cubemap after render because we need to know the renderer.
|
||
|
|
// TODO
|
||
|
|
var renderer = layerGL.renderer;
|
||
|
|
|
||
|
|
this._sceneHelper.updateAmbientCubemap(renderer, grid3DModel, api);
|
||
|
|
|
||
|
|
this._sceneHelper.updateSkybox(renderer, grid3DModel, api);
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* showAxisPointer will be triggered by action.
|
||
|
|
*/
|
||
|
|
showAxisPointer: function (grid3dModel, ecModel, api, payload) {
|
||
|
|
this._doShowAxisPointer();
|
||
|
|
|
||
|
|
this._updateAxisPointer(payload.value);
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* hideAxisPointer will be triggered by action.
|
||
|
|
*/
|
||
|
|
hideAxisPointer: function (grid3dModel, ecModel, api, payload) {
|
||
|
|
this._doHideAxisPointer();
|
||
|
|
},
|
||
|
|
_initMouseHandler: function (grid3DModel) {
|
||
|
|
var cartesian = grid3DModel.coordinateSystem;
|
||
|
|
var viewGL = cartesian.viewGL; // TODO xAxis3D.axisPointer.show ?
|
||
|
|
|
||
|
|
if (grid3DModel.get('show') && grid3DModel.get('axisPointer.show')) {
|
||
|
|
viewGL.on('mousemove', this._updateAxisPointerOnMousePosition, this);
|
||
|
|
} else {
|
||
|
|
viewGL.off('mousemove', this._updateAxisPointerOnMousePosition);
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Try find and show axisPointer on the intersect point
|
||
|
|
* of mouse ray with grid plane.
|
||
|
|
*/
|
||
|
|
_updateAxisPointerOnMousePosition: function (e) {
|
||
|
|
// Ignore if mouse is on the element.
|
||
|
|
if (e.target) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
var grid3DModel = this._model;
|
||
|
|
var cartesian = grid3DModel.coordinateSystem;
|
||
|
|
var viewGL = cartesian.viewGL;
|
||
|
|
var ray = viewGL.castRay(e.offsetX, e.offsetY, new graphicGL.Ray());
|
||
|
|
var nearestIntersectPoint;
|
||
|
|
|
||
|
|
for (var i = 0; i < this._faces.length; i++) {
|
||
|
|
var face = this._faces[i];
|
||
|
|
|
||
|
|
if (face.rootNode.invisible) {
|
||
|
|
continue;
|
||
|
|
} // Plane is not face the camera. flip it
|
||
|
|
|
||
|
|
|
||
|
|
if (face.plane.normal.dot(viewGL.camera.worldTransform.z) < 0) {
|
||
|
|
face.plane.normal.negate();
|
||
|
|
}
|
||
|
|
|
||
|
|
var point = ray.intersectPlane(face.plane);
|
||
|
|
|
||
|
|
if (!point) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
var axis0 = cartesian.getAxis(face.faceInfo[0]);
|
||
|
|
var axis1 = cartesian.getAxis(face.faceInfo[1]);
|
||
|
|
var idx0 = dimIndicesMap[face.faceInfo[0]];
|
||
|
|
var idx1 = dimIndicesMap[face.faceInfo[1]];
|
||
|
|
|
||
|
|
if (axis0.contain(point.array[idx0]) && axis1.contain(point.array[idx1])) {
|
||
|
|
nearestIntersectPoint = point;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (nearestIntersectPoint) {
|
||
|
|
var data = cartesian.pointToData(nearestIntersectPoint.array, [], true);
|
||
|
|
|
||
|
|
this._updateAxisPointer(data);
|
||
|
|
|
||
|
|
this._doShowAxisPointer();
|
||
|
|
} else {
|
||
|
|
this._doHideAxisPointer();
|
||
|
|
}
|
||
|
|
},
|
||
|
|
_onCameraChange: function (grid3DModel, api) {
|
||
|
|
if (grid3DModel.get('show')) {
|
||
|
|
this._updateFaceVisibility();
|
||
|
|
|
||
|
|
this._updateAxisLinePosition();
|
||
|
|
}
|
||
|
|
|
||
|
|
var control = this._control;
|
||
|
|
api.dispatchAction({
|
||
|
|
type: 'grid3DChangeCamera',
|
||
|
|
alpha: control.getAlpha(),
|
||
|
|
beta: control.getBeta(),
|
||
|
|
distance: control.getDistance(),
|
||
|
|
center: control.getCenter(),
|
||
|
|
from: this.uid,
|
||
|
|
grid3DId: grid3DModel.id
|
||
|
|
});
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Update visibility of each face when camera view changed, front face will be invisible.
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
_updateFaceVisibility: function () {
|
||
|
|
var camera = this._control.getCamera();
|
||
|
|
|
||
|
|
var viewSpacePos = new graphicGL.Vector3();
|
||
|
|
camera.update();
|
||
|
|
|
||
|
|
for (var idx = 0; idx < this._faces.length / 2; idx++) {
|
||
|
|
var depths = [];
|
||
|
|
|
||
|
|
for (var k = 0; k < 2; k++) {
|
||
|
|
var face = this._faces[idx * 2 + k];
|
||
|
|
face.rootNode.getWorldPosition(viewSpacePos);
|
||
|
|
viewSpacePos.transformMat4(camera.viewMatrix);
|
||
|
|
depths[k] = viewSpacePos.z;
|
||
|
|
} // Set the front face invisible
|
||
|
|
|
||
|
|
|
||
|
|
var frontIndex = depths[0] > depths[1] ? 0 : 1;
|
||
|
|
var frontFace = this._faces[idx * 2 + frontIndex];
|
||
|
|
var backFace = this._faces[idx * 2 + 1 - frontIndex]; // Update rotation.
|
||
|
|
|
||
|
|
frontFace.rootNode.invisible = true;
|
||
|
|
backFace.rootNode.invisible = false;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Update axis line position when camera view changed.
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
_updateAxisLinePosition: function () {
|
||
|
|
// Put xAxis, yAxis on x, y visible plane.
|
||
|
|
// Put zAxis on the left.
|
||
|
|
// TODO
|
||
|
|
var cartesian = this._model.coordinateSystem;
|
||
|
|
var xAxis = cartesian.getAxis('x');
|
||
|
|
var yAxis = cartesian.getAxis('y');
|
||
|
|
var zAxis = cartesian.getAxis('z');
|
||
|
|
var top = zAxis.getExtentMax();
|
||
|
|
var bottom = zAxis.getExtentMin();
|
||
|
|
var left = xAxis.getExtentMin();
|
||
|
|
var right = xAxis.getExtentMax();
|
||
|
|
var near = yAxis.getExtentMax();
|
||
|
|
var far = yAxis.getExtentMin();
|
||
|
|
var xAxisNode = this._axes[0].rootNode;
|
||
|
|
var yAxisNode = this._axes[1].rootNode;
|
||
|
|
var zAxisNode = this._axes[2].rootNode;
|
||
|
|
var faces = this._faces; // Notice: in cartesian up axis is z, but in webgl up axis is y.
|
||
|
|
|
||
|
|
var xAxisZOffset = faces[4].rootNode.invisible ? far : near;
|
||
|
|
var xAxisYOffset = faces[2].rootNode.invisible ? top : bottom;
|
||
|
|
var yAxisXOffset = faces[0].rootNode.invisible ? left : right;
|
||
|
|
var yAxisYOffset = faces[2].rootNode.invisible ? top : bottom;
|
||
|
|
var zAxisXOffset = faces[0].rootNode.invisible ? right : left;
|
||
|
|
var zAxisZOffset = faces[4].rootNode.invisible ? far : near;
|
||
|
|
xAxisNode.rotation.identity();
|
||
|
|
yAxisNode.rotation.identity();
|
||
|
|
zAxisNode.rotation.identity();
|
||
|
|
|
||
|
|
if (faces[4].rootNode.invisible) {
|
||
|
|
this._axes[0].flipped = true;
|
||
|
|
xAxisNode.rotation.rotateX(Math.PI);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (faces[0].rootNode.invisible) {
|
||
|
|
this._axes[1].flipped = true;
|
||
|
|
yAxisNode.rotation.rotateZ(Math.PI);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (faces[4].rootNode.invisible) {
|
||
|
|
this._axes[2].flipped = true;
|
||
|
|
zAxisNode.rotation.rotateY(Math.PI);
|
||
|
|
}
|
||
|
|
|
||
|
|
xAxisNode.position.set(0, xAxisYOffset, xAxisZOffset);
|
||
|
|
yAxisNode.position.set(yAxisXOffset, yAxisYOffset, 0); // Actually z
|
||
|
|
|
||
|
|
zAxisNode.position.set(zAxisXOffset, 0, zAxisZOffset); // Actually y
|
||
|
|
|
||
|
|
xAxisNode.update();
|
||
|
|
yAxisNode.update();
|
||
|
|
zAxisNode.update();
|
||
|
|
|
||
|
|
this._updateAxisLabelAlign();
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Update label align on axis when axisLine position changed.
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
_updateAxisLabelAlign: function () {
|
||
|
|
// var cartesian = this._model.coordinateSystem;
|
||
|
|
var camera = this._control.getCamera();
|
||
|
|
|
||
|
|
var coords = [new graphicGL.Vector4(), new graphicGL.Vector4()];
|
||
|
|
var center = new graphicGL.Vector4();
|
||
|
|
this.groupGL.getWorldPosition(center);
|
||
|
|
center.w = 1.0;
|
||
|
|
center.transformMat4(camera.viewMatrix).transformMat4(camera.projectionMatrix);
|
||
|
|
center.x /= center.w;
|
||
|
|
center.y /= center.w;
|
||
|
|
|
||
|
|
this._axes.forEach(function (axisInfo) {
|
||
|
|
var lineCoords = axisInfo.axisLineCoords;
|
||
|
|
var labelGeo = axisInfo.labelsMesh.geometry;
|
||
|
|
|
||
|
|
for (var i = 0; i < coords.length; i++) {
|
||
|
|
coords[i].setArray(lineCoords[i]);
|
||
|
|
coords[i].w = 1.0;
|
||
|
|
coords[i].transformMat4(axisInfo.rootNode.worldTransform).transformMat4(camera.viewMatrix).transformMat4(camera.projectionMatrix);
|
||
|
|
coords[i].x /= coords[i].w;
|
||
|
|
coords[i].y /= coords[i].w;
|
||
|
|
}
|
||
|
|
|
||
|
|
var dx = coords[1].x - coords[0].x;
|
||
|
|
var dy = coords[1].y - coords[0].y;
|
||
|
|
var cx = (coords[1].x + coords[0].x) / 2;
|
||
|
|
var cy = (coords[1].y + coords[0].y) / 2;
|
||
|
|
var textAlign;
|
||
|
|
var verticalAlign;
|
||
|
|
|
||
|
|
if (Math.abs(dy / dx) < 0.5) {
|
||
|
|
textAlign = 'center';
|
||
|
|
verticalAlign = cy > center.y ? 'bottom' : 'top';
|
||
|
|
} else {
|
||
|
|
verticalAlign = 'middle';
|
||
|
|
textAlign = cx > center.x ? 'left' : 'right';
|
||
|
|
} // axis labels
|
||
|
|
|
||
|
|
|
||
|
|
axisInfo.setSpriteAlign(textAlign, verticalAlign, this._api);
|
||
|
|
}, this);
|
||
|
|
},
|
||
|
|
_doShowAxisPointer: function () {
|
||
|
|
if (!this._axisPointerLineMesh.invisible) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
this._axisPointerLineMesh.invisible = false;
|
||
|
|
this._axisPointerLabelsMesh.invisible = false;
|
||
|
|
|
||
|
|
this._api.getZr().refresh();
|
||
|
|
},
|
||
|
|
_doHideAxisPointer: function () {
|
||
|
|
if (this._axisPointerLineMesh.invisible) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
this._axisPointerLineMesh.invisible = true;
|
||
|
|
this._axisPointerLabelsMesh.invisible = true;
|
||
|
|
|
||
|
|
this._api.getZr().refresh();
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private updateAxisPointer.
|
||
|
|
*/
|
||
|
|
_updateAxisPointer: function (data) {
|
||
|
|
var cartesian = this._model.coordinateSystem;
|
||
|
|
var point = cartesian.dataToPoint(data);
|
||
|
|
var axisPointerLineMesh = this._axisPointerLineMesh;
|
||
|
|
var linesGeo = axisPointerLineMesh.geometry;
|
||
|
|
|
||
|
|
var axisPointerParentModel = this._model.getModel('axisPointer');
|
||
|
|
|
||
|
|
var dpr = this._api.getDevicePixelRatio();
|
||
|
|
|
||
|
|
linesGeo.convertToDynamicArray(true);
|
||
|
|
|
||
|
|
function ifShowAxisPointer(axis) {
|
||
|
|
return retrieve.firstNotNull(axis.model.get('axisPointer.show'), axisPointerParentModel.get('show'));
|
||
|
|
}
|
||
|
|
|
||
|
|
function getAxisColorAndLineWidth(axis) {
|
||
|
|
var axisPointerModel = axis.model.getModel('axisPointer', axisPointerParentModel);
|
||
|
|
var lineStyleModel = axisPointerModel.getModel('lineStyle');
|
||
|
|
var color = graphicGL.parseColor(lineStyleModel.get('color'));
|
||
|
|
var lineWidth = firstNotNull(lineStyleModel.get('width'), 1);
|
||
|
|
var opacity = firstNotNull(lineStyleModel.get('opacity'), 1);
|
||
|
|
color[3] *= opacity;
|
||
|
|
return {
|
||
|
|
color: color,
|
||
|
|
lineWidth: lineWidth
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
for (var k = 0; k < this._faces.length; k++) {
|
||
|
|
var face = this._faces[k];
|
||
|
|
|
||
|
|
if (face.rootNode.invisible) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
var faceInfo = face.faceInfo;
|
||
|
|
var otherCoord = faceInfo[3] < 0 ? cartesian.getAxis(faceInfo[2]).getExtentMin() : cartesian.getAxis(faceInfo[2]).getExtentMax();
|
||
|
|
var otherDimIdx = dimIndicesMap[faceInfo[2]]; // Line on face.
|
||
|
|
|
||
|
|
for (var i = 0; i < 2; i++) {
|
||
|
|
var dim = faceInfo[i];
|
||
|
|
var faceOtherDim = faceInfo[1 - i];
|
||
|
|
var axis = cartesian.getAxis(dim);
|
||
|
|
var faceOtherAxis = cartesian.getAxis(faceOtherDim);
|
||
|
|
|
||
|
|
if (!ifShowAxisPointer(axis)) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
var p0 = [0, 0, 0];
|
||
|
|
var p1 = [0, 0, 0];
|
||
|
|
var dimIdx = dimIndicesMap[dim];
|
||
|
|
var faceOtherDimIdx = dimIndicesMap[faceOtherDim];
|
||
|
|
p0[dimIdx] = p1[dimIdx] = point[dimIdx];
|
||
|
|
p0[otherDimIdx] = p1[otherDimIdx] = otherCoord;
|
||
|
|
p0[faceOtherDimIdx] = faceOtherAxis.getExtentMin();
|
||
|
|
p1[faceOtherDimIdx] = faceOtherAxis.getExtentMax();
|
||
|
|
var colorAndLineWidth = getAxisColorAndLineWidth(axis);
|
||
|
|
linesGeo.addLine(p0, p1, colorAndLineWidth.color, colorAndLineWidth.lineWidth * dpr);
|
||
|
|
} // Project line.
|
||
|
|
|
||
|
|
|
||
|
|
if (ifShowAxisPointer(cartesian.getAxis(faceInfo[2]))) {
|
||
|
|
var p0 = point.slice();
|
||
|
|
var p1 = point.slice();
|
||
|
|
p1[otherDimIdx] = otherCoord;
|
||
|
|
var colorAndLineWidth = getAxisColorAndLineWidth(cartesian.getAxis(faceInfo[2]));
|
||
|
|
linesGeo.addLine(p0, p1, colorAndLineWidth.color, colorAndLineWidth.lineWidth * dpr);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
linesGeo.convertToTypedArray();
|
||
|
|
|
||
|
|
this._updateAxisPointerLabelsMesh(data);
|
||
|
|
|
||
|
|
this._api.getZr().refresh();
|
||
|
|
},
|
||
|
|
_updateAxisPointerLabelsMesh: function (data) {
|
||
|
|
var grid3dModel = this._model;
|
||
|
|
var axisPointerLabelsMesh = this._axisPointerLabelsMesh;
|
||
|
|
var axisPointerLabelsSurface = this._axisPointerLabelsSurface;
|
||
|
|
var cartesian = grid3dModel.coordinateSystem;
|
||
|
|
var axisPointerParentModel = grid3dModel.getModel('axisPointer');
|
||
|
|
axisPointerLabelsMesh.geometry.convertToDynamicArray(true);
|
||
|
|
axisPointerLabelsSurface.clear();
|
||
|
|
var otherDim = {
|
||
|
|
x: 'y',
|
||
|
|
y: 'x',
|
||
|
|
z: 'y'
|
||
|
|
};
|
||
|
|
|
||
|
|
this._axes.forEach(function (axisInfo, idx) {
|
||
|
|
var axis = cartesian.getAxis(axisInfo.dim);
|
||
|
|
var axisModel = axis.model;
|
||
|
|
var axisPointerModel = axisModel.getModel('axisPointer', axisPointerParentModel);
|
||
|
|
var labelModel = axisPointerModel.getModel('label');
|
||
|
|
var lineColor = axisPointerModel.get('lineStyle.color');
|
||
|
|
|
||
|
|
if (!labelModel.get('show') || !axisPointerModel.get('show')) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
var val = data[idx];
|
||
|
|
var formatter = labelModel.get('formatter');
|
||
|
|
var text = axis.scale.getLabel({
|
||
|
|
value: val
|
||
|
|
});
|
||
|
|
|
||
|
|
if (formatter != null) {
|
||
|
|
text = formatter(text, data);
|
||
|
|
} else {
|
||
|
|
if (axis.scale.type === 'interval' || axis.scale.type === 'log') {
|
||
|
|
var precision = echarts.number.getPrecisionSafe(axis.scale.getTicks()[0]);
|
||
|
|
text = val.toFixed(precision + 2);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
var labelColor = labelModel.get('color');
|
||
|
|
var textEl = new echarts.graphic.Text({
|
||
|
|
style: createTextStyle(labelModel, {
|
||
|
|
text: text,
|
||
|
|
fill: labelColor || lineColor,
|
||
|
|
align: 'left',
|
||
|
|
verticalAlign: 'top'
|
||
|
|
})
|
||
|
|
});
|
||
|
|
var coords = axisPointerLabelsSurface.add(textEl);
|
||
|
|
var rect = textEl.getBoundingRect();
|
||
|
|
|
||
|
|
var dpr = this._api.getDevicePixelRatio();
|
||
|
|
|
||
|
|
var pos = axisInfo.rootNode.position.toArray();
|
||
|
|
var otherIdx = dimIndicesMap[otherDim[axisInfo.dim]];
|
||
|
|
pos[otherIdx] += (axisInfo.flipped ? -1 : 1) * labelModel.get('margin');
|
||
|
|
pos[dimIndicesMap[axisInfo.dim]] = axis.dataToCoord(data[idx]);
|
||
|
|
axisPointerLabelsMesh.geometry.addSprite(pos, [rect.width * dpr, rect.height * dpr], coords, axisInfo.textAlign, axisInfo.textVerticalAlign);
|
||
|
|
}, this);
|
||
|
|
|
||
|
|
axisPointerLabelsSurface.getZr().refreshImmediately();
|
||
|
|
axisPointerLabelsMesh.material.set('uvScale', axisPointerLabelsSurface.getCoordsScale());
|
||
|
|
axisPointerLabelsMesh.geometry.convertToTypedArray();
|
||
|
|
},
|
||
|
|
dispose: function () {
|
||
|
|
this.groupGL.removeAll();
|
||
|
|
|
||
|
|
this._control.dispose();
|
||
|
|
|
||
|
|
this._axisLabelSurface.dispose();
|
||
|
|
|
||
|
|
this._axisPointerLabelsSurface.dispose();
|
||
|
|
}
|
||
|
|
});
|