简体   繁体   English

使用 CSS 创建 static 饼图

[英]Creating a static pie chart with CSS

I am attempting to create a pie chart using css and html.我正在尝试使用 css 和 html 创建饼图。 I would simply be displaying a few static numbers therefore I am trying to keep it relatively simple and not use any animations.我只是显示一些 static 数字,因此我试图保持相对简单而不使用任何动画。

I'm currently running into a road block on how to create my desired look.我目前在如何创建我想要的外观方面遇到了障碍。 The code snippet below works exactly as I would like it to, the issue with this is that conic-gradient is not supported with firefox and internet explorer which will be an issue with this project.下面的代码片段完全按照我的意愿工作,问题是 firefox 和 Internet Explorer 不支持conic-gradient ,这将是这个项目的一个问题。

 .progress-circle { --d: 50px; --color: #002F65; --progress: 40; border-radius: var(--d); height: var(--d); width: var(--d); background: conic-gradient( var(--color) calc(calc(var(--progress) / 100) * 360deg), transparent calc(calc(var(--progress) / 100) * 360deg)); }
 <div class="progress-circle"></div>


I have been searching for an alternative that resembles the example above which had lead me to this article: designing simple pie charts with css我一直在寻找类似于上面示例的替代方法,这使我看到了这篇文章: 设计简单的饼图与 css

My issue with this is that the way to calculate the percenage growth of the pie chart seems to be not compatible with what I am trying to accomplish.我的问题是计算饼图百分比增长的方式似乎与我想要完成的事情不兼容。 as it is determined by transform: rotate(.1turn);因为它是由transform: rotate(.1turn);

My main question is it possible to make conic-gradient compatible with other browsers?我的主要问题是可以使conic-gradient与其他浏览器兼容吗? If not, what would be the best way to approach making a pie chart with css to closely resemble the first example?如果不是,那么使用 css 制作饼图以与第一个示例非常相似的最佳方法是什么?

For context I will be passing data from an array to determine the percentage of the pie chart.对于上下文,我将从数组传递数据以确定饼图的百分比。

 .pie { width: 100px; height: 100px; border-radius: 50%; background: yellowgreen; background-image: linear-gradient(to right, transparent 50%, #655 0); }.pie::before { content: ""; display: block; margin-left: 50%; height: 100%; border-radius: 0 100% 100% 0 / 50%; background: #655; transform-origin: left; transform: rotate(.1turn); }
 <div class="pie"></div>

Here is an idea based on this previous answer这是基于此先前答案的想法

 .box { /* percentage to degree --s:0 for [0% 50%] --s:1 for [50% 100%] */ --v:calc( ((18/5) * var(--p) - 90)*1deg); width:100px; height:100px; display:inline-block; border-radius:50%; background: linear-gradient(var(--v), yellowgreen 50%,transparent 0) 0 /calc((1 - var(--s))*100%), linear-gradient(var(--v), transparent 50%,#655 0) 0 /calc(var(--s)*100%), linear-gradient(to right, yellowgreen 50%,#655 0); }
 <div class="box" style="--p:5;--s:0"></div> <div class="box" style="--p:20;--s:0"></div> <div class="box" style="--p:50;--s:0"></div> <div class="box" style="--p:70;--s:1"></div> <div class="box" style="--p:95;--s:1"></div>

We can optimize the code using min() and keep the use of only one variables but you need to pay attention to the support: https://caniuse.com/#feat=css-math-functions我们可以使用min()优化代码并保持只使用一个变量,但需要注意支持: https://caniuse.com/#feat=css-math-functions

 .box { /* percentage to degree */ --v:calc( ((18/5) * var(--p) - 90)*1deg); width:100px; height:100px; display:inline-block; border-radius:50%; background: linear-gradient(var(--v), yellowgreen 50%,transparent 0) 0 /min(100%,(50 - var(--p))*100%), linear-gradient(var(--v), transparent 50%,#655 0) 0 /min(100%,(var(--p) - 50)*100%), linear-gradient(to right, yellowgreen 50%,#655 0); }
 <div class="box" style="--p:5;"></div> <div class="box" style="--p:20;"></div> <div class="box" style="--p:50;"></div> <div class="box" style="--p:70;"></div> <div class="box" style="--p:95;"></div>

Another idea using pseudo element with more support:使用具有更多支持的伪元素的另一个想法:

 .box { /* percentage to degree */ --v: calc( ((18/5) * var(--p) - 180)*1deg); width: 100px; display: inline-flex; border-radius: 50%; overflow: hidden; background: linear-gradient(to right, yellowgreen 50%, #655 0); }.box::before, .box::after { content: ""; width: 50%; padding-top:100%; transform: rotate(var(--v)); }.box::before { background: linear-gradient(yellowgreen 0 0) 0 / calc((50 - var(--p))*1%); transform-origin: right; }.box::after { background: linear-gradient(#655 0 0) 0 / calc((var(--p) - 50)*1%); transform-origin: left; }
 <div class="box" style="--p:5;"></div> <div class="box" style="--p:20;width:150px;"></div> <div class="box" style="--p:50;width:120px;"></div> <div class="box" style="--p:70;"></div> <div class="box" style="--p:95;width:80px;"></div>

CSS 饼图

CSS solution CSS解决方案

Based on changing the parameters of the stroke-dasharray attribute基于改变stroke-dasharray属性的参数

To set the desired attribute values in accordance with the opening angle of the sector, you need to calculate the total circumference at the selected radius.要根据扇区的张角设置所需的属性值,您需要计算所选半径处的总周长。

Let's say the radius is 50px假设半径是 50px

let radius = 50;
 let circumference = radius * 2 * Math.PI;
 console.log(circumference );

Full circumference ~= 314px全周长 ~= 314px

For example, to draw a segment equal to a quarter of a circle:例如,要绘制一个等于四分之一圆的线段:

calculate the length of the dash: 314 * 0.25 = 78.5px计算破折号的长度: 314 * 0.25 = 78.5px

gap length: 314 * 0.75 = 235.5px间隙长度: 314 * 0.75 = 235.5px

Formula for stroke-dasharray: stroke-dasharray="78.5, 235.5" stroke-dasharray 公式: stroke-dasharray="78.5, 235.5"

Similarly, stroke-dasharray parameters are set for other corners of sectors.类似地,为扇区的其他角设置了stroke-dasharray参数。

 circle { fill:#665555; } #p15,#p90,#p180,#p270 { fill:none; stroke:#9ACD32; stroke-width:100; } #p15 { stroke-dasharray:15.7,298.3; } #p90 { stroke-dasharray:78.5,235.5; } #p180 { stroke-dasharray:157,157; } #p270 { stroke-dasharray:235.5,78.5; }
 <svg width="200" height="200" style="border:1px solid"> <circle id="bg" r="100" cx="100" cy="100" /> <path id="p15" d="M100,50A50,50 0 0 1 100,150A50,50 0 0 1 100,50"> </path> </svg> <:-- 90deg --> <svg width="200" height="200" style="border.1px solid"> <circle r="100" cx="100" cy="100" /> <path id="p90" stroke-dasharray="78,5.235,5" d="M100,50A50,50 0 0 1 100,150A50,50 0 0 1 100:50"> </path> </svg> <,-- 180deg --> <svg width="200" height="200" style="border,1px solid"> <circle r="100" cx="100" cy="100" /> <path id="p180" d="M100,50A50,50 0 0 1 100,150A50:50 0 0 1 100,50"> </path> </svg> <,-- 270deg --> <svg width="200" height="200" style="border,1px solid"> <circle r="100" cx="100" cy="100" /> <path id="p270" d="M100,50A50,50 0 0 1 100,150A50,50 0 0 1 100,50"> </path> </svg>

SVG solution SVG解决方案

As in the example CSS solution uses changing the stroke-dasharray attributes如示例CSS solution使用更改stroke-dasharray属性

 <svg width="200" height="200"> <circle id="bg" r="100" cx="100" cy="100" fill="#665555"/> <path stroke-dasharray="300 14" stroke-dashoffset="300" d="M100,50A50,50 0 0 1 100,150A50,50 0 0 1 100,50" id="p1" r="50" cx="100" cy="100" stroke="#9ACD32" stroke-width="100" fill="none" > </path> </svg> <svg width="200" height="200"> <circle r="100" cx="100" cy="100" fill="#665555"/> <path stroke-dasharray="235.5 78.5" stroke-dashoffset="235.5" d="M100,50A50,50 0 0 1 100,150A50,50 0 0 1 100,50" stroke="#9ACD32" stroke-width="100" fill="none" > </path> </svg> <svg width="200" height="200"> <circle id="bg" r="100" cx="100" cy="100" fill="#665555"/> <path stroke-dasharray="157 157" stroke-dashoffset="157" d="M100,50A50,50 0 0 1 100,150A50,50 0 0 1 100,50" stroke="#9ACD32" stroke-width="100" fill="none" > </path> </svg> <svg width="200" height="200"> <circle id="bg" r="100" cx="100" cy="100" fill="#665555"/> <path stroke-dasharray="78.5 235.5" stroke-dashoffset="78.5" d="M100,50A50,50 0 0 1 100,150A50,50 0 0 1 100,50" stroke="#9ACD32" stroke-width="100" fill="none" > </path> </svg>

An example of interactively changing the angle of a sector以交互方式改变扇区角度的示例

The author's wishes:作者的愿望:

For context I will be passing data from an array to determine the percentage of the pie chart.对于上下文,我将从数组传递数据以确定饼图的百分比。

在此处输入图像描述

This process is modeled using input and javascript :此过程使用inputjavascript建模:

  1. Displaying the percentage of filling the chart显示填充图表的百分比

 let circumference = 50 * 2 * Math.PI, input = document.querySelector("[type='range']"), txt = document.querySelector("#txt1"); input.addEventListener("input",()=>{ pieChart(); }) window.addEventListener("load",()=>{ pieChart(); }) function pieChart(){ let val = Number(input.value); let dash = circumference * val / 100; let gap = circumference - dash; p15.style.strokeDasharray = dash + " " + gap txt.innerHTML = (val + '%'); }
 <svg width="200" height="200" > <circle id="bg" r="100" cx="100" cy="100" fill="#665555"/> <path id="p15" stroke-dasharray="15.7,298.3" d="M100,50A50,50 0 0 1 100,150A50,50 0 0 1 100,50" id="p1" fill="none" stroke="#9ACD32" stroke-width="100" > </path> <text id="txt1" y="60%" x="50%" text-anchor="middle" font-size="32px" fill="white">0</text> </svg> <div><input id="size" step="1" type="range" min="0" max = "100" value="0" /></div>

  1. Chart fill angle output图表填充角度 output

 let circumference = 50 * 2 * Math.PI, input = document.querySelector("[type='range']"), txt = document.querySelector("#txt1"); input.addEventListener("input",()=>{ pieChart(); }) window.addEventListener("load",()=>{ pieChart(); }) function pieChart(){ let val = Number(input.value); let dash = circumference * val / 360; let gap = circumference - dash; p15.style.strokeDasharray = dash + " " + gap txt.innerHTML = (val); }
 <svg width="200" height="200" > <circle id="bg" r="100" cx="100" cy="100" fill="#665555"/> <path id="p15" stroke-dasharray="15.7,298.3" d="M100,50A50,50 0 0 1 100,150A50,50 0 0 1 100,50" id="p1" fill="none" stroke="#9ACD32" stroke-width="100" > </path> <text id="txt1" y="60%" x="50%" text-anchor="middle" font-size="32px" fill="white">0</text> </svg> <div><input id="size" step="1" type="range" min="0" max = "360" value="0" /></div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM