├── .gitignore ├── .vscode └── settings.json ├── README.md ├── demo ├── largeBar.json ├── largeLine.json ├── largeLineSampling.json ├── main.js └── normal.json ├── dist ├── EchartsAdaptor.js ├── EchartsAdaptor.js.map ├── FallbackEcharts.js ├── FallbackEcharts.js.map ├── IEcharts.js ├── IEcharts.js.map ├── OffscreenEcharts.js ├── OffscreenEcharts.js.map ├── SafeJson.js ├── SafeJson.js.map ├── echarts.js ├── renderer.worker.js └── renderer.worker.js.map ├── index.html ├── package.json ├── patch.diff ├── src ├── EchartsAdaptor.ts ├── FallbackEcharts.ts ├── IEcharts.ts ├── OffscreenEcharts.ts ├── SafeJson.ts ├── echarts.d.ts ├── echarts.js ├── renderer.worker.ts └── types.d.ts ├── tsconfig.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib" 3 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OffscreenEcharts 2 | 3 | Echarts with OffscreenCanvas 4 | 5 | * Echarts: https://github.com/apache/incubator-echarts 6 | 7 | * OffscreenCanvas: https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas 8 | 9 | * Original issue: https://github.com/apache/incubator-echarts/issues/9232 10 | 11 | * Supported browser: https://caniuse.com/#feat=offscreencanvas 12 | 13 | * Ref: https://segmentfault.com/a/1190000012563475 14 | 15 | ## How does it work 16 | 17 | 1. A canvas cannot be used directly in worker, but OffscreenCanvas [can be used as a handle](https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas#Asynchronous_display_of_frames_produced_by_an_OffscreenCanvas) to control it. 18 | 1. All rendering is done in worker. `Echarts` has pretty well worker support, with a few exceptions. Patched below. 19 | 1. Mouse events are bind on the canvas in UI thread. When triggered, necessary event data is sent into worker using `postMessage`, then dispatches the event to echarts instance using its internal API. See https://github.com/ecomfe/zrender/pull/448#issuecomment-692451904 20 | 1. All methods are dispatched into worker using `postMessage`, and return a promise immediately. After the method is called in worker, send its return value back to UI thread using `postMessage`, and then resolve the promise. See https://github.com/CarterLi/ThreadPool.js 21 | 1. All Echarts events are bound in worker, and send event data back to UI thread when triggered. In UI thread, `DocumentFragment` is used as an event bus. 22 | 23 | ## Modify Echarts source code 24 | 25 | 1. Add `&& !env.worker` to disable hoverLayerThreshold in worker. See https://github.com/apache/incubator-echarts/issues/13164 26 | 1. Modify `SaveAsImage.prototype.onclick` to let it support `OffscreenCanvas` 27 | 1. Optional: Remove UMD sh*t 28 | 1. Optional: Modify `tooltip.init` to let it accept a customized `TooltipContent` implementation 29 | 30 | See `patch.diff` 31 | 32 | ## Known issues 33 | 34 | 1. [DataView](https://www.echartsjs.com/option.html#toolbox.feature.dataView) because it operates DOM ( won't fix because few people use it ) 35 | 1. [Group](https://echarts.apache.org/zh/api.html#echartsInstance.group) doesn't work (yet) 36 | 37 | ## Demo 38 | 39 | See Github Page: https://carterli.github.io/echarts-with-offscreencanvas/ 40 | 41 | Support Chrome 80+ ( due to using of module scripts on worker ). Fallback version support Safari & Firefox 67 ( because older FireFox versions and Edge lack [dynamic import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports) support ) 42 | -------------------------------------------------------------------------------- /demo/main.js: -------------------------------------------------------------------------------- 1 | const delay = duration => new Promise(resolve => setTimeout(resolve, duration)); 2 | 3 | import { getEchartsAdaptor, getOffscreenCanvasSupport } from '../dist/EchartsAdaptor.js'; 4 | 5 | async function startRender() { 6 | const forceFallback = document.getElementById('forceFallback').checked; 7 | const EchartsAdaptor = await getEchartsAdaptor(forceFallback); 8 | const echarts = new EchartsAdaptor(); 9 | const div = document.getElementById('content'); 10 | div.style.cssText = 'width: 1366px; height: 768px'; 11 | await echarts.init(div); 12 | function showLoading(loading = true) { 13 | if (loading) { 14 | return echarts.callMethod('showLoading', { 15 | text: '努力加载中', 16 | color: '#c23531', 17 | textColor: '#04beb4', 18 | maskColor: 'rgba(255, 255, 255, 0)', 19 | }); 20 | } else { 21 | return echarts.callMethod('hideLoading'); 22 | } 23 | } 24 | async function loadData() { 25 | const file = document.getElementById('dataOption').value; 26 | await showLoading(); 27 | const options = await fetch('demo/' + file).then(res => res.json()); 28 | await echarts.setOption(options, true); 29 | await showLoading(false); 30 | } 31 | document.getElementById('loadData').onclick = loadData; 32 | 33 | await showLoading(); 34 | await delay(1000); 35 | await loadData(); 36 | 37 | const events = []; 38 | document.getElementById('addEvent').onclick = async () => { 39 | events.push(await echarts.on('click', e => console.log(e))); 40 | }; 41 | document.getElementById('delEvent').onclick = () => { 42 | echarts.off(events.pop()); 43 | }; 44 | }; 45 | 46 | void function main() { 47 | if (!getOffscreenCanvasSupport()) { 48 | document.getElementById('explain').textContent = '您的浏览器不支持 OffscreenCanvas,将自动降级至主线程渲染'; 49 | document.getElementById('forceFallback').disabled = true; 50 | document.getElementById('forceFallback').checked = true; 51 | } else { 52 | document.getElementById('explain').textContent = '您的浏览器支持 OffscreenCanvas,可使用辅助线程渲染图表'; 53 | } 54 | document.getElementById('start').onclick = () => { 55 | document.getElementById('startField').disabled = true; 56 | document.getElementById('optionField').disabled = false; 57 | startRender(); 58 | }; 59 | 60 | let lastTime = 0, fps = document.getElementById('fps'); 61 | requestAnimationFrame(function run(t) { 62 | fps.textContent = (1000 / (t - lastTime)).toFixed(3) + ' FPS'; 63 | lastTime = t; 64 | requestAnimationFrame(run); 65 | }); 66 | }(); 67 | -------------------------------------------------------------------------------- /demo/normal.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": { 3 | "text": "未来一周气温变化", 4 | "subtext": "纯属虚构" 5 | }, 6 | "tooltip": { 7 | "trigger": "axis", 8 | "appendToBody": true 9 | }, 10 | "legend": { 11 | "data": [ 12 | "最高气温", 13 | "最低气温" 14 | ] 15 | }, 16 | "toolbox": { 17 | "show": true, 18 | "feature": { 19 | "dataZoom": { 20 | "yAxisIndex": "none" 21 | }, 22 | "dataView": { 23 | "readOnly": false 24 | }, 25 | "magicType": { 26 | "type": [ 27 | "line", 28 | "bar" 29 | ] 30 | }, 31 | "restore": {}, 32 | "saveAsImage": {} 33 | } 34 | }, 35 | "xAxis": { 36 | "type": "category", 37 | "boundaryGap": false, 38 | "data": [ 39 | "周一", 40 | "周二", 41 | "周三", 42 | "周四", 43 | "周五", 44 | "周六", 45 | "周日" 46 | ] 47 | }, 48 | "yAxis": { 49 | "type": "value", 50 | "axisLabel": { 51 | "formatter": "{value} °C" 52 | } 53 | }, 54 | "series": [ 55 | { 56 | "name": "最高气温", 57 | "type": "line", 58 | "data": [ 59 | 11, 60 | 11, 61 | 15, 62 | 13, 63 | 12, 64 | 13, 65 | 10 66 | ], 67 | "markPoint": { 68 | "data": [ 69 | { 70 | "type": "max", 71 | "name": "最大值" 72 | }, 73 | { 74 | "type": "min", 75 | "name": "最小值" 76 | } 77 | ] 78 | }, 79 | "markLine": { 80 | "data": [ 81 | { 82 | "type": "average", 83 | "name": "平均值" 84 | } 85 | ] 86 | } 87 | }, 88 | { 89 | "name": "最低气温", 90 | "type": "line", 91 | "data": [ 92 | 1, 93 | -2, 94 | 2, 95 | 5, 96 | 3, 97 | 2, 98 | 0 99 | ], 100 | "markPoint": { 101 | "data": [ 102 | { 103 | "name": "周最低", 104 | "value": -2, 105 | "xAxis": 1, 106 | "yAxis": -1.5 107 | } 108 | ] 109 | }, 110 | "markLine": { 111 | "data": [ 112 | { 113 | "type": "average", 114 | "name": "平均值" 115 | }, 116 | [ 117 | { 118 | "symbol": "none", 119 | "x": "90%", 120 | "yAxis": "max" 121 | }, 122 | { 123 | "symbol": "circle", 124 | "label": { 125 | "normal": { 126 | "position": "start", 127 | "formatter": "最大值" 128 | } 129 | }, 130 | "type": "max", 131 | "name": "最高点" 132 | } 133 | ] 134 | ] 135 | } 136 | } 137 | ] 138 | } 139 | -------------------------------------------------------------------------------- /dist/EchartsAdaptor.js: -------------------------------------------------------------------------------- 1 | export function getOffscreenCanvasSupport() { 2 | if (typeof OffscreenCanvas === 'function') { 3 | try { 4 | const offscreen = new OffscreenCanvas(32, 32); 5 | return !!offscreen.getContext('2d'); 6 | } 7 | catch { } 8 | } 9 | return false; 10 | } 11 | export async function getEchartsAdaptor(forceFallback = false) { 12 | if (!forceFallback && getOffscreenCanvasSupport()) { 13 | const { OffscreenEcharts } = await import('./OffscreenEcharts.js'); 14 | return OffscreenEcharts; 15 | } 16 | else { 17 | const { FallbackEcharts } = await import('./FallbackEcharts.js'); 18 | return FallbackEcharts; 19 | } 20 | } 21 | //# sourceMappingURL=EchartsAdaptor.js.map -------------------------------------------------------------------------------- /dist/EchartsAdaptor.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"EchartsAdaptor.js","sourceRoot":"","sources":["../src/EchartsAdaptor.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,yBAAyB;IACvC,IAAI,OAAO,eAAe,KAAK,UAAU,EAAE;QACzC,IAAI;YACF,MAAM,SAAS,GAAG,IAAI,eAAe,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YAC9C,OAAO,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;SACrC;QAAC,MAAM,GAAE;KACX;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,aAAa,GAAG,KAAK;IAC3D,IAAI,CAAC,aAAa,IAAI,yBAAyB,EAAE,EAAE;QACjD,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;QACnE,OAAO,gBAAgB,CAAC;KACzB;SAAM;QACL,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;QACjE,OAAO,eAAe,CAAC;KACxB;AACH,CAAC"} -------------------------------------------------------------------------------- /dist/FallbackEcharts.js: -------------------------------------------------------------------------------- 1 | import echarts from './echarts.js'; 2 | export class FallbackEcharts { 3 | constructor() { 4 | this._plot = null; 5 | } 6 | async registerTheme(name, theme) { 7 | echarts.registerTheme(name, theme); 8 | } 9 | async on(type, listener) { 10 | this._plot.on(type, listener); 11 | return { type, listener }; 12 | } 13 | async off(indicator) { 14 | if (!indicator.type) 15 | return; 16 | this._plot.off(indicator.type, indicator.listener); 17 | indicator.type = null; 18 | indicator.listener = null; 19 | } 20 | async init(el, theme) { 21 | this._plot = echarts.init(el, theme); 22 | } 23 | async callMethod(methodName, ...args) { 24 | return this._plot[methodName](...args); 25 | } 26 | async setOption(option, ...args) { 27 | return this._plot.setOption(option, ...args); 28 | } 29 | async dispatchAction(payload) { 30 | return this._plot.dispatchAction(payload); 31 | } 32 | async resize(opts) { 33 | this._plot.resize(opts); 34 | } 35 | dispose() { 36 | this._plot.dispose(); 37 | } 38 | } 39 | //# sourceMappingURL=FallbackEcharts.js.map -------------------------------------------------------------------------------- /dist/FallbackEcharts.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"FallbackEcharts.js","sourceRoot":"","sources":["../src/FallbackEcharts.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AAGnC,MAAM,OAAO,eAAe;IAA5B;QACU,UAAK,GAAoB,IAAI,CAAC;IA0CxC,CAAC;IAxCC,KAAK,CAAC,aAAa,CAAC,IAAY,EAAE,KAA0B;QAC1D,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,EAAE,CAAC,IAAY,EAAE,QAAgC;QACrD,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC9B,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,SAAyD;QACjE,IAAI,CAAC,SAAS,CAAC,IAAI;YAAE,OAAO;QAE5B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;QACnD,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC;QACtB,SAAS,CAAC,QAAQ,GAAG,IAAI,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAkB,EAAE,KAAa;QAC1C,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,UAAkB,EAAE,GAAG,IAAW;QACjD,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,MAA2B,EAAE,GAAG,IAAW;QACzD,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,OAA4B;QAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAkC;QAC7C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO;QACL,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;IACvB,CAAC;CACF"} -------------------------------------------------------------------------------- /dist/IEcharts.js: -------------------------------------------------------------------------------- 1 | export {}; 2 | //# sourceMappingURL=IEcharts.js.map -------------------------------------------------------------------------------- /dist/IEcharts.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"IEcharts.js","sourceRoot":"","sources":["../src/IEcharts.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /dist/OffscreenEcharts.js: -------------------------------------------------------------------------------- 1 | import { stringify } from './SafeJson.js'; 2 | import echarts from './echarts.js'; 3 | function copyByKeys(data, keys) { 4 | const result = {}; 5 | keys.forEach(x => { 6 | if (x in data) 7 | result[x] = data[x]; 8 | }); 9 | return result; 10 | } 11 | const mouseEventKeys = [ 12 | 'zrX', 'zrY', 'zrDelta', 'which', 'button', 13 | ]; 14 | const mouseEventNames = [ 15 | 'click', 'dblclick', 'mousewheel', 'mouseout', 16 | 'mouseup', 'mousedown', 'contextmenu', 17 | ]; 18 | export class OffscreenEcharts { 19 | constructor() { 20 | this._worker = new Worker('dist/renderer.worker.js', { type: 'module' }); 21 | this._eventTarget = document.createDocumentFragment(); 22 | this._eventsMap = {}; 23 | this._promise = Promise.resolve(undefined); 24 | this._worker.addEventListener('message', e => { 25 | console.assert(Array.isArray(e.data), 'Unknown message type posted: ', e); 26 | const [msgType, data] = e.data; 27 | switch (msgType) { 28 | case 'event': { 29 | const { type } = data; 30 | delete data.type; 31 | this._eventTarget.dispatchEvent(Object.assign(new Event(type), data)); 32 | break; 33 | } 34 | case 'open': { 35 | open(...data); 36 | break; 37 | } 38 | case 'saveAsImage': { 39 | const $a = document.createElement('a'); 40 | $a.download = `${data.title}.${data.type}`; 41 | $a.target = '_blank'; 42 | $a.href = this._canvas.toDataURL('image/' + data.type); 43 | $a.click(); 44 | break; 45 | } 46 | case 'tooltip': { 47 | const { type, param } = data; 48 | switch (type) { 49 | case 'init': { 50 | const container = this._canvas.parentElement; 51 | const div = this._tooltip = document.createElement('div'); 52 | const appendToBody = param.appendToBody; 53 | Object.assign(div.style, { 54 | position: 'absolute', 55 | left: 0, 56 | top: 0, 57 | zIndex: 9999999, 58 | display: 'none', 59 | whiteSpace: 'pre-wrap', 60 | transitionProperty: 'transform', 61 | transitionTimingFunction: 'cubic-bezier(0.23, 1, 0.32, 1)', 62 | borderRadius: '4px', 63 | borderStyle: 'solid', 64 | pointerEvents: 'none', 65 | contain: 'content', 66 | }); 67 | if (appendToBody) { 68 | document.body.append(div); 69 | } 70 | else { 71 | container.style.position = 'relative'; 72 | container.appendChild(div); 73 | } 74 | break; 75 | } 76 | case 'show': { 77 | const div = this._tooltip; 78 | Object.assign(div.style, param); 79 | if (this._tooltip.parentElement !== document.body) { 80 | div.style.display = 'block'; 81 | } 82 | if (param.extraCssText) { 83 | div.style.cssText += param.extraCssText; 84 | } 85 | break; 86 | } 87 | case 'setContent': 88 | this._tooltip.innerHTML = param; 89 | break; 90 | case 'moveTo': 91 | const { style } = this._tooltip; 92 | if (this._tooltip.parentElement === document.body) { 93 | const container = this._canvas.parentElement; 94 | const { left, top } = container.getBoundingClientRect(); 95 | style.display = 'block'; 96 | style.transform = `translate(${left + param[0]}px, ${top + param[1]}px)`; 97 | } 98 | else { 99 | style.transform = `translate(${param[0]}px, ${param[1]}px)`; 100 | } 101 | break; 102 | case 'hide': 103 | this._tooltip.style.display = 'none'; 104 | break; 105 | case 'dispose': 106 | this._tooltip.remove(); 107 | this._tooltip = null; 108 | break; 109 | } 110 | break; 111 | } 112 | case 'setCursor': { 113 | this._canvas.style.cursor = data; 114 | } 115 | } 116 | }); 117 | } 118 | registerTheme(name, theme) { 119 | return this.postMessage({ 120 | type: 'registerTheme', 121 | args: [name, JSON.stringify(theme)], 122 | }); 123 | } 124 | async on(type, listener) { 125 | if (!this._eventsMap[type]) { 126 | this._eventsMap[type] = 0; 127 | await this.postMessage({ 128 | type: 'addEventListener', 129 | args: [type], 130 | }); 131 | } 132 | console.assert(this._eventsMap[type] >= 0, 'Something must be wrong'); 133 | this._eventTarget.addEventListener(type, listener); 134 | ++this._eventsMap[type]; 135 | return { type, listener }; 136 | } 137 | async off(indicator) { 138 | if (!indicator.type) 139 | return; 140 | const { type, listener } = indicator; 141 | if (this._eventsMap[type] === 1) { 142 | await this.postMessage({ 143 | type: 'removeEventListener', 144 | args: [type], 145 | }); 146 | } 147 | console.assert(this._eventsMap[type] > 0, 'Something must be wrong'); 148 | this._eventTarget.removeEventListener(type, listener); 149 | indicator.type = null; 150 | indicator.listener = null; 151 | --this._eventsMap[type]; 152 | } 153 | async init(div, theme) { 154 | const canvas = this._canvas = document.createElement('canvas'); 155 | canvas.style.cssText = 'width: 100%; height: 100%; margin: 0; user-select: none; border: 0;'; 156 | canvas.width = div.clientWidth; 157 | canvas.height = div.clientHeight; 158 | div.appendChild(canvas); 159 | const offscreen = canvas.transferControlToOffscreen(); 160 | await this.postMessage({ 161 | type: 'init', 162 | args: [offscreen, theme, { devicePixelRatio }], 163 | }, [offscreen]); 164 | // In order not to push too many (mousemove) events in queue, 165 | // we will prevent new events from responding before 166 | // previous event is handled. 167 | let blockEvent = false; 168 | canvas.addEventListener('mousemove', e => { 169 | if (blockEvent) { 170 | console.warn('Blocking mousemove event', e); 171 | return; 172 | } 173 | blockEvent = true; 174 | this.postMessage({ 175 | type: 'event', 176 | args: [e.type, copyByKeys(echarts.normalizeEvent(this._canvas, e), mouseEventKeys)], 177 | }).then(() => blockEvent = false); 178 | }, { passive: true }); 179 | mouseEventNames.forEach(eventType => { 180 | canvas.addEventListener(eventType, (e) => { 181 | this.postMessage({ 182 | type: 'event', 183 | args: [e.type, copyByKeys(echarts.normalizeEvent(this._canvas, e), mouseEventKeys)], 184 | }); 185 | }, { passive: true }); 186 | }); 187 | } 188 | callMethod(methodName, ...args) { 189 | return this.postMessage({ 190 | type: 'callMethod', 191 | args: [methodName, ...args], 192 | }); 193 | } 194 | setOption(option, ...args) { 195 | return this.postMessage({ 196 | type: 'setOption', 197 | args: [stringify(option, /^[\$_]/), ...args], 198 | }); 199 | } 200 | dispatchAction(payload) { 201 | return this.callMethod('dispatchAction', payload); 202 | } 203 | resize(opts) { 204 | return this.callMethod('resize', opts); 205 | } 206 | dispose() { 207 | // It's an noop of dispose method in worker 208 | this._worker.terminate(); 209 | this._tooltip?.remove(); 210 | } 211 | /** Post message into worker thread; returned promise is resolved when get message back */ 212 | postMessage(message, transfer) { 213 | // eslint-disable-next-line arrow-body-style, @typescript-eslint/no-empty-function 214 | return this._promise = this._promise.catch(() => { }).then(() => { 215 | return new Promise((resolve, reject) => { 216 | this._worker.addEventListener('message', function onMessage(e) { 217 | console.assert(Array.isArray(e.data), 'Unknown message type posted: ', e); 218 | const [type, data] = e.data; 219 | switch (type) { 220 | case 'resolve': { 221 | resolve(data); 222 | this.removeEventListener('message', onMessage); 223 | break; 224 | } 225 | case 'reject': { 226 | reject(data); 227 | this.removeEventListener('message', onMessage); 228 | break; 229 | } 230 | case 'error': { 231 | const [name, msg, stack] = data; 232 | const error = new self[name](msg); 233 | error.stack = stack; 234 | reject(error); 235 | this.removeEventListener('message', onMessage); 236 | break; 237 | } 238 | } 239 | }); 240 | this._worker.postMessage(message, transfer); 241 | }); 242 | }); 243 | } 244 | } 245 | //# sourceMappingURL=OffscreenEcharts.js.map -------------------------------------------------------------------------------- /dist/OffscreenEcharts.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"OffscreenEcharts.js","sourceRoot":"","sources":["../src/OffscreenEcharts.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/SafeJson.js: -------------------------------------------------------------------------------- 1 | class ValueWrapper { 2 | constructor(value) { 3 | this.value = value; 4 | } 5 | } 6 | function* iterateObject(obj) { 7 | for (const key in obj) { 8 | if (obj.hasOwnProperty(key)) { 9 | yield [key, obj[key]]; 10 | } 11 | } 12 | } 13 | export function stringify(value, excludePattern) { 14 | const date2json = Date.prototype.toJSON; // trap 15 | Date.prototype.toJSON = function toJSON() { 16 | return { '\0dt': new ValueWrapper(+this) }; 17 | }; 18 | const json = JSON.stringify(value, (key, val) => { 19 | if (!val) 20 | return val; 21 | if (key.startsWith('\0')) { 22 | if (val instanceof ValueWrapper) { 23 | return val.value; 24 | } 25 | return undefined; 26 | } 27 | if (excludePattern?.test(key)) { 28 | return undefined; 29 | } 30 | if (typeof val === 'number') { 31 | if (Number.isNaN(val) || !Number.isFinite(val)) { 32 | return { '\0num': new ValueWrapper(val + '') }; 33 | } 34 | else { 35 | return val; 36 | } 37 | } 38 | if (typeof val === 'object') { 39 | const type = Object.prototype.toString.call(val).slice(8, -1); 40 | switch (type) { 41 | case 'Error': 42 | return { '\0err': new ValueWrapper([val.name, val.message, val.stack]) }; 43 | case 'Int8Array': 44 | case 'Uint8Array': 45 | case 'Uint8ClampedArray': 46 | case 'Int16Array': 47 | case 'Uint16Array': 48 | case 'Int32Array': 49 | case 'Uint32Array': 50 | case 'Float32Array': 51 | case 'Float64Array': 52 | case 'Map': 53 | case 'Set': 54 | return { '\0arr': new ValueWrapper([type, Array.from(val)]) }; 55 | } 56 | } 57 | if (typeof val === 'function') { 58 | return { '\0fn': new ValueWrapper(val + '') }; 59 | } 60 | return val; 61 | }); 62 | Date.prototype.toJSON = date2json; 63 | return json; 64 | } 65 | export function parse(json) { 66 | return JSON.parse(json, (key, obj) => { 67 | if (obj && typeof obj === 'object' && !Array.isArray(obj)) { 68 | for (const [type, data] of iterateObject(obj)) { 69 | if (type.charCodeAt(0) === 0) { 70 | switch (type.slice(1)) { 71 | case 'dt': return new Date(data); 72 | case 'fn': { 73 | let body = data; 74 | const matched = /^function\W\(\) { \[native code\] }$/.exec(body); 75 | if (matched) 76 | return self[matched[1]]; 77 | // Object member function doesn't start with `function` eg `{ f() {} }` 78 | if (!/^function\W|=>/.test(body)) 79 | body = 'function ' + body; 80 | // eslint-disable-next-line @typescript-eslint/no-implied-eval 81 | return new Function(`"use strict"\nreturn (${body})`)(); 82 | } 83 | case 'num': return +data; 84 | case 'err': { 85 | const [name, message, stack] = data; 86 | const error = new self[name](message); 87 | error.stack = stack; 88 | return error; 89 | } 90 | case 'arr': return new self[data[0]](data[1]); 91 | } 92 | } 93 | return obj; 94 | } 95 | } 96 | return obj; 97 | }); 98 | } 99 | //# sourceMappingURL=SafeJson.js.map -------------------------------------------------------------------------------- /dist/SafeJson.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"SafeJson.js","sourceRoot":"","sources":["../src/SafeJson.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/echarts.js: -------------------------------------------------------------------------------- 1 | ../src/echarts.js -------------------------------------------------------------------------------- /dist/renderer.worker.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-classes-per-file */ 2 | import { parse } from './SafeJson.js'; 3 | import echarts from './echarts.js'; 4 | echarts.setCanvasCreator(() => new OffscreenCanvas(32, 32)); 5 | const ctx = self; 6 | class TooltipContent { 7 | constructor(param) { 8 | this._isShow = false; 9 | ctx.postMessage(['tooltip', { 10 | type: 'init', 11 | param, 12 | }]); 13 | } 14 | update() { 15 | // empty 16 | } 17 | show(tooltipModel) { 18 | this._isShow = true; 19 | const textStyleModel = tooltipModel.getModel('textStyle'); 20 | ctx.postMessage(['tooltip', { 21 | type: 'show', 22 | param: { 23 | transitionDuration: tooltipModel.get('transitionDuration') + 's', 24 | backgroundColor: tooltipModel.get('backgroundColor'), 25 | color: textStyleModel.getTextColor(), 26 | font: textStyleModel.getFont(), 27 | fontSize: textStyleModel.get('fontSize') + 'px', 28 | textDecoration: textStyleModel.get('decoration'), 29 | textAlign: textStyleModel.get('align'), 30 | padding: tooltipModel.get('padding') + 'px', 31 | borderColor: tooltipModel.get('borderColor'), 32 | borderWidth: tooltipModel.get('borderWidth'), 33 | extraCssText: tooltipModel.get('extraCssText'), 34 | }, 35 | }]); 36 | } 37 | setContent(content) { 38 | ctx.postMessage(['tooltip', { 39 | type: 'setContent', 40 | param: content, 41 | }]); 42 | } 43 | setEnterable(_enterable) { 44 | // unimplemented 45 | } 46 | getSize() { 47 | return [0, 0]; 48 | } 49 | moveTo(zrX, zrY) { 50 | ctx.postMessage(['tooltip', { 51 | type: 'moveTo', 52 | param: [zrX, zrY], 53 | }]); 54 | } 55 | hide() { 56 | if (this._isShow) { 57 | this._isShow = false; 58 | ctx.postMessage(['tooltip', { 59 | type: 'hide', 60 | }]); 61 | } 62 | } 63 | hideLater(_time) { 64 | if (this._isShow) { 65 | setTimeout(() => this.hide(), _time); 66 | } 67 | } 68 | isShow() { 69 | return this._isShow; 70 | } 71 | dispose() { 72 | ctx.postMessage(['tooltip', { 73 | type: 'dispose', 74 | }]); 75 | } 76 | getOuterSize() { 77 | return [0, 0]; 78 | } 79 | } 80 | TooltipContent.newLine = '\n'; 81 | const events = new class WorkerEventHandler { 82 | constructor() { 83 | this.plot = null; 84 | } 85 | init(canvas, theme, opts) { 86 | if (this.plot) 87 | throw new Error('Has been initialized'); 88 | ctx.devicePixelRatio = opts.devicePixelRatio; 89 | const plot = this.plot = echarts.init(canvas, theme, opts); 90 | plot._api.saveAsImage = (args) => { 91 | ctx.postMessage(['saveAsImage', args]); 92 | }; 93 | plot.getZr().handler.proxy.setCursor = (cursorStyle) => { 94 | ctx.postMessage(['setCursor', cursorStyle]); 95 | }; 96 | } 97 | registerTheme(name, theme) { 98 | echarts.registerTheme(name, JSON.parse(theme)); 99 | } 100 | addEventListener(type) { 101 | this.plot.off(type); 102 | return this.plot.on(type, params => { 103 | params.event = undefined; 104 | ctx.postMessage(['event', params]); 105 | }); 106 | } 107 | removeEventListener(type) { 108 | return this.plot.off(type); 109 | } 110 | event(type, eventInitDict) { 111 | return this.plot.getZr().handler.dispatch(type, eventInitDict); 112 | } 113 | callMethod(methodName, ...args) { 114 | return this.plot[methodName](...args); 115 | } 116 | setOption(json, ...args) { 117 | const option = parse(json); 118 | if (option.tooltip && typeof option.tooltip === 'object' && !option.tooltip.renderMode) { 119 | option.tooltip.renderMode = 'html'; 120 | option.tooltip.renderer = TooltipContent; 121 | } 122 | return this.plot.setOption(option, ...args); 123 | } 124 | dispose() { 125 | this.plot.dispose(); 126 | this.plot = null; 127 | } 128 | }(); 129 | ctx.open = (...args) => { 130 | ctx.postMessage(['open', args]); 131 | }; 132 | ctx.onmessage = msg => { 133 | try { 134 | ctx.postMessage(['resolve', events[msg.data.type](...msg.data.args)]); 135 | } 136 | catch (e) { 137 | if (e instanceof Error) { 138 | ctx.postMessage(['error', [e.name, e.message, e.stack]]); 139 | } 140 | else { 141 | ctx.postMessage(['reject', e]); 142 | } 143 | } 144 | }; 145 | //# sourceMappingURL=renderer.worker.js.map -------------------------------------------------------------------------------- /dist/renderer.worker.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"renderer.worker.js","sourceRoot":"","sources":["../src/renderer.worker.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 |