You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by sh...@apache.org on 2021/10/03 10:52:19 UTC

[echarts] branch svg-ssr created (now 44e26a8)

This is an automated email from the ASF dual-hosted git repository.

shenyi pushed a change to branch svg-ssr
in repository https://gitbox.apache.org/repos/asf/echarts.git.


      at 44e26a8  wip(ssr): integrate ssr svg output. upgrade ts

This branch includes the following new commits:

     new 44e26a8  wip(ssr): integrate ssr svg output. upgrade ts

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org


[echarts] 01/01: wip(ssr): integrate ssr svg output. upgrade ts

Posted by sh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

shenyi pushed a commit to branch svg-ssr
in repository https://gitbox.apache.org/repos/asf/echarts.git

commit 44e26a8c9e55adbd33df9a9ad71a2b11cb32a28f
Author: pissang <bm...@gmail.com>
AuthorDate: Sun Oct 3 18:51:17 2021 +0800

    wip(ssr): integrate ssr svg output. upgrade ts
---
 build/dev-fast.js                            |  3 +-
 package-lock.json                            |  6 +--
 package.json                                 |  2 +-
 src/component/toolbox/feature/SaveAsImage.ts |  4 +-
 src/core/echarts.ts                          | 64 +++++++++++++++-----------
 src/util/decal.ts                            | 17 +++++--
 src/util/states.ts                           |  2 +-
 test/node/ssr.js                             | 67 ++++++++++++++++++++++++++++
 8 files changed, 129 insertions(+), 36 deletions(-)

