带有 HTML、CSS 和 JS 的圆表

Posted

技术标签:

【中文标题】带有 HTML、CSS 和 JS 的圆表【英文标题】:Circular Table with HTML , CSS and JS 【发布时间】:2022-01-20 19:05:15 【问题描述】:

我正在尝试使用 html、JS 和 CSS 重新创建以下内容:

我的目标是能够用我想要的任何内容替换每个圈子中的内容,就像一个表格一样。

到目前为止,我已经阅读了以下帖子 - Circular HTML table。这个有一个答案,但我无法让它工作,它使用了一些 CSS 扩展

阅读完代码后,我尝试自己实现,并且能够做到这一点:

使用以下代码:codepen.io

    function createLayer(radius) 
        let circleGraph = document.createElement("div");
        circleGraph.classList.add("circlegraph");
        circleGraph.style.width = `$radiuspx`;
        circleGraph.style.height = `$radiuspx`;
        for (let j = 0; j < 12; j++) 
            let note = document.createElement("div");
            note.classList.add("circle");
            note.classList.add("center");
            let content = document.createTextNode(`$j`)
            note.appendChild(content);
            circleGraph.appendChild(note);
        
        let circles = circleGraph.querySelectorAll( '.circle' )
        let theta = 0, dtheta = Math.PI * 2 / circles.length
        for( let i = 0; i < circles.length; ++i )
            let circle = circles[i]
            theta += dtheta
            circle.style.transform = `translate(-50%, -50%) rotate($thetarad) translate($radiuspx) `;
            circle.style.transform += `rotate($Math.PI/2rad)`;
        
        document.body.appendChild(circleGraph)
    

    createLayer(100);
    createLayer(150);
    createLayer(200);
    createLayer(250);
    html, body 
        margin: 0;
        height: 100%;
    

    .circlegraph 
        margin: auto;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
    


    .circlegraph .circle 
        position: absolute;
        top: 50%; left: 50%;
        width: 50%;
        height: 50px;
        transform-origin: center;
        border: 1px solid red;
        /*border-radius: 50%;*/
    

    .center
        display: flex;
        justify-content: center;
        align-items: center;
    

我正在寻求一些帮助,使其与原始图像相匹配。如果您知道更好的方法而不是手动翻译每个元素,我很乐意看到它。

【问题讨论】:

使用 SVG 或画布 也许这对你有帮助 - blog.fofwebdesign.co.uk/… 我不知道如何给它一个曲线,但如果你在.circlegraph .circle ... 中添加width:50% 而不是px,这看起来会好一些。我对此提交了修改。 【参考方案1】:

从@HoratioNullbuilt 的评论中获得灵感,我能够对他们链接的示例进行可扩展的修改:

http://blog.fofwebdesign.co.uk/16-circular-segment-pie-chart-menu-experimental

需要对其进行扩展的原因是许多值是硬编码的,例如,您不能在不同的层中包含不同数量的元素。

这里是修改后的结果:

https://codepen.io/cuppajoeman/pen/oNGwxzQ

radial.js

let data =  [
    Array.from(Array(15).keys()).map(String),
    Array.from(Array(13).keys()).map(String),
    Array.from(Array(10).keys()).map(String),
    Array.from(Array(7).keys()).map(String),
    Array.from(Array(4).keys()).map(String),
]

function getRandomHTMLColor() 
    var r = 255*Math.random()|0,
        g = 255*Math.random()|0,
        b = 255*Math.random()|0;
    return 'rgb(' + r + ',' + g + ',' + b + ')';


