js实现圆角矩形(非canvas)

image

代码

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>矩形</title>
    <link rel="stylesheet" href="">
    <style>
        .juxing{
            /* 加上css会很奇怪-。-*/
            /* transition:all 0.1s ease-in; */
        }
    </style>
</head>

<body>
    <button type="button" onclick="start()">点击</button>
    <script>
    const len = 50;
    let array = [];
    let time = null;

    function start() {
        clearInterval(time);
        time = setInterval(() => {
            huanwei();
        }, 100);
    }

    function huanwei() {
        array.unshift(array.pop());
        var els = document.querySelectorAll('.juxing');
        for (let i = 0; i < len; i++) {
            let el = document.getElementById('ip' + (i + 1));
            if (array[i] && array[i].point) {
                let point = array[i].point;
                el.style.left = point.x + 'px';
                el.style.top = point.y + 'px';
            }
        }
    }

    function createNode(name, p) {
        // 填充div
        let x = p.x;
        let y = p.y;

        var createDiv = document.createElement("div");
        // 动态
        createDiv.id = name;
        createDiv.style.left = p.x + 'px';
        createDiv.style.top = p.y + 'px';
        createDiv.innerHTML = name;
        // 固定
        if (name !== 'yuan') {
            // 存储非圆心的所有坐标点
            createDiv.className = "juxing"
            let obj = {
                id: name,
                point: { x: p.x, y: p.y }
            }
            array.push(obj);
        }
        createDiv.style.position = "absolute";
        createDiv.style.width = "30px";
        createDiv.style.height = "30px";
        createDiv.style.borderRadius = "30px";
        // border-radius: 30px;
        createDiv.style.background = "pink";
        createDiv.style.border = "1pxsolidred";
        document.body.appendChild(createDiv);
    }

    initNode({
        len: len,
        rectW: 400,
        rectH: 300,
        p: {
            x: 400,
            y: 200
        }
    });

    function initNode(params) {
        //初始化圆角矩形

        // 数量
        let len = params.len || 100;
        // 设置圆角矩形内矩形宽高 ,
        let rectW = params.rectW || 700;
        let rectH = params.rectH || 900;
        // 中心
        let cx = params.p.x || 0;
        let cy = params.p.y || 0;

        /*
         * 思路:圆角矩形可以看作一个矩形和左右两个半圆组成,半径为矩形的一半;
         * 圆周长+矩形两边的长度 / 总数量 计算出各边应该存放的小车数量,以此数量为基准判断该绘制哪一块;
         *
         * o = (180 / arcLenSplit) * Math.PI / 180
         * l=nπr/180 弧长公式
         * l = n(圆心角)× π(圆周率)× r(半径)/180=α(圆心角弧度数)× r(半径)
         * 这里的象限为4321,为(1,1),(1,-1),(-1,-1),(-1,1)
         * 
         */



        // 圆半径
        let radius = rectH / 2;

        // 两边弧长相等为
        let arcLength = Math.PI * radius;
        // 圆弧*2 + 矩形顶边底边长度除以总数量
        let split = ((arcLength * 2) + (rectW * 2)) / len;
        // 矩形边长可以存放数量,均分
        let sideLenCount = Math.round(rectW / split);
        //弧长可以存放小车数量 
        let arcLenSplit = Math.round(arcLength / split);
        // 
        let lineSplit = rectW / sideLenCount

        //每一个BOX对应的角度;
        // var avd = 180 / arcLenSplit;
        //每一个BOX对应的弧度;
        // let o = avd * Math.PI / 180;


        // 再次尝试,改掉以角度划分为以数量来划分,
        var count = 0;
        var count2 = 0;

        // 画圆心,主要绘制的时候观察使用,后期删除
        createNode('yuan', { x: cx, y: cy });
        // 左下角
        let p1 = { x: -rectW / 2, y: rectH / 2, i: 0 };
        let p2 = { x: rectW / 2, y: -rectH / 2, i: 0 }


        //思路:计算矩形周长,处以数量值;先从左下角开始,每次叠加x,如果超过矩形下方长度,则切换至圆形弧度绘制,还是只能以是否在矩形上来判断该绘制矩形横轴或者圆形
        for (var j = 1; j <= len; j++) {
            if (j <= sideLenCount) {
                //绘制矩形底边 外面为计算总共拆分,里面重新计算分到的 边长/数量
                let x = p1.x + getSplit(lineSplit, p1.i)
                let y = p1.y;
                p1.i++;
                createNode('ip' + j, { x: x + cx, y: y + cy });
            } else if (j > sideLenCount && j <= (sideLenCount + arcLenSplit)) {
                // 绘制右侧圆弧
                let ang = 180 / arcLenSplit;
                let hd = getSplit(ang, count) * Math.PI / 180;
                count++;
                let yuanx = radius * Math.sin(hd) + cx + (rectW / 2);
                let yuany = radius * Math.cos(hd) + cy;
                createNode('ip' + j, { x: yuanx, y: yuany });
            } else if (j > (sideLenCount + arcLenSplit) && j <= (sideLenCount + sideLenCount + arcLenSplit)) {
                // 矩形顶部
                let x = p2.x - getSplit(lineSplit, p2.i)
                y = p2.y;
                p2.i++;
                createNode('ip' + j, { x: x + cx, y: y + cy });
            } else {
                //剩余
                let remaining = len - (sideLenCount * 2) - arcLenSplit;
                let ang = getSplit(180 / remaining, count2) * Math.PI / 180;
                // 貌似是加上180度弧度的意思?
                let hd = ang + (Math.PI / 180 * 180);
                count2++;
                let yuanx = radius * Math.sin(hd) + cx - (rectW / 2);
                let yuany = radius * Math.cos(hd) + cy;
                createNode('ip' + j, { x: yuanx, y: yuany });
            }
        }

        function getSplit(split, count) {
            // 2,6,10,14方式均分排列
            return (split / 2) + (count * split)
        }

    }
    </script>
</body>

</html>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容