import * as echarts from 'echarts/lib/echarts'; import graphicGL from '../../util/graphicGL'; import ViewGL from '../../core/ViewGL'; import Lines2DGeometry from '../../util/geometry/Lines2D'; import GLViewHelper from '../common/GLViewHelper'; import { getItemVisualColor, getItemVisualOpacity } from '../../util/visual'; import retrieve from '../../util/retrieve'; export default echarts.ChartView.extend({ type: 'linesGL', __ecgl__: true, init: function (ecModel, api) { this.groupGL = new graphicGL.Node(); this.viewGL = new ViewGL('orthographic'); this.viewGL.add(this.groupGL); this._glViewHelper = new GLViewHelper(this.viewGL); this._nativeLinesShader = graphicGL.createShader('ecgl.lines3D'); this._meshLinesShader = graphicGL.createShader('ecgl.meshLines3D'); this._linesMeshes = []; this._currentStep = 0; }, render: function (seriesModel, ecModel, api) { this.groupGL.removeAll(); this._glViewHelper.reset(seriesModel, api); var linesMesh = this._linesMeshes[0]; if (!linesMesh) { linesMesh = this._linesMeshes[0] = this._createLinesMesh(seriesModel); } this._linesMeshes.length = 1; this.groupGL.add(linesMesh); this._updateLinesMesh(seriesModel, linesMesh, 0, seriesModel.getData().count()); this.viewGL.setPostEffect(seriesModel.getModel('postEffect'), api); }, incrementalPrepareRender: function (seriesModel, ecModel, api) { this.groupGL.removeAll(); this._glViewHelper.reset(seriesModel, api); this._currentStep = 0; this.viewGL.setPostEffect(seriesModel.getModel('postEffect'), api); }, incrementalRender: function (params, seriesModel, ecModel, api) { var linesMesh = this._linesMeshes[this._currentStep]; if (!linesMesh) { linesMesh = this._createLinesMesh(seriesModel); this._linesMeshes[this._currentStep] = linesMesh; } this._updateLinesMesh(seriesModel, linesMesh, params.start, params.end); this.groupGL.add(linesMesh); api.getZr().refresh(); this._currentStep++; }, updateTransform: function (seriesModel, ecModel, api) { if (seriesModel.coordinateSystem.getRoamTransform) { this._glViewHelper.updateTransform(seriesModel, api); } }, _createLinesMesh: function (seriesModel) { var linesMesh = new graphicGL.Mesh({ $ignorePicking: true, material: new graphicGL.Material({ shader: graphicGL.createShader('ecgl.lines3D'), transparent: true, depthMask: false, depthTest: false }), geometry: new Lines2DGeometry({ segmentScale: 10, useNativeLine: true, dynamic: false }), mode: graphicGL.Mesh.LINES, culling: false }); return linesMesh; }, _updateLinesMesh: function (seriesModel, linesMesh, start, end) { var data = seriesModel.getData(); linesMesh.material.blend = seriesModel.get('blendMode') === 'lighter' ? graphicGL.additiveBlend : null; var curveness = seriesModel.get('lineStyle.curveness') || 0; var isPolyline = seriesModel.get('polyline'); var geometry = linesMesh.geometry; var coordSys = seriesModel.coordinateSystem; var lineWidth = retrieve.firstNotNull(seriesModel.get('lineStyle.width'), 1); if (lineWidth > 1) { if (linesMesh.material.shader !== this._meshLinesShader) { linesMesh.material.attachShader(this._meshLinesShader); } linesMesh.mode = graphicGL.Mesh.TRIANGLES; } else { if (linesMesh.material.shader !== this._nativeLinesShader) { linesMesh.material.attachShader(this._nativeLinesShader); } linesMesh.mode = graphicGL.Mesh.LINES; } start = start || 0; end = end || data.count(); geometry.resetOffset(); var vertexCount = 0; var triangleCount = 0; var p0 = []; var p1 = []; var p2 = []; var p3 = []; var lineCoords = []; var t = 0.3; var t2 = 0.7; function updateBezierControlPoints() { p1[0] = (p0[0] * t2 + p3[0] * t) - (p0[1] - p3[1]) * curveness; p1[1] = (p0[1] * t2 + p3[1] * t) - (p3[0] - p0[0]) * curveness; p2[0] = (p0[0] * t + p3[0] * t2) - (p0[1] - p3[1]) * curveness; p2[1] = (p0[1] * t + p3[1] * t2) - (p3[0] - p0[0]) * curveness; } if (isPolyline || curveness !== 0) { for (var idx = start; idx < end; idx++) { if (isPolyline) { var count = seriesModel.getLineCoordsCount(idx); vertexCount += geometry.getPolylineVertexCount(count); triangleCount += geometry.getPolylineTriangleCount(count); } else { seriesModel.getLineCoords(idx, lineCoords); this._glViewHelper.dataToPoint(coordSys, lineCoords[0], p0); this._glViewHelper.dataToPoint(coordSys, lineCoords[1], p3); updateBezierControlPoints(); vertexCount += geometry.getCubicCurveVertexCount(p0, p1, p2, p3); triangleCount += geometry.getCubicCurveTriangleCount(p0, p1, p2, p3); } } } else { var lineCount = end - start; vertexCount += lineCount * geometry.getLineVertexCount(); triangleCount += lineCount * geometry.getLineVertexCount(); } geometry.setVertexCount(vertexCount); geometry.setTriangleCount(triangleCount); var dataIndex = start; var colorArr = []; for (var idx = start; idx < end; idx++) { graphicGL.parseColor(getItemVisualColor(data, dataIndex), colorArr); var opacity = retrieve.firstNotNull(getItemVisualOpacity(data, dataIndex), 1); colorArr[3] *= opacity; var count = seriesModel.getLineCoords(idx, lineCoords); for (var k = 0; k < count; k++) { this._glViewHelper.dataToPoint(coordSys, lineCoords[k], lineCoords[k]); } if (isPolyline) { geometry.addPolyline(lineCoords, colorArr, lineWidth, 0, count); } else if (curveness !== 0) { p0 = lineCoords[0]; p3 = lineCoords[1]; updateBezierControlPoints(); geometry.addCubicCurve(p0, p1, p2, p3, colorArr, lineWidth); } else { geometry.addPolyline(lineCoords, colorArr, lineWidth, 0, 2); } dataIndex++; } }, dispose: function () { this.groupGL.removeAll(); }, remove: function () { this.groupGL.removeAll(); } });