function createPieMenu() 
    let pieMenu = document.createElement("div");
    pieMenu.id = "pie-menu"
    pieMenu.classList.add("pie-outer");

    let widthDelta = 100/data.length;
    let widthPercentage = 100;

    for (let i = 0; i < data.length; i ++) 
        let dataItem = data[i];
        let numSegments = dataItem.length;
        let segmentAngle = (Math.PI * 2)/numSegments;
        let skewAngle = (Math.PI/2) - segmentAngle;

        let pie = document.createElement("div");
        let pieRotateAngle = (Math.PI/2) - segmentAngle/2;
        pie.classList.add("pie");
        console.log(widthPercentage);

        pie.style.width = `$widthPercentage%`;
        pie.style.background = getRandomHTMLColor();

        pie.style.transform = `translate(-50%,-50%) rotate($pieRotateAnglerad)`;

        let pieList = document.createElement("ul");

        for (let j = 0; j < dataItem.length; j ++) 
            let rotationAngle = segmentAngle * j;
            let dataContent = dataItem[j];
            let pieListItem = document.createElement('li'); // create a new list item
            let pieItemAnchor = document.createElement('a'); // create a new list item

            pieListItem.style.transform = `rotate($rotationAnglerad) skew($skewAnglerad)`;

            pieItemAnchor.appendChild(document.createTextNode(dataContent)); // append the text to the li
            let anchorRotate = segmentAngle/2 - Math.PI/2;
            let anchorSkew = segmentAngle - Math.PI/2;
            pieItemAnchor.style.transform = `skew($anchorSkewrad) rotate($anchorRotaterad)`;

            pieListItem.appendChild(pieItemAnchor);
            pieList.appendChild(pieListItem)
        
        pie.appendChild(pieList);
        pieMenu.appendChild(pie);
        widthPercentage -= widthDelta;
    

    document.body.appendChild(pieMenu);


createPieMenu();

radial.css

html, body 
    margin:0;
    padding:0;
    font:1em/1.75 Verdana, Arial, Helvetica, sans-serif;
    -ms-text-size-adjust:100%;
    -webkit-text-size-adjust:100%


.pie-outer *, .pie-outer 
    padding:0;
    margin:0


.pie-outer 
    position:relative;
    padding-top:100%;
    margin:auto


.pie 
    pointer-events:none;
    position:absolute;
    top:50%;
    left:50%;
    overflow:hidden;
    border:2px solid #000;
    border-radius:50%;


.pie ul 
    list-style-type:none


.pie ul:after 
    content:" ";
    display:block;
    width:100%;
    padding-top:100%


.pie li 
    position:absolute;
    top:-50%;
    left:-50%;
    width:100%;
    height:100%;
    margin-left:-2px;
    margin-top:-2px;
    overflow:hidden;
    border:1px solid #000;
    -webkit-transform-origin:100% 100%;
    -ms-transform-origin:100% 100%;
    transform-origin:100% 100%



.pie a 
    pointer-events:auto;
    font-size:2.125vw;
    /*line-height:170%;*/
    display:block;
    position:absolute;
    top:50%;
    left:50%;
    width:100%;
    height:100%;
    text-decoration:none;
    text-align:center;
    color:#fff;
    -webkit-tap-highlight-color:rgba(0,0,0,0);


.pie a:hover 
    background:rgba(255,255,255,0.25)


@media ( min-width:42em ) 
    /* #### - > 672px - #### */
    .pie-outer 
        padding-top:0;
        width:40em;
        height:40em
    
    .pie a 
        font-size:1em
    


radial.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Circular Menu</title>
    <link rel="stylesheet" href="radial.css">
</head>
<body>
    <script src="radial.js"></script>
</body>
</html>

一些注意事项:

当您的数据列表包含大小为 2 的列表时,上面的代码不起作用,但我还没有说明为什么会发生这种情况(可能某些极端情况适用于大小 1 和 2)。

鼠标悬停效果有一个小错误,即如果您将鼠标悬停在两个相邻部分之间的裂缝上,它将向外突出显示下一层(仅当下一层向外具有不同数量的单元格时才会发生)。

单元格中文本的位置并不完美,问题与行高有关(我已将其注释掉),欢迎修改以修复文本位置。

【讨论】:

只想说,出于兴趣一直在跟踪这个问题,干得好!所有相关人员都做得很好。 哇,那真是太好了。干得好。

以上是关于带有 HTML、CSS 和 JS 的圆表的主要内容,如果未能解决你的问题,请参考以下文章

如何在 WebView Cocoa / Mac OS 上加载带有图像、js 和 css 的本地 html 文件

js怎么解析带有html的数据

基于HTML/CSS/JS的年龄计算器 | 带有免费源码

基于HTML/CSS/JS的年龄计算器 | 带有免费源码

带有 css/js 的 Django“包含”模板

将 Bootstrap 主题(带有自定义 CSS 和 JS 插件)与带有 Webpacker 和 Yarn/NPM 的 Rails 6 集成