/** * echarts-gl * Extension pack of ECharts providing 3d plots and globe visualization * * Copyright (c) 2014, echarts-gl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @module echarts-gl * @author Yi Shen(http://github.com/pissang) */ // PENDING Use a single canvas as layer or use image element? var echartsGl = { version: '1.1.1', dependencies: { echarts: '4.1.0', claygl: '1.2.1' } }; import echarts from 'echarts/lib/echarts'; import clayVersion from 'claygl/src/version'; import LayerGL from './core/LayerGL'; import backwardCompat from './preprocessor/backwardCompat'; import graphicGL from './util/graphicGL'; // Version checking var deps = echartsGl.dependencies; function versionTooOldMsg(name) { throw new Error( name + ' version is too old, needs ' + deps[name] + ' or higher' ); } function checkVersion(version, name) { if ((version.replace('.', '') - 0) < (deps[name].replace('.', '') - 0)) { versionTooOldMsg(name); } // console.log('Loaded ' + name + ', version ' + version); } checkVersion(clayVersion, 'claygl'); checkVersion(echarts.version, 'echarts'); function EChartsGL (zr) { this._layers = {}; this._zr = zr; } EChartsGL.prototype.update = function (ecModel, api) { var self = this; var zr = api.getZr(); if (!zr.getWidth() || !zr.getHeight()) { console.warn('Dom has no width or height'); return; } function getLayerGL(model) { var zlevel; // Host on coordinate system. if (model.coordinateSystem && model.coordinateSystem.model) { zlevel = model.get('zlevel'); } else { zlevel = model.get('zlevel'); } var layers = self._layers; var layerGL = layers[zlevel]; if (!layerGL) { layerGL = layers[zlevel] = new LayerGL('gl-' + zlevel, zr); if (zr.painter.isSingleCanvas()) { layerGL.virtual = true; // If container is canvas, use image to represent LayerGL // FIXME Performance var img = new echarts.graphic.Image({ z: 1e4, style: { image: layerGL.renderer.canvas }, silent: true }); layerGL.__hostImage = img; zr.add(img); } zr.painter.insertLayer(zlevel, layerGL); } if (layerGL.__hostImage) { layerGL.__hostImage.setStyle({ width: layerGL.renderer.getWidth(), height: layerGL.renderer.getHeight() }); } return layerGL; } function setSilent(groupGL, silent) { if (groupGL) { groupGL.traverse(function (mesh) { if (mesh.isRenderable && mesh.isRenderable()) { mesh.ignorePicking = mesh.$ignorePicking != null ? mesh.$ignorePicking : silent; } }); } } for (var zlevel in this._layers) { this._layers[zlevel].removeViewsAll(); } ecModel.eachComponent(function (componentType, componentModel) { if (componentType !== 'series') { var view = api.getViewOfComponentModel(componentModel); var coordSys = componentModel.coordinateSystem; // View with __ecgl__ flag is a echarts-gl component. if (view.__ecgl__) { var viewGL; if (coordSys) { if (!coordSys.viewGL) { console.error('Can\'t find viewGL in coordinateSystem of component ' + componentModel.id); return; } viewGL = coordSys.viewGL; } else { if (!componentModel.viewGL) { console.error('Can\'t find viewGL of component ' + componentModel.id); return; } viewGL = coordSys.viewGL; } viewGL = coordSys.viewGL; var layerGL = getLayerGL(componentModel); layerGL.addView(viewGL); view.afterRender && view.afterRender( componentModel, ecModel, api, layerGL ); setSilent(view.groupGL, componentModel.get('silent')); } } }); ecModel.eachSeries(function (seriesModel) { var chartView = api.getViewOfSeriesModel(seriesModel); var coordSys = seriesModel.coordinateSystem; if (chartView.__ecgl__) { if ((coordSys && !coordSys.viewGL) && !chartView.viewGL) { console.error('Can\'t find viewGL of series ' + chartView.id); return; } var viewGL = (coordSys && coordSys.viewGL) || chartView.viewGL; // TODO Check zlevel not same with component of coordinate system ? var layerGL = getLayerGL(seriesModel); layerGL.addView(viewGL); chartView.afterRender && chartView.afterRender( seriesModel, ecModel, api, layerGL ); setSilent(chartView.groupGL, seriesModel.get('silent')); } }); }; // Hack original getRenderedCanvas. Will removed after new echarts released // TODO var oldInit = echarts.init; echarts.init = function () { var chart = oldInit.apply(this, arguments); chart.getZr().painter.getRenderedCanvas = function (opts) { opts = opts || {}; if (this._singleCanvas) { return this._layers[0].dom; } var canvas = document.createElement('canvas'); var dpr = opts.pixelRatio || this.dpr; canvas.width = this.getWidth() * dpr; canvas.height = this.getHeight() * dpr; var ctx = canvas.getContext('2d'); ctx.dpr = dpr; ctx.clearRect(0, 0, canvas.width, canvas.height); if (opts.backgroundColor) { ctx.fillStyle = opts.backgroundColor; ctx.fillRect(0, 0, canvas.width, canvas.height); } var displayList = this.storage.getDisplayList(true); var scope = {}; var zlevel; var self = this; function findAndDrawOtherLayer(smaller, larger) { var zlevelList = self._zlevelList; if (smaller == null) { smaller = -Infinity; } var intermediateLayer; for (var i = 0; i < zlevelList.length; i++) { var z = zlevelList[i]; var layer = self._layers[z]; if (!layer.__builtin__ && z > smaller && z < larger) { intermediateLayer = layer; break; } } if (intermediateLayer && intermediateLayer.renderToCanvas) { ctx.save(); intermediateLayer.renderToCanvas(ctx); ctx.restore(); } } var layer = { ctx: ctx }; for (var i = 0; i < displayList.length; i++) { var el = displayList[i]; if (el.zlevel !== zlevel) { findAndDrawOtherLayer(zlevel, el.zlevel); zlevel = el.zlevel; } this._doPaintEl(el, layer, true, scope); } findAndDrawOtherLayer(zlevel, Infinity); return canvas; }; return chart; }; echarts.registerPostUpdate(function (ecModel, api) { var zr = api.getZr(); var egl = zr.__egl = zr.__egl || new EChartsGL(zr); egl.update(ecModel, api); }); echarts.registerPreprocessor(backwardCompat); echarts.graphicGL = graphicGL; export default EChartsGL;