如何在D3中实现适配带箭头矩形的散列图案并兼容PPT导出
解决带箭头矩形的散列图案遮罩问题
要解决散列图案超出箭头边界的问题,最直接的方法是利用SVG的裁剪路径(clipPath),将主形状作为裁剪区域,让散列图案仅在该区域内显示,完全适配箭头侧边的轮廓。
实现步骤
- 创建一个裁剪路径,路径数据与主形状完全一致
- 将散列图案的路径包裹在应用了该裁剪路径的
<g>元素中 - 确保裁剪路径的ID唯一,避免与其他元素冲突
修改后的完整代码
<!DOCTYPE html> <!-- Add a svg area, empty --> <svg id="area" height=500 width=500></svg> <script> function calculateStripyRectD( x, y, width, height, stripeWidth, isPointedLeft, isPointedRight, pointWidth ) { const stripes = []; for (let yTop = 0; yTop < height + width; yTop += 5 * stripeWidth) { const yBottom = yTop + stripeWidth; let stripeTopStartX = yTop > height ? x + (yTop - height) : x; let stripeTopStartY = yTop > height ? y + height : y + yTop; let stripeTopEndX = yTop > width ? x + width : x + yTop; let stripeTopEndY = yTop > width ? y + yTop - width : y; let stripe2startX = yBottom > height ? x + (yBottom - height) : x; let stripe2startY = yBottom > height ? y + height : y + yBottom; let stripe2endX = yBottom > width ? x + width : x + yBottom; let stripe2endY = yBottom > width ? y + yBottom - width : y; stripes.push(`M ${stripeTopStartX}, ${stripeTopStartY} L ${stripeTopEndX}, ${stripeTopEndY} L ${stripe2endX}, ${stripe2endY} L ${stripe2startX}, ${stripe2startY} L ${stripeTopStartX}, ${stripeTopStartY} `); } return stripes .join(' ') } function rectangleWithOptionalPoints( width, height, isPointedLeft, isPointedRight, isStriped, ) { const pointWidth = 20; const stripeWidth = 1; let leftX = 0; let rightX = width; if (isPointedLeft) { leftX += pointWidth; } if (isPointedRight) { rightX -= pointWidth; } const mainPath = ` M ${leftX - (isPointedLeft ? pointWidth : 0)} ${height / 2} L ${leftX} 0 L ${rightX} 0 L ${rightX + (isPointedRight ? pointWidth : 0)} ${height / 2} L ${rightX} ${height} L ${leftX} ${height} Z `; const stripes = isStriped ? calculateStripyRectD( leftX - pointWidth, 0, width, height, stripeWidth, isPointedLeft, isPointedRight, pointWidth ) : undefined; return { main: mainPath, stripes, }; } const renderBarGroup = () => { const barGroup = svg.append('g') // 创建裁剪路径 const clipPath = svg.append('clipPath') .attr('id', 'bar-clip') .append('path') .attr('d', () => { const paths = rectangleWithOptionalPoints( 200, 25, true, true, true, ); return paths.main; }); // 应用裁剪路径的组,放置条纹 const stripedGroup = barGroup.append('g') .attr('clip-path', 'url(#bar-clip)'); stripedGroup .append('path') .attr('d', () => { const paths = rectangleWithOptionalPoints( 200, 25, true, true, true, ); return paths.stripes; }) .style('stroke', 'green'); barGroup .append('path') .attr('d', () => { const paths = rectangleWithOptionalPoints( 200, 25, true, true, true, ); return paths.main; }) .attr('fill', 'none') .style('stroke', 'red'); }; var svg = d3.select("#area") renderBarGroup(); </script>
关键修改说明
- 添加了
<clipPath>元素,使用主形状的路径作为裁剪区域 - 将散列图案路径放入带有
clip-path属性的组中,确保条纹仅在主形状内部可见 - 这种方法无需手动调整条纹坐标,完全适配箭头的不规则边界,同时导出到PowerPoint时也能保留正确的视觉效果
内容的提问来源于stack exchange,提问作者sam
相关产品推荐
相关产品推荐

