JavaScript 八卦

来源:互联网 发布:淘宝宝贝创建时间查询 编辑:程序博客网 时间:2024/05/02 02:18
<html>    <head>        <meta charset="utf8" />        <title>伏羲八卦</title>        <style type="text/css">            #canvas {                background-color:yellow;            }        </style>    </head>    <body>        <canvas id="canvas" width="950" height="950">This browser does not support canvas tag</canvas>        <script type="text/javascript">            var c = document.getElementById("canvas");            var ctx = c.getContext("2d");            //太极中心点X坐标            var centerX = c.width / 2;            //太极中心点Y坐标            var centerY = c.height / 2;            //阴阳鱼(左阳右阴)形环转相抱的太极图的半径,大圈通神            var radius = 200;            //鱼头半径,中圈通气            var fishHeadRadius = radius / 2;            //鱼眼半径,小圈养精            var fisheyeRadius = radius / 6;            //当前弧度数(从0点钟方向为起始,顺时针方向为正,初始图像为左阳右阴)            var radian = 0;            //2 * Math.PI弧度切割的总份数            var radianCount = 720;            //2 * Math.PI长度,避免重复计算            var doublePI = Math.PI * 2;            var halfPI = Math.PI * 0.5;            //弧度步长            var radianStep = doublePI / radianCount;            //八卦间隔弧度            var eightCombinationRadiusStep = doublePI / 8;            //八卦间隔弧度的一半            var eightCombinationRadiusHalfStep = doublePI / 16;            var sinEightCombinationRadiusHalfStep = Math.sin(eightCombinationRadiusHalfStep);            var cosEightCombinationRadiusHalfStep = Math.cos(eightCombinationRadiusHalfStep);            //八卦内径            var eightCombinationInnerDiameter = radius + 0;            //八卦的正八边形的外切圆半径            var eightCombinationOutsideDiameter = eightCombinationInnerDiameter + 150;            //八卦的正八边形边框线宽            var eightCombinationRegularOctagonLineWidth = 15;            //八卦内径到正八边形的最短距离            var eightCombinationInnerDiameterToRegularOctagonDistance = (eightCombinationOutsideDiameter - eightCombinationRegularOctagonLineWidth / 2) * cosEightCombinationRadiusHalfStep - eightCombinationInnerDiameter;            //八卦线断开的间隔            var eightCombinationLineBreakLength = 15;            //八卦线宽            var eightCombinationLineWidth = eightCombinationInnerDiameterToRegularOctagonDistance / 7;            //八卦线两端与圆心连成的三角形在圆心处的弧度的一半            var eightCombinationLineHalfTriangleRadius = new Float32Array(3);            //八卦线两端到圆心的距离            var eightCombinationLineEndRadius = new Float32Array(3);            //八卦线条类型(外0x04,中0x02,内0x01; 1表示完整,0表示中间断开)            //var eightCombinationLineTypes = new Uint8Array([111,110,010,100,000,001,101,011]);            var eightCombinationLineTypes = new Uint8Array([7,6,2,4,0,1,5,3]);            //初始化八卦线数据            function initEightCombinationLine() {                //八卦线长(二分之一的外框长)                var eightCombinationLineLength = eightCombinationOutsideDiameter * sinEightCombinationRadiusHalfStep;                //内径到八卦线,再到正八边形的距离比例                var distanceRates = [1.5, 3.5, 5.5];                for(var i=0; i<3; i++) {                    var eightCombinationLineCenterRadius = eightCombinationInnerDiameter + eightCombinationLineWidth * distanceRates[i];                    eightCombinationLineHalfTriangleRadius[i] = Math.atan(eightCombinationLineLength / 2 / eightCombinationLineCenterRadius);                    eightCombinationLineEndRadius[i] = eightCombinationLineCenterRadius / Math.cos(eightCombinationLineHalfTriangleRadius[i]);                }            }            //辅助线宽            var auxiliaryLineWidth = 1;            //八卦字体            var eightCombinationFont = "bold 22pt 'Microsoft YaHei',SimHei,FangSong,KaiTi,YouYuan blue";            //八卦字体颜色            var eightCombinationFontColor = "black";            //八卦方位文字的半径            var eightCombinationDirectionTextRadius = eightCombinationOutsideDiameter + 20;            //八卦文字的半径            var eightCombinationTextRadius = eightCombinationDirectionTextRadius + 40;            //八卦宫号            var eightCombinationNumRadius = eightCombinationTextRadius + 40;            //八卦方向文字            var eightCombinationDirectionTexts = ["南","西南","西","西北","北","东北","正","东南",];            //八卦文字            var eightCombinationTexts = ["乾(天)","巽xun(风)","坎(水)","艮gen(山)","坤(地)","震(雷)","离(火)","兑(沼泽)",];            //八卦宫号            var eightCombinationNums = ["一","五","六","七","八","四","三","二","一",];             //阳鱼鱼眼X坐标            var whiteFisheyeX;            //阳鱼鱼眼Y坐标            var whiteFisheyeY;            //阴鱼鱼眼X坐标            var blackFisheyeX;            //阴鱼鱼眼Y坐标            var blackFisheyeY;            //画弧            function fillArc(cx, cy, r, startRadian, endRadian, color) {                ctx.fillStyle = color;                ctx.beginPath();                ctx.arc(cx, cy, r, startRadian, endRadian);                ctx.fill();            }            //描圆            function strokeCircle(cx, cy, r, color, lineWidth) {                ctx.fillStyle = color;                ctx.lineWidth = lineWidth;                ctx.beginPath();                ctx.arc(cx, cy, r, 0, doublePI);                ctx.stroke();            }            //绘制经过圆心的直径            function strokeCircleDiameter(cx, cy, r, rad, color, lineWidth) {                ctx.strokeStyle = color;                ctx.lineWidth = lineWidth                var sinRad = Math.sin(rad);                var cosRad = Math.cos(rad);                ctx.beginPath();                ctx.moveTo(cx + r * sinRad, cy - r * cosRad);                ctx.lineTo(cx - r * sinRad, cy + r * cosRad)                ctx.stroke();            }            //在圆上绘制文字            function fillCircleText(cx, cy, r, rad, color, font, text) {                ctx.fillStyle = color;                ctx.font = font;                ctx.textAlign = "center";                ctx.fillText(text, cx + r * Math.sin(rad), cy - r * Math.cos(rad));            }            //绘制八卦的某一条线            function strokeEightCombination(cx, cy, r, rad, halfTriangleRad, color, lineWidth, isBreak, breakLength) {                ctx.strokeStyle = color;                ctx.lineWidth = lineWidth;                var rad1 = rad - halfTriangleRad;                var rad2 = rad + halfTriangleRad;                var x1 = cx + r * Math.sin(rad1);                var y1 = cy - r * Math.cos(rad1);                var x2 = cx + r * Math.sin(rad2);                var y2 = cy - r * Math.cos(rad2);                ctx.beginPath();                ctx.moveTo(x1, y1);                if(isBreak !== undefined && isBreak === true && breakLength !== undefined && breakLength > 0) {                    //这里不能用"向量夹角公式": con(@) = b*c/(|b|*|c|)来求夹角,因为同一个cos值有两个角与之对应                    //因此这里要用相似三角形公式                    var midX = (x1 + x2) / 2;                    var midY = (y1 + y2) / 2;                    var dx = x2 - x1;                    var dy = y2 - y1;                    var len = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));                    var halfBreakPercentage = breakLength / len / 2;                    var halfBreakX = dx * halfBreakPercentage;                    var halfBreakY = dy * halfBreakPercentage;                                      var midX1 = midX - halfBreakX;                    var midY1 = midY - halfBreakY;                    var midX2 = midX + halfBreakX;                    var midY2 = midY + halfBreakY;                    ctx.lineTo(midX1, midY1);                    ctx.moveTo(midX2, midY2);                }                ctx.lineTo(x2, y2);                ctx.stroke();            }            //更新            function update() {                //radian = 0;                radian += radianStep;                if(radian >= doublePI) {                    radian = 0;                }                whiteFisheyeX = centerX + fishHeadRadius * Math.sin(radian);                whiteFisheyeY = centerY - fishHeadRadius * Math.cos(radian);                blackFisheyeX = centerX - fishHeadRadius * Math.sin(radian);                blackFisheyeY = centerY + fishHeadRadius * Math.cos(radian);            }            //渲染            function render() {                ctx.clearRect(0, 0, c.width, c.height);                var rad;                //八卦外边框                ctx.lineWidth = eightCombinationRegularOctagonLineWidth;                ctx.fillStyle = "black";                ctx.beginPath();                rad = radian - eightCombinationRadiusHalfStep;                for(var i=0; i < 8; i++, rad += eightCombinationRadiusStep) {                    if(i == 0) {                        ctx.moveTo(centerX + eightCombinationOutsideDiameter * Math.sin(rad), centerY - eightCombinationOutsideDiameter * Math.cos(rad));                    } else {                        ctx.lineTo(centerX + eightCombinationOutsideDiameter * Math.sin(rad), centerY - eightCombinationOutsideDiameter * Math.cos(rad));                    }                }                ctx.closePath();                ctx.stroke();                //八卦分隔线                rad = radian - eightCombinationRadiusHalfStep;                for(var i = 0; i < 4; i++, rad += eightCombinationRadiusStep) {                    strokeCircleDiameter(centerX, centerY, eightCombinationOutsideDiameter, rad, "black", auxiliaryLineWidth);                }                //八卦内环                //strokeCircle(centerX, centerY, eightCombinationInnerDiameter, auxiliaryLineWidth, "black");                //八卦外环                //strokeCircle(centerX, centerY, eightCombinationOutsideDiameter, auxiliaryLineWidth, "black");                //阳鱼                fillArc(centerX, centerY, radius, halfPI + radian, Math.PI + halfPI + radian, "white");                //阴鱼                fillArc(centerX, centerY, radius, -1 * halfPI + radian, halfPI + radian, "black");                //阳鱼头                fillArc(whiteFisheyeX, whiteFisheyeY, fishHeadRadius, 0, doublePI, "white");                //阴鱼头                fillArc(blackFisheyeX, blackFisheyeY, fishHeadRadius, 0, doublePI, "black");                //阳鱼眼                fillArc(blackFisheyeX, blackFisheyeY, fisheyeRadius, 0, doublePI, "white");                //阴鱼眼                fillArc(whiteFisheyeX, whiteFisheyeY, fisheyeRadius, 0, doublePI, "black");                //八卦                rad = radian;                for(var i=0; i < 8; i++, rad += eightCombinationRadiusStep) {                    for(var j=0; j<3; j++) {                        var isBreak = (eightCombinationLineTypes[i] & (1 << j)) === 0;                        strokeEightCombination(centerX, centerY, eightCombinationLineEndRadius[j], rad, eightCombinationLineHalfTriangleRadius[j], "black", eightCombinationLineWidth, isBreak, eightCombinationLineBreakLength);                    }                }                //八卦文字                ctx.save();                //ctx.translate把画布原点平移到(x,y)                ctx.translate(centerX, centerY);                //注意: 旋转的弧度是"画布"从要绘制的目标点旋转到原来的点的弧度,也可以说是原来的点旋转到目标点的相反数.                ctx.rotate(radian - Math.PI);                for(var i=0; i < 8; i++, ctx.rotate(eightCombinationRadiusStep)) {                    fillCircleText(0, 0, eightCombinationTextRadius, Math.PI, eightCombinationFontColor, eightCombinationFont, eightCombinationTexts[i]);                    fillCircleText(0, 0, eightCombinationDirectionTextRadius, Math.PI, eightCombinationFontColor, eightCombinationFont, eightCombinationDirectionTexts[i]);                    fillCircleText(0, 0, eightCombinationNumRadius, Math.PI, eightCombinationFontColor, eightCombinationFont, eightCombinationNums[i]);                }                ctx.restore();            }            function loop() {                update();                render();                window.requestAnimationFrame(loop);            }            function init() {                initEightCombinationLine();                loop();            }            init();        </script>    </body></html>

这里写图片描述

2 0