简体   繁体   中英

Circular Table with HTML , CSS and JS

I'm trying to re-create the following with HTML, JS & CSS:

在此处输入图像描述

My goal is to be able to replace the content in each of the circles with whatever I want, just like a table.

So far I've read the following post - Circular HTML table . This one has an answer but I wasn't able to get it working and it uses some CSS extension

After reading the code I tried to make my own implementation, and was able to get to this point:

在此处输入图像描述

with the following code: codepen.io

 function createLayer(radius) { let circleGraph = document.createElement("div"); circleGraph.classList.add("circlegraph"); circleGraph.style.width = `${radius}px`; circleGraph.style.height = `${radius}px`; 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(${theta}rad) translate(${radius}px) `; circle.style.transform += `rotate(${Math.PI/2}rad)`; } 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; }

I'm looking to get some help making it match the original image. If you know of a better way of doing this rather than translating each element by hand I would love to see it.

Taking inspiration from @HoratioNullbuilt's comment I was able to make an extensible modification of the example they had linked:

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

The reason why it needed to be extended was that the many of the values were hardcoded, for example you couldn't have different layers with different numbers of elements in them.

After the modification here is the result:

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(${pieRotateAngle}rad)`;

        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(${rotationAngle}rad) skew(${skewAngle}rad)`;

            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(${anchorSkew}rad) rotate(${anchorRotate}rad)`;

            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>

Some notes:

The above code doesn't work when there your data list contains a list of size two, but I haven't gone into why that might happen (probably some edge case work for sizes 1 and 2).

The mouse hover effect has a slight bug which is that if you hover on the crack between two adjacent sections, it will highlight the next layer outward (only seems to happen if the next layer outward has a different number of cells).

The location of the text in the cells is not perfect, the problem is something to do with the line-height (which I commented out), modifications to fix the text position are welcome.

Taking inspiration from @cuppajoeman--

if you modify the Array builders your cells can contain what ever you want. Just remove the '.keys()' function as it turns everything into numbers, and put actual data instead of numbers in the second 'Array()'

You can also add and remove 'Array.from(Array()' lines and the whole thing will auto-adjust.

let data =  [
//    Array.from(Array(32).keys()).map(String),
//    Array.from(Array(32).keys()).map(String),
//    Array.from(Array(16).keys()).map(String),
//    Array.from(Array(4).keys()).map(String),
//    Array.from(Array(1).keys()).map(String),

// ************************************
// *** trying to put text in boxes  ***
// ************************************
            
Array.from(Array("1","2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32")).map(String),
Array.from(Array("Nehrdas", "Jahdas", "Gahldas", "Dehrdas", "Elimdas", "Iadas", "Zepdas", "Makda", "Nehrdas", "Jahdas", "Gahldas", "Dehrdas", "Elimdas", "Iadas", "Zepdas", "Makda", "Nehrdas", "Jahdas", "Gahldas", "Dehrdas", "Elimdas", "Iadas", "Zepdas", "Makda", "Nehrdas", "Jahdas", "Gahldas", "Dehrdas", "Elimdas", "Iadas", "Zepdas", "Makda")).map(String),
Array.from(Array("Solaris", "Seprensdor", "Fonsoc", "Ganrehm", "Calidum", "Somnercrest", "Aesoc", "Jehmri", "Lunaris", "Autunsveil", "Cadoc", "Nehnma", "Frigus", "Wevnercrest", "Hemoc", "Duhmret")).map(String),
Array.from(Array(16)).map(String),
Array.from(Array(4)).map(String),
        
// ************************************
// *** END trying to put text in boxes  ***
// ************************************

]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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