This is an automated email from the ASF dual-hosted git repository. ovilia pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/echarts-custom-series.git
commit dbd53814d072dd9e920ce878502c6943f11896f6 Author: Ovilia <[email protected]> AuthorDate: Wed Oct 9 17:36:46 2024 +0800 refactor(stage): using compoundPath --- custom-series/stage/src/index.ts | 280 +++++++++++++++++++++------------------ 1 file changed, 150 insertions(+), 130 deletions(-) diff --git a/custom-series/stage/src/index.ts b/custom-series/stage/src/index.ts index 71eb248..d365229 100644 --- a/custom-series/stage/src/index.ts +++ b/custom-series/stage/src/index.ts @@ -51,6 +51,16 @@ interface StageItemPayload { envelope?: Envelope; } +interface MyPathProps {} + +class MyPath { + constructor() {} + + buildPath(ctx: CanvasRenderingContext2D) { + console.log('build', ctx); + } +} + const renderItem = ( params: echarts.CustomSeriesRenderItemParams, api: echarts.CustomSeriesRenderItemAPI @@ -112,6 +122,7 @@ const renderItem = ( style: { fill: color, }, + z2: 10, }); boxes.push(shape); params.context.boxes = boxes; @@ -136,6 +147,7 @@ const renderItem = ( text, verticalAlign: 'bottom', }, + z2: 20, }); renderedStages[stageIndex] = true; } @@ -152,50 +164,53 @@ const renderItem = ( const envelope: Envelope = itemPayload.envelope || {}; if (envelope.show !== false && boxes.length > 1) { + const envelopePaths: Path[] = []; + const envelopeDebugPaths: Path[] = []; const margin = echarts.zrUtil.retrieve2(envelope.margin as number, 2); // Sort boxes by x, then by y boxes.sort((a, b) => a.x - b.x || a.y - b.y); const coordSys = params.coordSys as any; - const dpr = envelope.dpr == null ? 2 : envelope.dpr || 1; - const canvasWidth = coordSys.width * dpr; - const canvasHeight = coordSys.height * dpr; - const canvas = createCanvas(canvasWidth, canvasHeight); - const ox = coordSys.x; - const oy = coordSys.y; - - const ctx = canvas.getContext('2d') as CanvasRenderingContext2D; + // const dpr = envelope.dpr == null ? 2 : envelope.dpr || 1; + // const canvasWidth = coordSys.width; + // const canvasHeight = coordSys.height; + // const canvas = createCanvas(canvasWidth, canvasHeight); + // const ox = coordSys.x; + // const oy = coordSys.y; + + // const ctx = canvas.getContext('2d') as CanvasRenderingContext2D; if (allColors.length > 0 && !envelope.color) { - const gradient = ctx.createLinearGradient(0, 0, 0, canvasHeight); - for (let i = 0; i < allColors.length; i++) { - // For example, if there are 4 colors, the gradient stops are 1/8, - // 3/8, 5/8, 7/8. - gradient.addColorStop( - (i * 2 + 1) / (allColors.length * 2), - allColors[i] - ); - } - ctx.fillStyle = gradient; + // const gradient = ctx.createLinearGradient(0, 0, 0, canvasHeight); + // for (let i = 0; i < allColors.length; i++) { + // // For example, if there are 4 colors, the gradient stops are 1/8, + // // 3/8, 5/8, 7/8. + // gradient.addColorStop( + // (i * 2 + 1) / (allColors.length * 2), + // allColors[i] + // ); + // } + // ctx.fillStyle = gradient; } else { - ctx.fillStyle = envelope.color || '#888'; + // ctx.fillStyle = envelope.color || '#888'; } const opacity = zrUtil.retrieve2(envelope.opacity as number, 0.25); for (let i = 0; i < boxes.length; i++) { const box = boxes[i]; - drawRoundedRect( - ctx, - (box.x - margin - ox) * dpr, - (box.y - margin - oy) * dpr, - (box.width + margin * 2) * dpr, - (box.height + margin * 2) * dpr, - (Math.min(borderRadius, box.width / 2) + margin) * dpr - ); + envelopePaths.push({ + type: 'rect', + shape: { + x: box.x - margin, + y: box.y - margin, + width: box.width + margin * 2, + height: box.height + margin * 2, + r: Math.min(borderRadius, box.width / 2) + margin, + }, + }); if (i > 0) { - ctx.beginPath(); const prevBox = boxes[i - 1]; const isPrevLower = prevBox.y > box.y + box.height; const height = isPrevLower @@ -213,85 +228,126 @@ const renderItem = ( // Draw outer border-radius if (isPrevLower) { if (box.x - margin - prevBox.x > 0) { - const right = Math.ceil((box.x - margin - ox) * dpr); - const bottom = (prevBox.y - margin - oy) * dpr; - const r = - Math.min((box.x - margin - prevBox.x) / 2, externalRadius) * - dpr; - ctx.moveTo(right, bottom + r); - ctx.arc(right - r, bottom - r, r, 0, Math.PI / 2); - ctx.lineTo(right, bottom + margin * dpr); - ctx.lineTo(right, bottom - r); - } - - if (box.x + box.width - prevBox.x - prevBox.width - margin > 0) { - const top = (box.y + box.height + margin - oy) * dpr; - const left = Math.floor( - (prevBox.x + prevBox.width + margin - ox) * dpr + const right = Math.ceil(box.x - margin); + const bottom = prevBox.y - margin; + const r = Math.min( + (box.x - margin - prevBox.x) / 2, + externalRadius ); - const r = - Math.min( - (box.x + box.width - prevBox.x - prevBox.width - margin) / 2, - externalRadius - ) * dpr; - ctx.moveTo(left, top + r); - ctx.arc(left + r, top + r, r, Math.PI, Math.PI * 1.5); - ctx.lineTo(left, top - margin * dpr); - ctx.lineTo(left, top); - } - } else { - if (box.x - margin - prevBox.x > 0) { - const right = Math.ceil((box.x - margin - ox) * dpr); - const top = (prevBox.y + prevBox.height + margin - oy) * dpr; - const r = - Math.min((box.x - margin - prevBox.x) / 2, externalRadius) * - dpr; - ctx.moveTo(right, top + r); - ctx.arc(right - r, top + r, r, -Math.PI / 2, 0); - ctx.lineTo(right, top - margin * dpr); - ctx.lineTo(right - r, top); - } - if (box.x + box.width - prevBox.x - prevBox.width - margin > 0) { - const bottom = (box.y - margin - oy) * dpr; - const left = Math.floor( - (prevBox.x + prevBox.width + margin - ox) * dpr - ); - const r = - Math.min( - (box.x + box.width - prevBox.x - prevBox.width - margin) / 2, - externalRadius - ) * dpr; - ctx.moveTo(left + r, bottom); - ctx.arc(left + r, bottom - r, r, Math.PI / 2, Math.PI); - ctx.lineTo(left, bottom + (margin + borderRadius) * dpr); - ctx.lineTo(left + r, bottom); + envelopePaths.push({ + type: 'path', + shape: { + pathData: `M${right},${bottom + r}A${r},${r},0,0,1,${ + right - r + },${bottom}L${right},${bottom + margin}L${right},${ + bottom - r + }Z`, + }, + }); + // const path = ((right, bottom, r, margin) => { + // return { + // buildPath: (ctx) => { + // ctx.moveTo(right, bottom + r); + // ctx.arc(right - r, bottom + r, r, 0, Math.PI / 2); + // ctx.lineTo(right, bottom + margin); + // ctx.lineTo(right, bottom - r); + // }, + // }; + // })(right, bottom, r, margin); + // envelopeDebugPaths.push(path); + + // ctx.moveTo(right, bottom + r); + // ctx.arc(right - r, bottom - r, r, 0, Math.PI / 2); + // ctx.lineTo(right, bottom + margin); + // ctx.lineTo(right, bottom - r); } } - ctx.closePath(); - ctx.fill(); + + // if (box.x + box.width - prevBox.x - prevBox.width - margin > 0) { + // const top = (box.y + box.height + margin); + // const left = Math.floor( + // (prevBox.x + prevBox.width + margin) + // ); + // const r = + // Math.min( + // (box.x + box.width - prevBox.x - prevBox.width - margin) / 2, + // externalRadius + // ); + // ctx.moveTo(left, top + r); + // ctx.arc(left + r, top + r, r, Math.PI, Math.PI * 1.5); + // ctx.lineTo(left, top - margin); + // ctx.lineTo(left, top); + // } + // } else { + // if (box.x - margin - prevBox.x > 0) { + // const right = Math.ceil((box.x - margin)); + // const top = (prevBox.y + prevBox.height + margin); + // const r = + // Math.min((box.x - margin - prevBox.x) / 2, externalRadius) * + // dpr; + // ctx.moveTo(right, top + r); + // ctx.arc(right - r, top + r, r, -Math.PI / 2, 0, false); // Top-right corner + // ctx.lineTo(right, top - margin); + // ctx.lineTo(right - r, top); + // } + + // if (box.x + box.width - prevBox.x - prevBox.width - margin > 0) { + // const bottom = (box.y - margin); + // const left = Math.floor( + // (prevBox.x + prevBox.width + margin) + // ); + // const r = + // Math.min( + // (box.x + box.width - prevBox.x - prevBox.width - margin) / 2, + // externalRadius + // ); + // ctx.moveTo(left + r, bottom); + // ctx.arc(left + r, bottom - r, r, Math.PI / 2, Math.PI); + // ctx.lineTo(left, bottom + (margin + borderRadius)); + // ctx.lineTo(left + r, bottom); + // } + // } + // ctx.closePath(); + // ctx.fill(); // Draw bars between boxes - ctx.fillRect( - (prevBox.x + prevBox.width + margin - ox) * dpr, - (y - oy) * dpr, - (box.x - prevBox.x - prevBox.width - margin * 2) * dpr, - height * dpr - ); + envelopePaths.push({ + type: 'rect', + shape: { + x: prevBox.x + prevBox.width + margin, + y: y + height, + width: box.x - prevBox.x - prevBox.width - margin * 2, + height: -height, + }, + }); } } children.push({ - type: 'image', + type: 'compoundPath', + shape: { + paths: envelopePaths, + }, + style: { + fill: envelope.color || '#888', + opacity: 0.2, + }, + silent: true, + z2: 200, + }); + + children.push({ + type: 'compoundPath', + shape: { + paths: envelopeDebugPaths, + }, style: { - image: canvas, - x: coordSys.x * dpr, - y: coordSys.y * dpr, - opacity, + fill: envelope.color || '#f00', + opacity: 0.9, }, silent: true, - scaleX: 1 / dpr, - scaleY: 1 / dpr, + z2: 200, }); } } @@ -302,42 +358,6 @@ const renderItem = ( } as CustomRootElementOption; }; -function createCanvas(width, height) { - const canvas = document.createElement('canvas'); - canvas.width = width; - canvas.height = height; - return canvas; -} - -function drawRoundedRect( - ctx: CanvasRenderingContext2D, - x: number, - y: number, - width: number, - height: number, - radius: number -) { - ctx.beginPath(); - ctx.moveTo(x + radius, y); // Move to the top-left corner - ctx.lineTo(x + width - radius, y); // Top edge - ctx.arc(x + width - radius, y + radius, radius, -Math.PI / 2, 0, false); // Top-right corner - ctx.lineTo(x + width, y + height - radius); // Right edge - ctx.arc( - x + width - radius, - y + height - radius, - radius, - 0, - Math.PI / 2, - false - ); // Bottom-right corner - ctx.lineTo(x + radius, y + height); // Bottom edge - ctx.arc(x + radius, y + height - radius, radius, Math.PI / 2, Math.PI, false); // Bottom-left corner - ctx.lineTo(x, y + radius); // Left edge - ctx.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 1.5, false); // Top-left corner - ctx.closePath(); - ctx.fill(); -} - export default { install(registers: EChartsExtensionInstallRegisters) { registers.registerCustomSeries( --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
