CSS 带有完全交互式和可访问的饼图的圆圈?
CSS Circle with fully interactive & accessible pie wedges?
目标:
如何在不使用图表库的情况下使用可访问的交互式饼图在 CSS 中创建一个圆圈 (通常会创建完全不可交互或不可访问的饼图)
如果您需要将按钮创建为圆楔形怎么办?
欢迎所有回答,但我写这个 Jeopardy style 问题是为了帮助其他人解决我的问题。
解决方案:
我到处搜索,找到了很多解决方案 - 所有这些都非常肤浅,它们填充了设计方面,但最终没有给你任何可用或可访问的元素。
[tl;dr] Codepen
以最简单的形式创建一个容器,并确保它的溢出是隐藏的,并且它是 border-radius: 50%
的完美圆
在标记中,您可以添加内部元素 - 它们可以是按钮、div、带有列表的 ul/ol 等...您放在那里什么并不重要,它是 CSS计算即算。这是我的例子 HTML
<div class="pie">
<button>
<span class="text">1</span>
</button>
<button>
<span class="text">2</span>
</button>
<button>
<span class="text">3</span>
</button>
</div>
在我的示例中,我将容器命名为 .pie
,这里是重要的 CSS:
.pie {
border-radius: 50%;
height: 150px;
overflow: hidden;
position: relative;
width: 150px;
}
高度和宽度显然只需要彼此匹配,但可以是任何值。
然后给内部元素 CSS 使它们最初都显示为饼图容器的第一四分之一象限。
button {
bottom: 50%;
height: 100%;
left: 50%;
position: absolute;
transform-origin: bottom left;
width: 100%;
}
您可以将目前所拥有的概念化为:
那里的transform-origin
可能看起来不合时宜,但后来就有意义了,而且是整件事的关键...
制作楔形的最后一个关键是将每个正方形变成楔形的计算。这是通过使用以下的有序组合完成的:
transform: rotate()
transform: skeyY()
为了进行计算,我们需要知道每个楔形在圆中的度数。比方说
share = 120
这对于我们的例子来说是正确的,有 3 个相等的份额,我们需要一个迭代器,让我们使用
i = 0
(我相信您可以看到这将如何转化为任意数量的楔形的动态 JS 函数...)
现在每个楔子按出现顺序计算如下:
rotate = (i * share)deg
skeyY = (share - 90)deg
i++
负 90 因为楔形一开始是正方形
基本上,旋转将其左下角(即饼图的中心)上的楔形旋转为它之前所有楔形的度数。 skewY 将楔形从矩形倾斜为正确度数的楔形。
然后我们必须抵消内部元素的 skewY 和旋转(特别是如果你想要那里的文本),计算是:
rotate = (share / 2)deg
skewY(-(share - 90)deg
这将反转转换并将文本旋转 相对于包含 'wedge'.
的内容 45 度
现在您的标记将如下所示:
<div class="pie">
<button style="transform: rotate(0deg) skewY(30deg)">
<span style="transform: skewY(-30deg) rotate(60deg)" class="text">1</span>
</button>
<button style="transform: rotate(120deg) skewY(30deg)">
<span style="transform: skewY(-30deg) rotate(60deg)" class="text">2</span>
</button>
<button style="transform: rotate(240deg) skewY(30deg)">
<span style="transform: skewY(-30deg) rotate(60deg)"class="text">3</span>
</button>
</div>
一般警告
顺序或转换属性很重要。尝试切换顺序,它不会工作。我没有足够的时间来解决这个问题,所以如果这里有人想解释一下 - 去吧!
这是最后的样子,还有一些额外的东西 css 这样您就可以更好地看到结果。
.pie {
background-color: rgba(0,0,0,0.5);
position: relative;
width: 150px;
height: 150px;
border-radius: 50%;
overflow: hidden;
}
.pie button,
.pie button:focus {
outline: none;
background-color: lightgreen;
border: thin solid white;
position: absolute;
cursor: pointer;
width: 100%;
height: 100%;
left: 50%;
bottom: 50%;
transform-origin: bottom left;
transition: all 200ms ease-out;
}
.pie button:hover,
.pie button:focus:hover {
box-shadow: 0px 0px 10px 5px #515151;
z-index: 1;
}
.pie button .text,
.pie button:focus .text {
position: absolute;
bottom: 30px;
padding: 0px;
color: #333;
left: 30px;
}
<div class="pie">
<button style="transform: rotate(0deg) skewY(30deg)">
<span style="transform: skewY(-30deg) rotate(60deg)" class="text">1</span>
</button>
<button style="transform: rotate(120deg) skewY(30deg)">
<span style="transform: skewY(-30deg) rotate(60deg)" class="text">2</span>
</button>
<button style="transform: rotate(240deg) skewY(30deg)">
<span style="transform: skewY(-30deg) rotate(60deg)"class="text">3</span>
</button>
</div>
如果您有兴趣让它动态化,这里有一个非常简单的实现:
响应能力
是 - 你只需要改变饼图的宽度和高度。可以是 css var,或者带有媒体查询...
@media (min-width: 1920px) {
.pie {
height: 350px;
width: 350px;
}
}
注意事项和想法...
唯一真正需要注意的是,您最多只能使用三个楔子。最大值实际上取决于楔形的内部内容以及 'pie'...
的整体大小
如果您确实需要 1 和 2 楔形支撑,我在自己的项目中写了一些条件,我很乐意与您分享。
如果您有兴趣,这很可能很容易被改编成一个简单的饼图引擎 - 但我没有时间弄清楚细节。
希望有需要的人能找到这个,它会有所帮助:-)
目标:
如何在不使用图表库的情况下使用可访问的交互式饼图在 CSS 中创建一个圆圈 (通常会创建完全不可交互或不可访问的饼图)
如果您需要将按钮创建为圆楔形怎么办?
欢迎所有回答,但我写这个 Jeopardy style 问题是为了帮助其他人解决我的问题。
解决方案:
我到处搜索,找到了很多解决方案 - 所有这些都非常肤浅,它们填充了设计方面,但最终没有给你任何可用或可访问的元素。
[tl;dr] Codepen
以最简单的形式创建一个容器,并确保它的溢出是隐藏的,并且它是 border-radius: 50%
在标记中,您可以添加内部元素 - 它们可以是按钮、div、带有列表的 ul/ol 等...您放在那里什么并不重要,它是 CSS计算即算。这是我的例子 HTML
<div class="pie">
<button>
<span class="text">1</span>
</button>
<button>
<span class="text">2</span>
</button>
<button>
<span class="text">3</span>
</button>
</div>
在我的示例中,我将容器命名为 .pie
,这里是重要的 CSS:
.pie {
border-radius: 50%;
height: 150px;
overflow: hidden;
position: relative;
width: 150px;
}
高度和宽度显然只需要彼此匹配,但可以是任何值。
然后给内部元素 CSS 使它们最初都显示为饼图容器的第一四分之一象限。
button {
bottom: 50%;
height: 100%;
left: 50%;
position: absolute;
transform-origin: bottom left;
width: 100%;
}
您可以将目前所拥有的概念化为:
那里的transform-origin
可能看起来不合时宜,但后来就有意义了,而且是整件事的关键...
制作楔形的最后一个关键是将每个正方形变成楔形的计算。这是通过使用以下的有序组合完成的:
transform: rotate()
transform: skeyY()
为了进行计算,我们需要知道每个楔形在圆中的度数。比方说
share = 120
这对于我们的例子来说是正确的,有 3 个相等的份额,我们需要一个迭代器,让我们使用
i = 0
(我相信您可以看到这将如何转化为任意数量的楔形的动态 JS 函数...)
现在每个楔子按出现顺序计算如下:
rotate = (i * share)deg
skeyY = (share - 90)deg
i++
负 90 因为楔形一开始是正方形
基本上,旋转将其左下角(即饼图的中心)上的楔形旋转为它之前所有楔形的度数。 skewY 将楔形从矩形倾斜为正确度数的楔形。
然后我们必须抵消内部元素的 skewY 和旋转(特别是如果你想要那里的文本),计算是:
rotate = (share / 2)deg
skewY(-(share - 90)deg
这将反转转换并将文本旋转 相对于包含 'wedge'.
的内容 45 度现在您的标记将如下所示:
<div class="pie">
<button style="transform: rotate(0deg) skewY(30deg)">
<span style="transform: skewY(-30deg) rotate(60deg)" class="text">1</span>
</button>
<button style="transform: rotate(120deg) skewY(30deg)">
<span style="transform: skewY(-30deg) rotate(60deg)" class="text">2</span>
</button>
<button style="transform: rotate(240deg) skewY(30deg)">
<span style="transform: skewY(-30deg) rotate(60deg)"class="text">3</span>
</button>
</div>
一般警告 顺序或转换属性很重要。尝试切换顺序,它不会工作。我没有足够的时间来解决这个问题,所以如果这里有人想解释一下 - 去吧!
这是最后的样子,还有一些额外的东西 css 这样您就可以更好地看到结果。
.pie {
background-color: rgba(0,0,0,0.5);
position: relative;
width: 150px;
height: 150px;
border-radius: 50%;
overflow: hidden;
}
.pie button,
.pie button:focus {
outline: none;
background-color: lightgreen;
border: thin solid white;
position: absolute;
cursor: pointer;
width: 100%;
height: 100%;
left: 50%;
bottom: 50%;
transform-origin: bottom left;
transition: all 200ms ease-out;
}
.pie button:hover,
.pie button:focus:hover {
box-shadow: 0px 0px 10px 5px #515151;
z-index: 1;
}
.pie button .text,
.pie button:focus .text {
position: absolute;
bottom: 30px;
padding: 0px;
color: #333;
left: 30px;
}
<div class="pie">
<button style="transform: rotate(0deg) skewY(30deg)">
<span style="transform: skewY(-30deg) rotate(60deg)" class="text">1</span>
</button>
<button style="transform: rotate(120deg) skewY(30deg)">
<span style="transform: skewY(-30deg) rotate(60deg)" class="text">2</span>
</button>
<button style="transform: rotate(240deg) skewY(30deg)">
<span style="transform: skewY(-30deg) rotate(60deg)"class="text">3</span>
</button>
</div>
如果您有兴趣让它动态化,这里有一个非常简单的实现:
响应能力
是 - 你只需要改变饼图的宽度和高度。可以是 css var,或者带有媒体查询...
@media (min-width: 1920px) {
.pie {
height: 350px;
width: 350px;
}
}
注意事项和想法...
唯一真正需要注意的是,您最多只能使用三个楔子。最大值实际上取决于楔形的内部内容以及 'pie'...
的整体大小如果您确实需要 1 和 2 楔形支撑,我在自己的项目中写了一些条件,我很乐意与您分享。
如果您有兴趣,这很可能很容易被改编成一个简单的饼图引擎 - 但我没有时间弄清楚细节。
希望有需要的人能找到这个,它会有所帮助:-)