You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by GitBox <gi...@apache.org> on 2022/09/09 03:02:39 UTC

[GitHub] [echarts] pe-3 commented on a diff in pull request #17461: feat(funnel): add funnel new styles #14863

pe-3 commented on code in PR #17461:
URL: https://github.com/apache/echarts/pull/17461#discussion_r966581436


##########
src/chart/funnel/funnelLayout.ts:
##########
@@ -337,55 +427,156 @@ export default function funnelLayout(ecModel: GlobalModel, api: ExtensionAPI) {
             indices = indices.reverse();
         }
 
-        for (let i = 0; i < indices.length; i++) {
-            const idx = indices[i];
-            const nextIdx = indices[i + 1];
-            const itemModel = data.getItemModel<FunnelDataItemOption>(idx);
+        const valueSum = valueArr.reduce((pre, cur) => pre + cur);
 
-            if (orient === 'horizontal') {
-                let width = itemModel.get(['itemStyle', 'width']);
-                if (width == null) {
-                    width = itemSize;
+        const getSideLen = function (sideLen: number | string, idx?: number): number {
+            if (dynamicHeight) {
+                // in dy height, user can't set itemHeight or itemWidth
+                const val = data.get(valueDim, idx) as number || 0;
+                sideLen = linearMap(val, [0, valueSum], sizeExtent, true);
+                sideLen = sort === 'ascending' ? -sideLen : sideLen;
+                return sideLen;
+            }
+
+            if (sideLen == null) {
+                sideLen = itemSize;
+            }
+            else {
+                if (orient === 'horizontal') {
+                    sideLen = parsePercent(sideLen, viewWidth);
                 }
                 else {
-                    width = parsePercent(width, viewWidth);
-                    if (sort === 'ascending') {
-                        width = -width;
-                    }
+                    sideLen = parsePercent(sideLen, viewHeight);
                 }
 
-                const start = getLinePoints(idx, x);
-                const end = getLinePoints(nextIdx, x + width);
+                if (sort === 'ascending') {
+                    sideLen = -sideLen;
+                }
+            }
+            return sideLen;
+        };
 
-                x += width + gap;
+        const exitShape = seriesModel.get('exitShape');
+        let resSize = sizeExtent[1];
+        let maxSize = sizeExtent[1];
+        let exitWidth: string | number = seriesModel.get('exitWidth');
 
-                data.setItemLayout(idx, {
-                    points: start.concat(end.slice().reverse())
-                });
+        if (exitWidth) {
+            const percentReg = /^\w{1,2}\.{0,}\w{0,}%$/;
+            if (percentReg.test(exitWidth)) {
+                exitWidth = parseInt(exitWidth, 10);
+                resSize = maxSize = 100 * maxSize / (100 - exitWidth);
             }
             else {
-                let height = itemModel.get(['itemStyle', 'height']);
-                if (height == null) {
-                    height = itemSize;
-                }
-                else {
-                    height = parsePercent(height, viewHeight);
-                    if (sort === 'ascending') {
-                        height = -height;
+                throw new Error(`the exitWidth must be in percentage format and cannot be greater than 99%, 
+                but you set it as '${exitWidth}'`);
+            }
+        }
+
+        const showRate = seriesModel.get('showRate');
+        let firstVal: number;
+        const setLayoutPoints =
+            // The subsequent funnel shape modification will be done in this func.
+            // We don’t need to concern direction when we use this function to set points.
+            function (
+                index: number,
+                idx: number,
+                nextIdx: number,
+                sideLen: number,
+                pos: number
+            ): void {
+                if (dynamicHeight) {
+                    const start = getLinePointsBySize(pos, resSize / maxSize * viewSize);
+                    let end;
+
+                    if (index === indices.length - 1 && exitShape === 'rect') {
+                        end = getLinePointsBySize(pos + sideLen, resSize / maxSize * viewSize);
+                    }
+                    else {
+                        resSize += sort === 'ascending' ? sideLen : -sideLen;
+                        end = getLinePointsBySize(pos + sideLen, resSize / maxSize * viewSize);
                     }
+
+                    data.setItemLayout(idx, {
+                        points: start.concat(end.slice().reverse())
+                    });
+                    return;
                 }
+                else if (showRate) {
+                    const dataStart = getLinePoints(idx, pos);
+                    let dataEnd;
+                    if (exitWidth !== undefined && index === indices.length - 1) {
+                        const val = data.get(valueDim, idx) as number || 0;
+                        const itemSize = linearMap(val, [min, max], sizeExtent, true);
+                        const exitSize = itemSize * (exitWidth as number) / 100;
+                        dataEnd = getLinePointsBySize(pos + sideLen / 2, exitSize);
+                    }
+                    else {
+                        dataEnd = getLinePoints(idx, pos + sideLen / 2);
+                    }
+                    const rateStart = getLinePoints(idx, pos + sideLen / 2);
+                    const rateEnd = getLinePoints(nextIdx, pos + sideLen);
 
-                const start = getLinePoints(idx, y);
-                const end = getLinePoints(nextIdx, y + height);
+                    const val = data.get(valueDim, idx) as number || 0;
+                    const nextVal = data.get(valueDim, nextIdx) as number || 0;
+                    let rate: number | string = nextVal / val;
+                    rate = 'Rate ' + (rate * 100).toFixed(0) + '%';
+                    if (index === 0) {
+                        firstVal = val;
+                    }
+                    else if (index === indices.length - 1) {
+                        const lastVal = val;
+                        rate = lastVal / firstVal;
+                        rate = 'Overall rate ' + (rate * 100).toFixed(0) + '%';

Review Comment:
   Rate formatter is different with label formatter, it has to concern previous and next, so it need a new label fetcher, so sorry, I can't implement this.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


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