Teach you how to implement a circular/fan-shaped menu in 2 minutes (basic version)

Teach you how to implement a circular/fan-shaped menu in 2 minutes (basic version)

Preface

The project requires a circular menu. I searched for it online but couldn't find a suitable one, so I wrote a very simple one myself and will optimize it later.

This component is based on react, but the principle is the same.

The expansion effect is as follows:

accomplish

css(less)

@centerIconSize: 30px;

.flex(@justify: flex-start, @align: center) {
    justify-content: @justify;
    align-items: @align;
    display: flex;
}
.sector-menu-wrapper {
    position: relative;
    width: @centerIconSize;
    margin: auto;

    .center-icon {
        .flex(center);
        width: @centerIconSize;
        height: @centerIconSize;
        border-radius: 50%;
        background: rgba(0, 0, 0, 0.3);
        color: white;
        cursor: pointer;
    }

    .sector-item {
        position: absolute;
        .flex(center);
        width: @centerIconSize;
        height: @centerIconSize;
        border-radius: 50%;
        background: rgba(0, 0, 0, 0.3);
        cursor: pointer;
        color: white;
        top: 0;
        left: 0;
        transition: all linear 0.5s;
        transform: translate(0, 0);
        // display: none;
        visibility: hidden;
    }

    .sector-list {
        &.sector-list-active {
            transition: all linear 0.5s;
            .sector-item {
                .flex(center);
                transition: all linear 0.5s;
                transform: translate(0, 0);
                visibility: visible;

                &:first-child {
                    transform: translate(0, -@centerIconSize * 1.5);
                }
        
                &:nth-child(2) {
                    transform: translate(-@centerIconSize * 1.5, 0);
                }
        
                &:nth-child(3) {
                    transform: translate(0, @centerIconSize * 1.5);
                    
                }
            }
        }
    }
}

SectorMenu.js

import React from 'react';

export default class SectorMenu extends React.Component {
    state = {
        direction: 'left',
        sectorMenuVisible: false,
        centerIconSize: 30,
        sectorItemSize: 30,
    }

    /**
     * Show radial menu */
    showSectorMenu = () => {
        const { sectorMenuVisible } = this.state;
        this.setState({
            sectorMenuVisible: !sectorMenuVisible,
        })
    }

    onClickSectorMenuItem = (index) => {
        const { sectorMenuItemFunctions } = this.props;
        if (!sectorMenuItemFunctions || typeof(sectorMenuItemFunctions[index]) !== 'function') {
            return;
        }
        sectorMenuItemFunctions[index]();
    }

    getSectorJsx = () => {
        const { sectorMenuItems } = this.props;

        if (!sectorMenuItems || !Array.isArray(sectorMenuItems) || sectorMenuItems.length === 0) {
            return;
        }

        const styles = {};
        const { sectorMenuVisible } = this.state;

        return sectorMenuItems.map((item, i) => {
            // const styles = {
            // transform: translate(0, -centerIconSize * 2);
            // };

            return (<div
                className={`sector-item ${sectorMenuVisible && 'sector-item-active'}`}
                style={styles}
                onClick={() => this.onClickSectorMenuItem(i)}
                key={i}
            >
                {item}
            </div>)
        });
    }
    render() {
        const { sectorMenuVisible } = this.state;
        return (
            <div className="sector-menu-wrapper">
                <div className="center-icon" onClick={this.showSectorMenu}>
                    {
                        sectorMenuVisible ? 'x' : '···'
                    }
                </div>
                <div className={`sector-list ${sectorMenuVisible && 'sector-list-active'}`}>
                    {this.getSectorJsx()}
                </div>
            </div>
        )
    }
}

Call

<SectorMenu
    sectorMenuItems={['A1', 'A2', 'A3']}
    sectorMenuItemFunctions={[function () {console.log(0)}, function () {console.log(1)}, function () {console.log(2)}]}
/>

expect

I originally wanted to write a flexible distribution, but I got stuck on how to calculate the position. The project time is tight, so I will find time to optimize it another day.

  1. Flexible layout of sectorMenuItem
  2. Flexible display of SectorMenu position (left, right, top, bottom...)

Pitfalls

The transition animation didn't work until I realized it was because I used display:none in the sector-item class. I just needed to use the visibility property instead.

The above is the full content of this article. I hope it will be helpful for everyone’s study. I also hope that everyone will support 123WORDPRESS.COM.

<<:  How to pass the value of the select drop-down box to the id to implement the code

>>:  How to use react-color to implement the front-end color picker

Recommend

Summary of the unknown usage of "!" in Linux

Preface In fact, the humble "!" has man...

express project file directory description and detailed function description

app.js: startup file, or entry file package.json:...

Vue uses the Element el-upload component to step on the pit

Table of contents 1. Basic Use 2. Image quantity ...

How to optimize MySQL index function based on Explain keyword

EXPLAIN shows how MySQL uses indexes to process s...

JavaScript to implement voice queuing system

Table of contents introduce Key Features Effect d...

Analysis of Apache's common virtual host configuration methods

1. Apache server installation and configuration y...

How to clean up data in MySQL online database

Table of contents 01 Scenario Analysis 02 Operati...

A brief analysis of the differences between px, rem, em, vh, and vw in CSS

Absolute length px px is the pixel value, which i...

A brief discussion on MySQL temporary tables and derived tables

About derived tables When the main query contains...

How to filter out duplicate data when inserting large amounts of data into MySQL

Table of contents 1. Discover the problem 2. Dele...

Process parsing of reserved word instructions in Dockerfile

Table of contents 1. What is Dockerfile? 2. Analy...