diff --git a/build/dev-fast.js b/build/dev-fast.js
index 2a1aacb..8d417e7 100644
--- a/build/dev-fast.js
+++ b/build/dev-fast.js
@@ -26,8 +26,9 @@ const outFilePath = path.resolve(__dirname, '../dist/echarts.js');
 const umdMark = '// ------------- WRAPPED UMD --------------- //';
 const umdWrapperHead = `
 ${umdMark}
+typeof window !== 'undefined' ? window.__DEV__ = true
+    : typeof global !== 'undefined' ? global.__DEV__ = true : __DEV__ = true;
 (function (root, factory) {
-    window.__DEV__ = true;
     if (typeof define === 'function' && define.amd) {
         // AMD. Register as an anonymous module.
         define(['exports'], factory);
diff --git a/package-lock.json b/package-lock.json
index c319fcf..8236e54 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10619,9 +10619,9 @@
       }
     },
     "typescript": {
-      "version": "4.3.5",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
-      "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==",
+      "version": "4.4.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz",
+      "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==",
       "dev": true
     },
     "unbzip2-stream": {
diff --git a/package.json b/package.json
index 319d57e..7469582 100644
--- a/package.json
+++ b/package.json
@@ -106,6 +106,6 @@
     "socket.io": "2.2.0",
     "terser": "^5.3.8",
     "ts-jest": "^26.4.3",
-    "typescript": "4.3.5"
+    "typescript": "4.4.3"
   }
 }
diff --git a/src/component/toolbox/feature/SaveAsImage.ts b/src/component/toolbox/feature/SaveAsImage.ts
index c59bb86..6410b87 100644
--- a/src/component/toolbox/feature/SaveAsImage.ts
+++ b/src/component/toolbox/feature/SaveAsImage.ts
@@ -74,6 +74,7 @@ class SaveAsImage extends ToolboxFeature<ToolboxSaveAsImageFeatureOption> {
         }
         // IE or old Edge
         else {
+            // @ts-ignore
             if (window.navigator.msSaveOrOpenBlob || isSvg) {
                 const parts = url.split(',');
                 // data:[<mime type>][;charset=<charset>][;base64],<encoded data>
@@ -88,13 +89,14 @@ class SaveAsImage extends ToolboxFeature<ToolboxSaveAsImageFeatureOption> {
                 // (just a url-encoded string through `encodeURIComponent`)
                 base64Encoded && (bstr = window.atob(bstr));
                 const filename = title + '.' + type;
+                // @ts-ignore
                 if (window.navigator.msSaveOrOpenBlob) {
                     let n = bstr.length;
                     const u8arr = new Uint8Array(n);
                     while (n--) {
                         u8arr[n] = bstr.charCodeAt(n);
                     }
-                    const blob = new Blob([u8arr]);
+                    const blob = new Blob([u8arr]);// @ts-ignore
                     window.navigator.msSaveOrOpenBlob(blob, filename);
                 }
                 else {
diff --git a/src/core/echarts.ts b/src/core/echarts.ts
index 8a61c98..b997116 100644
--- a/src/core/echarts.ts
+++ b/src/core/echarts.ts
@@ -327,6 +327,7 @@ type EChartsInitOpts = {
     renderer?: RendererType,
     devicePixelRatio?: number,
     useDirtyRect?: boolean,
+    ssr?: boolean,
     width?: number,
     height?: number
 };
@@ -343,6 +344,8 @@ class ECharts extends Eventful<ECEventDefinition> {
      */
     group: string;
 
+    private _ssr: boolean;
+
     private _zr: zrender.ZRenderType;
 
     private _dom: HTMLElement;
@@ -429,8 +432,10 @@ class ECharts extends Eventful<ECEventDefinition> {
             devicePixelRatio: opts.devicePixelRatio,
             width: opts.width,
             height: opts.height,
+            ssr: opts.ssr,
             useDirtyRect: opts.useDirtyRect == null ? defaultUseDirtyRect : opts.useDirtyRect
         });
+        this._ssr = opts.ssr;
 
         // Expect 60 fps.
         this._throttledZrFlush = throttle(bind(zr.flush, zr), 17);
@@ -634,7 +639,10 @@ class ECharts extends Eventful<ECEventDefinition> {
 
             // Ensure zr refresh sychronously, and then pixel in canvas can be
             // fetched after `setOption`.
-            this._zr.flush();
+            if (!this._ssr) {
+                // not use flush when using ssr mode.
+                this._zr.flush();
+            }
 
             this[PENDING_UPDATE] = null;
             this[IN_MAIN_PROCESS_KEY] = false;
@@ -1121,7 +1129,10 @@ class ECharts extends Eventful<ECEventDefinition> {
         }
         this._disposed = true;
 
-        modelUtil.setAttribute(this.getDom(), DOM_ATTRIBUTE_KEY, '');
+        const dom = this.getDom();
+        if (dom) {
+            modelUtil.setAttribute(this.getDom(), DOM_ATTRIBUTE_KEY, '');
+        }
 
         const chart = this;
         const api = chart._api;
@@ -2546,32 +2557,35 @@ export function init(
     theme?: string | object,
     opts?: EChartsInitOpts
 ): EChartsType {
-    if (__DEV__) {
-        if (!dom) {
-            throw new Error('Initialize failed: invalid dom.');
+    const isClient = !(opts && opts.ssr);
+    if (isClient) {
+        if (__DEV__) {
+            if (!dom) {
+                throw new Error('Initialize failed: invalid dom.');
+            }
         }
-    }
 
-    const existInstance = getInstanceByDom(dom);
-    if (existInstance) {
-        if (__DEV__) {
-            console.warn('There is a chart instance already initialized on the dom.');
+        const existInstance = getInstanceByDom(dom);
+        if (existInstance) {
+            if (__DEV__) {
+                console.warn('There is a chart instance already initialized on the dom.');
+            }
+            return existInstance;
         }
-        return existInstance;
-    }
 
-    if (__DEV__) {
-        if (isDom(dom)
-            && dom.nodeName.toUpperCase() !== 'CANVAS'
-            && (
-                (!dom.clientWidth && (!opts || opts.width == null))
-                || (!dom.clientHeight && (!opts || opts.height == null))
-            )
-        ) {
-            console.warn('Can\'t get DOM width or height. Please check '
-            + 'dom.clientWidth and dom.clientHeight. They should not be 0.'
-            + 'For example, you may need to call this in the callback '
-            + 'of window.onload.');
+        if (__DEV__) {
+            if (isDom(dom)
+                && dom.nodeName.toUpperCase() !== 'CANVAS'
+                && (
+                    (!dom.clientWidth && (!opts || opts.width == null))
+                    || (!dom.clientHeight && (!opts || opts.height == null))
+                )
+            ) {
+                console.warn('Can\'t get DOM width or height. Please check '
+                + 'dom.clientWidth and dom.clientHeight. They should not be 0.'
+                + 'For example, you may need to call this in the callback '
+                + 'of window.onload.');
+            }
         }
     }
 
@@ -2579,7 +2593,7 @@ export function init(
     chart.id = 'ec_' + idBase++;
     instances[chart.id] = chart;
 
-    modelUtil.setAttribute(dom, DOM_ATTRIBUTE_KEY, chart.id);
+    isClient && modelUtil.setAttribute(dom, DOM_ATTRIBUTE_KEY, chart.id);
 
     enableConnect(chart);
 
diff --git a/src/util/decal.ts b/src/util/decal.ts
index 4058db9..dc26506 100644
--- a/src/util/decal.ts
+++ b/src/util/decal.ts
@@ -28,10 +28,11 @@ import ExtensionAPI from '../core/ExtensionAPI';
 import type SVGPainter from 'zrender/src/svg/Painter';
 import { brushSingle } from 'zrender/src/canvas/graphic';
 import {DecalDashArrayX, DecalDashArrayY, InnerDecalObject, DecalObject} from './types';
+import { SVGVNode } from 'zrender/src/svg/core';
 
 const decalMap = new WeakMap<DecalObject, PatternObject>();
 
-const decalCache = new LRU<HTMLCanvasElement | SVGElement>(100);
+const decalCache = new LRU<HTMLCanvasElement | SVGVNode>(100);
 
 const decalKeys = [
     'symbol', 'symbolSize', 'symbolKeepAspect',
@@ -117,7 +118,7 @@ export function createOrUpdatePatternFromDecal(
             cacheKey = keys.join(',') + (isSVG ? '-svg' : '');
             const cache = decalCache.get(cacheKey);
             if (cache) {
-                isSVG ? (pattern as SVGPatternObject).svgElement = cache as SVGElement
+                isSVG ? (pattern as SVGPatternObject).svgElement = cache as SVGVNode
                     : (pattern as ImagePatternObject).image = cache as HTMLCanvasElement;
             }
         }
@@ -129,7 +130,12 @@ export function createOrUpdatePatternFromDecal(
         const lineBlockLengthY = getLineBlockLengthY(dashArrayY);
 
         const canvas = !isSVG && createCanvas();
-        const svgRoot = isSVG && (zr.painter as SVGPainter).createSVGElement('g');
+        const svgRoot: SVGVNode = isSVG && {
+            tag: 'g',
+            attrs: {},
+            key: 'dcl',
+            children: []
+        };
         const pSize = getPatternSize();
         let ctx: CanvasRenderingContext2D;
         if (canvas) {
@@ -284,7 +290,10 @@ export function createOrUpdatePatternFromDecal(
                     decalOpt.symbolKeepAspect
                 );
                 if (isSVG) {
-                    svgRoot.appendChild((zr.painter as SVGPainter).paintOne(symbol));
+                    const symbolVNode = (zr.painter as SVGPainter).renderOneToVNode(symbol);
+                    if (symbolVNode) {
+                        svgRoot.children.push(symbolVNode);
+                    }
                 }
                 else {
                     // Paint to canvas for all other renderers.
diff --git a/src/util/states.ts b/src/util/states.ts
index ac5e01c..3cff899 100644
--- a/src/util/states.ts
+++ b/src/util/states.ts
@@ -216,7 +216,7 @@ function getFromStateStyle(
             // Dont consider the animation to emphasis state.
             && animator.__fromStateTransition.indexOf(toStateName) < 0
             && animator.targetName === 'style') {
-            animator.saveFinalToTarget(fromState, props);
+            animator.saveTo(fromState, props);
         }
     }
     return fromState;
diff --git a/test/node/ssr.js b/test/node/ssr.js
new file mode 100644
index 0000000..6f4673e
--- /dev/null
+++ b/test/node/ssr.js
@@ -0,0 +1,67 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+const echarts = require('../../dist/echarts');
+const chart = echarts.init(null, null, {
+    renderer: 'svg',
+    ssr: true,
+    width: 510,
+    height: 510
+});
+
+chart.setOption({
+    series: [
+        {
+            name: 'Nightingale Chart',
+            type: 'pie',
+            radius: [25, 250],
+            center: ['50%', '50%'],
+            roseType: 'radius',
+            label: {
+                show: false,
+            },
+            itemStyle: {
+                borderColor: 'white',
+                borderWidth: 4,
+            },
+            labelLine: {
+                show: false,
+            },
+            animationType: 'scale',
+            animationDuration: 500,
+            animationEasing: 'cubicOut',
+            animationDelay(idx) {
+                return (1 - idx / 8) * 500;
+            },
+            data: [
+                { value: 40, name: 'rose 1', itemStyle: { borderRadius: [0, 20] } },
+                { value: 32, name: 'rose 2', itemStyle: { borderRadius: [0, 18] } },
+                { value: 28, name: 'rose 3', itemStyle: { borderRadius: [0, 16] } },
+                { value: 24, name: 'rose 4', itemStyle: { borderRadius: [0, 14] } },
+                { value: 19, name: 'rose 5', itemStyle: { borderRadius: [0, 12] } },
+                { value: 15, name: 'rose 6', itemStyle: { borderRadius: [0, 10] } },
+                { value: 12, name: 'rose 7', itemStyle: { borderRadius: [0, 8] } },
+                { value: 10, name: 'rose 8', itemStyle: { borderRadius: [0, 6] } },
+            ],
+        },
+    ],
+});
+// chart.getZr().animation.update(true);
+const str = chart.getZr().painter.renderToString();
+console.log(str);
+chart.dispose();
\ No newline at end of file

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org