Ima*_*mad 2 html css svg stroke-dasharray
circle我正在尝试使用中的元素创建饼图svg。我可以将值填充到 60%、30% 和 10%,但所有圆圈都从同一位置开始。
如何使下一个循环从上一个循环结束的地方开始?
svg { transform: rotate(-90deg); }
circle {
stroke-width: 3;
stroke-opacity: 1;
fill: none;
}
circle.stroke-yellow {
stroke: yellow;
stroke-dasharray: calc(2*3.14*50*60/100),calc(2*3.14*50);
}
circle.stroke-red {
stroke: red;
stroke-dasharray: calc(2*3.14*50*30/100),calc(2*3.14*50);
}
circle.stroke-blue {
stroke: blue;
stroke-dasharray: calc(2*3.14*50*10/100),calc(2*3.14*50);
}Run Code Online (Sandbox Code Playgroud)
<svg xmlns="http://www.w3.org/2000/svg" height="220">
<circle class="stroke-yellow" cy="110" cx="110" r="50"></circle>
<circle class="stroke-red" cy="110" cx="110" r="50"></circle>
<circle class="stroke-blue" cy="110" cx="110" r="50"></circle>
</svg>Run Code Online (Sandbox Code Playgroud)
我在 CSS 中提到的也stroke-width不起作用。
正如 @enxaneta 提到的:您需要通过更改dash-offset属性来为每个饼图部分提供一个偏移量。
根据您的代码示例:
\nsvg {\n transform: rotate(-90deg);\n}\n\ncircle {\n stroke-width: 3;\n stroke-opacity: 1;\n fill: none;\n}\n\n.stroke {\n stroke-width: 100;\n --circumference: 314.159\n}\n\ncircle.stroke-blue {\n stroke: blue;\n stroke-dasharray: calc( var(--circumference) * 10 / 100), var(--circumference);\n stroke-dashoffset: 0;\n}\n\ncircle.stroke-red {\n stroke: red;\n stroke-dasharray: calc( var(--circumference) * 30 / 100), var(--circumference);\n stroke-dashoffset: calc( 0 - var(--circumference) * 10 / 100);\n}\n\ncircle.stroke-yellow {\n stroke: yellow;\n stroke-dasharray: calc( var(--circumference) * 60 / 100), var(--circumference);\n stroke-dashoffset: calc( 0 - var(--circumference) * 40 / 100);\n}Run Code Online (Sandbox Code Playgroud)\r\n<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 220" height="220">\n <circle class="stroke stroke-blue stroke-10" cy="110" cx="110" r="50" />\n <circle class="stroke stroke-yellow stroke-60" cy="110" cx="110" r="50" />\n <circle class="stroke stroke-red stroke-30" cy="110" cx="110" r="50" />\n</svg>Run Code Online (Sandbox Code Playgroud)\r\nstroke-width需要为“100”(半径*2);
缺点:
\ncalc() (SVG 饼图仅在 Chrome 中工作,在 Firefox 中不起作用)建议:
\n显示 2 个略有不同的 svg 设置的示例:
\nbody{\n font-family: arial;\n font-size:10px;\n}\n.icon-wrp {\n position: relative;\n display: inline-block;\n width: 200px;\n vertical-align: top;\n}\n\n.icon-wrp p{\n font-size:12px;\n}Run Code Online (Sandbox Code Playgroud)\r\n<!--simple pi -->\n<div class="icon-wrp">\n <svg class="svgPieAsset" viewBox="0 0 63.6619772368 63.6619772368">\n <symbol id="slice">\n <circle transform="rotate(-90 31.8309886184 31.8309886184)" id="circle" class="percent" cx="50%" cy="50%" r="15.9154943092" fill="none" stroke-width="31.8309886184" />\n </symbol>\n <!--actual pi slices -->\n <use class="segment" href="#slice" stroke="green" stroke-dashoffset="0" stroke-dasharray="30 100" />\n <use class="segment" href="#slice" stroke="orange" stroke-dashoffset="-30" stroke-dasharray="60 100" />\n <use class="segment" href="#slice" stroke="purple" stroke-dashoffset="-90" stroke-dasharray="10 100" />\n </svg>\n <p>1. Precice geometry based on PI. <br>Should be rendered fine on all browsers.</p>\n</div>\n\n\n<div class="icon-wrp">\n <svg class="svgPieAsset" viewBox="0 0 100 100">\n <symbol id="slice2">\n <circle transform="rotate(-90 50 50)" id="circle" class="percent" cx="50%" cy="50%" r="25" fill="none" stroke-width="50%" pathLength="100" />\n </symbol>\n <!--actual pi slices -->\n <use class="segment" href="#slice2" stroke="green" stroke-dashoffset="0" stroke-dasharray="30 100" />\n <use class="segment" href="#slice2" stroke="orange" stroke-dashoffset="-30" stroke-dasharray="60 100" />\n <use class="segment" href="#slice2" stroke="purple" stroke-dashoffset="-90" stroke-dasharray="10 100" />\n </svg>\n <p>2. Using pathLength="100". <br>Might show a tiny gap on chromium based browsers.</p>\n</div>Run Code Online (Sandbox Code Playgroud)\r\n1. 左示例:正在使用精确的(基于 PI 的)圆形几何图形
\n圆形元素所需的周长应为 100 svg 单位。
\n因此我们需要像这样设置理想值:
半径: 15.91549430919 (100/2\xcf\x80)
\n描边宽度: 31.8309886184 (2 r)
\n vieBox 宽度/高度: 63.6619772368 (4 r)
2. 右例:使用pathLength="100"
\n PathLength允许我们通过将路径的长度计算值设置为“100”来使用任何圆尺寸。
\n不幸的是,您可能会在某些浏览器(例如基于 Chromium 的浏览器)上遇到渲染不精确的情况,从而导致饼图片段之间出现明显的间隙。
这个问题很可能会在未来版本的 chromium 中得到解决。
\n显示饼图段
\n无论怎样,您现在可以通过设置笔画虚线长度值轻松显示基于百分比的饼图段/切片:
示例 30% 破折号长度;抵消。0(因为它是第一段):
\n <circle stroke-dashoffset="0" stroke-dasharray="30 100" cx="50%" cy="50%" r="15.9154943092" fill="none" stroke-width="31.8309886184" />\nRun Code Online (Sandbox Code Playgroud)\n添加饼图分段:
\n您需要通过减去之前的破折号长度(百分比)来逐步递减(因为我们需要负值)破折号偏移值:
\n0、-30、-90
示例:60% 破折号长度;抵消。-30
\n <circle stroke-dashoffset="-30" stroke-dasharray="60 100" cx="50%" cy="50%" r="15.9154943092" fill="none" stroke-width="31.8309886184" />\nRun Code Online (Sandbox Code Playgroud)\n针对可重用性进行优化的示例(使用 css 变量)
\n <circle stroke-dashoffset="0" stroke-dasharray="30 100" cx="50%" cy="50%" r="15.9154943092" fill="none" stroke-width="31.8309886184" />\nRun Code Online (Sandbox Code Playgroud)\r\n <circle stroke-dashoffset="-30" stroke-dasharray="60 100" cx="50%" cy="50%" r="15.9154943092" fill="none" stroke-width="31.8309886184" />\nRun Code Online (Sandbox Code Playgroud)\r\n编辑:圆环图示例
\n对于圆环图或圆形仪表\xe2\x80\x93,只需根据需要调整笔画宽度。
.icon-wrp {\n position: relative;\n display: inline-block;\n width: 200px;\n vertical-align: top;\n}\n\n.chart {\n width: 1em;\n height: 1em;\n font-size: var(--chartFontSize);\n}\n\n.segment {\n stroke-dasharray: var(--percent) 100;\n stroke-dashoffset: var(--offset);\n stroke: var(--strokeColor);\n}\n\n.chartAni .segment {\n animation-name: progress;\n animation-fill-mode: forwards;\n animation-delay: 0.3s;\n animation-duration: 0.5s;\n transition: 0.3s;\n stroke-dasharray: 0 100;\n}\n\n@keyframes progress {\n from {\n stroke-dasharray: 0 100;\n stroke-dashoffset: 0;\n }\n to {\n stroke-dasharray: var(--percent) 100;\n stroke-dashoffset: var(--offset);\n }\n}Run Code Online (Sandbox Code Playgroud)\r\n<!-- pie asset \xe2\x80\x93 hidden -->\n<svg class="svgPieAsset" style="display:none" viewBox="0 0 63.6619772368 63.6619772368">\n <symbol id="slice" viewBox="0 0 63.6619772368 63.6619772368">\n <circle transform="rotate(-90 31.8309886184 31.8309886184)" id="circle" class="percent" cx="31.8309886184" cy="31.8309886184" r="15.9154943092" fill="none" stroke-width="31.8309886184" />\n </symbol>\n</svg>\n\n<!-- visible pie chart -->\n<div class="icon-wrp">\n <svg id="pieChart01" class="chart chartAni" style="--chartFontSize:20vw">\n <use class="segment" href="#slice" style="--offset:-0; --percent:33.333; --strokeColor:green" />\n <use class="segment" href="#slice" style="--offset:-33.333; --percent:33.333; --strokeColor:purple" />\n <use class="segment" href="#slice" style="--offset:-66.666; --percent:33.333; --strokeColor:gray" />\n </svg>\n</div>Run Code Online (Sandbox Code Playgroud)\r\n如果由于某种原因,herrstrietzel 的回答未能解决您的问题:
\n曾几何时,我开始撰写一篇博客文章,演示如何在 React 中生成简单的 SVG 圆环图/饼图。它并不完整,但它包含了计算在图表中绘制每个线段的路径所需的所有信息。
\n这篇文章本身是以 React 为中心的,但方法不需要 React。
\n下面的代码片段是使用该博客文章中的演示生成的。
\n:root {\n --color1: #6761a8;\n --color2: #009ddc;\n --color3: #f26430;\n}\n\nsvg {\n max-width: 180px;\n}\n\npath:nth-child(3n + 1) {\n fill: var(--color1);\n}\n\npath:nth-child(3n + 2) {\n fill: var(--color2);\n}\n\npath:nth-child(3n + 3) {\n fill: var(--color3);\n}Run Code Online (Sandbox Code Playgroud)\r\n<svg viewBox="0 0 100 100">\n <path d="M50.99977962889557 22.51817981476399 L50.99993333466665 0.009999666671113516 A50 50 0 1 1 21.909411013411578 91.36325434956197 L34.92449717574351 72.99954813894905 A27.5 27.5 0 1 0 50.99977962889557 22.51817981476399"></path>\n <path d="M33.293128455589205 71.84331575559345 L20.27779148719977 90.20684420744341 A50 50 0 0 1 19.110270928347777 10.683023540969941 L32.65908657059322 28.656553196968876 A27.5 27.5 0 0 0 33.293128455589205 71.84331575559345"></path>\n <path d="M34.25580929035654 27.45292793069627 L20.707239127704607 9.479213229769087 A50 50 0 0 1 49.000066665333264 0.009999666671113516 L49.00022037110441 22.51817981476399 A27.5 27.5 0 0 0 34.25580929035654 27.45292793069627"></path>\n</svg>Run Code Online (Sandbox Code Playgroud)\r\n每个<path>代表图表的一个片段(切片)。
要绘制线段,您需要计算 4 个角的坐标并用直线和圆弧将它们连接起来。
\n给定角度、半径和中心点,您可以通过以下公式计算 (x, y) 坐标:
\nfunction getCoordinate(angleInDegrees, radius, center = 50) {\n // degrees to radians;\n const radians = angleInDegrees * (Math.PI / 180);\n\n const x = center - Math.cos(radians) * radius\n const y = center - Math.sin(radians) * radius;\n\n return [x, y];\n}\nRun Code Online (Sandbox Code Playgroud)\n因此,对于外半径为 50、内半径为 20 的 90\xc2\xb0 线段,您可以通过以下方式获取角坐标:
\nconst radiusOuter = 50;\nconst radiusInner = 20;\nconst angleStart = 0;\nconst angleEnd = 90;\n\nconst [x1, y1] = getCoordinate(angleStart, radiusInner); // starting angle on inner radius\nconst [x2, y2] = getCoordinate(angleStart, radiusOuter); // starting angle on outer radius\nconst [x3, y3] = getCoordinate(angleEnd, radiusOuter); // ending angle on outer radius\nconst [x4, y4] = getCoordinate(angleEnd, radiusInner); // ending angle on inner radius\nRun Code Online (Sandbox Code Playgroud)\n\n有关下面使用的每个路径命令的详细信息可以在 MDN 中找到。
\nconst largeArc = 0; // percent > 0.5 ? 1 : 0;\nconst sweepOuter = 1;\nconst sweepInner = 0;\n\nconst commands = [\n // move to start angle coordinate, inner radius (1)\n `M${x1} ${y1}`,\n\n // line to start angle coordinate, outer radius (2)\n `L${x2} ${y2}`,\n\n // arc to end angle coordinate, outer radius (3)\n `A${radiusOuter} ${radiusOuter} 0 ${largeArc} ${sweepOuter} ${x3} ${y3}`,\n\n // line to end angle coordinate, inner radius (4)\n `L${x4} ${y4}`,\n\n // arc back to start angle coordinate, inner radius (1)\n `A${radiusInner} ${radiusInner} 0 ${largeArc} ${sweepInner} ${x1} ${y1}`\n];\nRun Code Online (Sandbox Code Playgroud)\n将其放入 SVG 中并添加一些 css,您就得到了片段:
\nsvg {\n width: 250px;\n border: 1px solid grey;\n}\n\npath {\n fill: tomato;\n}Run Code Online (Sandbox Code Playgroud)\r\n<svg viewBox="0 0 100 100">\n <path d="\n M30 50\n L0 50\n A50 50 0 0 1 50 0\n L50 30\n A20 20 0 0 0 30 50\n "/>\n</svg>Run Code Online (Sandbox Code Playgroud)\r\n对其他段重复此操作。
\n