太极八卦罗盘JS绘制

LeaferJS 是一款好用的 Canvas 引擎,通过LeaferJS绘制罗盘案例.
https://www.leaferjs.com/ui/guide/

示例

太极八卦罗盘

直接上代码


<template>
  <div id="LuoPan"></div>
  <div id="info">
    <p>屏幕宽度: {{ screenWidth }}px</p>
    <p>屏幕高度: {{ screenHeight }}px</p>
    <p>圆心x: {{ centerX }}px</p>
    <p>圆心Y: {{ centerY }}px</p>
    <p>太极半径: {{ tjRadius }}px</p>
    <p>罗盘环宽度: {{ loopWidth }}px</p>
    <p>太极旋转速度: {{ tj_v }}</p>
    <p>先天八卦旋转速度: {{ xtbg_v }}</p>
  </div>
</template>
<script>
import {Leafer, Rect, Ellipse, Group,Text} from 'leafer-ui'
import '@leafer-in/state'
  import { Animate } from '@leafer-in/animate'
  export default {
    name: 'LuoPan',
    data(){
      return {
        screenWidth: 0,// 屏幕宽度
        screenHeight: 0, //屏幕高度
        centerX: 0, //圆心x
        centerY: 0, //圆心Y
        tjRadius: 100, //太极半径
        loopWidth: 50, // 罗盘环宽度
        tj_v: 5, // 太极旋转速度
        xtbg_v: 10, // 先天八卦旋转速度
        htbg_v: 20, // 后天八卦旋转速度
        loopData:{
          xtbg:[
            {code: "011",txt: "巽"},{code: "010",txt: "坎"},{code: "001",txt: "艮"}, {code: "000",txt: "坤"},
            {code: "100",txt: "震"},{code: "101",txt: "离"},{code: "110",txt: "兑"},{code: "111",txt: "乾"},
          ],
          htbg:[
            {code: "000",txt: "坤"},{code: "110",txt: "兑"},{code: "111",txt: "乾"},{code: "010",txt: "坎"},
            {code: "001",txt: "艮"},{code: "100",txt: "震"},{code: "011",txt: "巽"},{code: "101",txt: "离"},

          ],
        }
      };
    },
    mounted() {
      this.updateScreenSize();
      const leafer = new Leafer({
        view: 'LuoPan', // view 参数支持设置 canvas 标签对象
        width: 0, // 不能设置为 0, 否则会变成自动布局
        height: 800,
        fill: 'rgba(255,223,0,1)'
      })
      // 绘制太极
      const groudTaiji  = this.drewTaiji(leafer);
      // 绘制先天八卦
      const groudXtbagua = this.drewLoopXtbg(leafer,8, this.loopData.xtbg,1);
      // 绘制先天八卦
      const groudHtbagua = this.drewLoopHtbg(leafer,8, this.loopData.htbg,2);


    },
    methods: {
      // 获取屏幕长宽
      updateScreenSize() {
        this.screenWidth = window.innerWidth;
        this.screenHeight = window.innerHeight;
        this.centerX = this.screenWidth / 2 - this.tjRadius-200;
        this.centerY = this.screenHeight / 2 - this.tjRadius;
      },
      drewLoopHtbg(leafer,num, htbg,level) {
        const groundHtbg = new Group({
          x: this.centerX+this.tjRadius,
          y: this.centerY+this.tjRadius,
          around: 'center',
          animation:{
            keyframes: [
              {
                x: this.centerX+this.tjRadius,
                y: this.centerY+this.tjRadius,
                rotation: 360,
                cornerRadius: 0
              }
            ],
            easing: 'linear',
            duration: this.htbg_v, // 自动分配剩余的时长给未设置 duration 的关键帧: (3 - 0.5 - 0.2 - 0.1) / 2
            loop: true
          },
        });

        // 画框
        for (let i = 0; i < num; i++) {

          const itemAngle = 360/num;
          const item = Ellipse.one({
            fill: 'rgb(255,146,0,0.2)',
            draggable: false,
            x: this.centerX + this.tjRadius,
            y: this.centerY + this.tjRadius,
            width: this.tjRadius * 2 + this.loopWidth*2*2,
            height: this.tjRadius * 2 + this.loopWidth*2*2,
            startAngle: i*itemAngle,
            endAngle: (i+1)*itemAngle,
            innerRadius: (this.tjRadius+this.loopWidth)/(this.loopWidth*2+this.tjRadius),
            hoverStyle: { // // 鼠标悬停 样式
              fill: 'rgba(255,255,255, 0.8)',
              shadow: {
                x: 0,
                y: 0,
                blur: 30,
                color: 'rgba(255,255,255,0.97)',
                box: true // box-shadow
              }
            }
          });

          // 画爻
          var htbgItem = htbg[i];
          var htbgItemCode = htbgItem['code'];
          var htbgItemTxt = htbgItem['txt'];

          for (let j = 0; j < 3; j++) {
            var arry = htbgItemCode.split("");
            var arryElement = arry[j];
            const tempRadius = this.tjRadius - j*this.loopWidth/5 - this.loopWidth/3 + this.loopWidth*(level-1);

            if(arryElement == '1'){
              const yaoYang = Rect.one({
                zIndex: 10,
                fill: '#fff',
                draggable: false,
                y: this.loopWidth*(level-1) + this.centerY + this.tjRadius * 3 - this.tjRadius / 2 + (this.loopWidth + tempRadius) * Math.sin(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                x: this.loopWidth*(level-1) + this.centerX + this.tjRadius * 3 - this.tjRadius / 2 + (this.loopWidth + tempRadius) * Math.cos(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                width: this.loopWidth/3*2,
                height: this.loopWidth / 9,
                rotation: i * itemAngle + 118,
                around: 'center',
              });
              groundHtbg.add(yaoYang);
            }else{
              const yaoYangOne = Rect.one({
                zIndex: 10,
                fill: '#fff',
                draggable: false,
                x: this.loopWidth*(level-1) + this.centerX + this.tjRadius * 3 - this.tjRadius / 2 + (this.loopWidth + tempRadius) * Math.cos(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                y: this.loopWidth*(level-1) + this.centerY + this.tjRadius * 3 - this.tjRadius / 2 + (this.loopWidth + tempRadius) * Math.sin(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                offsetX: (-this.loopWidth/3*2/5*2+4) * Math.sin(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                offsetY: (this.loopWidth/3*2/5*2-5) * Math.cos(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                width: this.loopWidth/3*2/5*2,
                height: this.loopWidth / 9,
                rotation: i * itemAngle + 117,
                around: 'center',

              });
              groundHtbg.add(yaoYangOne);

              const yaoYangTwo = Rect.one({
                zIndex:  10,
                fill: '#fff',
                draggable: false,
                y: this.loopWidth*(level-1) + this.centerY + this.tjRadius * 3 - this.tjRadius / 2 + (this.loopWidth + tempRadius) * Math.sin(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                x: this.loopWidth*(level-1) + this.centerX + this.tjRadius * 3 - this.tjRadius / 2 + (this.loopWidth + tempRadius) * Math.cos(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                offsetX: (this.loopWidth/3*2/3/5*2 + 5) * Math.sin(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                offsetY: (- this.loopWidth/3*2/5*2 + 4) * Math.cos(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                width: this.loopWidth/3*2/5*2,
                height: this.loopWidth / 9,
                rotation: i * itemAngle + 117,
                around: 'center',

              });
              groundHtbg.add(yaoYangTwo);
            }
          }
          groundHtbg.add(item);
          const tempRadius = this.tjRadius - this.loopWidth/9*6-4 + this.loopWidth;
          const text = new Text({
            fill: '#000',
            text: "     "+htbg[i].txt,
            draggable: false,
            x: this.loopWidth + this.centerX + this.tjRadius * 3 - this.tjRadius / 2 + (this.loopWidth + tempRadius) * Math.cos(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 4)),
            y: this.loopWidth + this.centerY + this.tjRadius * 3 - this.tjRadius / 2 + (this.loopWidth + tempRadius) * Math.sin(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 4)),
            fontSize: 16,
            rotation: i * itemAngle + 290,
          });
          groundHtbg.add(text);
        }


        leafer.add(groundHtbg);
        return groundHtbg;
      },
      drewLoopXtbg(leafer,num, xtbg, level) {
        const groundXtbg = new Group({
          x: this.centerX+this.tjRadius,
          y: this.centerY+this.tjRadius,
          around: 'center',
          animation:{
            keyframes: [
              {
                x: this.centerX+this.tjRadius,
                y: this.centerY+this.tjRadius,
                rotation: 360,
                cornerRadius: 0
              }
            ],
            easing: 'linear',
            duration: this.xtbg_v, // 自动分配剩余的时长给未设置 duration 的关键帧: (3 - 0.5 - 0.2 - 0.1) / 2
            loop: true
          },
        });

        // 画框
        for (let i = 0; i < num; i++) {

          const itemAngle = 360/num;
          const item = Ellipse.one({
            zIndex: 10,
            fill: 'rgba(255,255,255,0.2)',
            draggable: false,
            x: this.centerX + this.tjRadius,
            y: this.centerY + this.tjRadius,
            width: this.tjRadius * 2 + this.loopWidth*2,
            height: this.tjRadius * 2 + this.loopWidth*2,
            startAngle: i*itemAngle,
            endAngle: (i+1)*itemAngle,
            innerRadius: this.tjRadius/(this.loopWidth+this.tjRadius),
            hoverStyle: { // // 鼠标悬停 样式
              fill: 'rgba(255,255,255, 0.8)',
              shadow: {
                x: 0,
                y: 0,
                blur: 30,
                color: 'rgba(255,255,255,0.97)',
                box: true // box-shadow
              }
            }
          });

          // 画爻
          var xtbgItem = xtbg[i];
          var xtbgItemCode = xtbgItem['code'];
          var xtbgItemTxt = xtbgItem['txt'];

          for (let j = 0; j < 3; j++) {
            var arry = xtbgItemCode.split("");
            var arryElement = arry[j];
            const tempRadius = this.tjRadius - j*this.loopWidth/5 - this.loopWidth/3 + this.loopWidth*(level-1);

            if(arryElement == '1'){
              const yaoYang = Rect.one({
                zIndex: 10,
                fill: '#fff',
                draggable: false,
                x: this.centerX + this.tjRadius * 3 - this.tjRadius / 2 + (this.loopWidth + tempRadius) * Math.cos(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                y: this.centerY + this.tjRadius * 3 - this.tjRadius / 2 + (this.loopWidth + tempRadius) * Math.sin(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                width: this.loopWidth/3*2,
                height: this.loopWidth / 9,
                rotation: i * itemAngle + 118,
                around: 'center',

              });
              groundXtbg.add(yaoYang);
            }else{
              const yaoYangOne = Rect.one({
                zIndex: 10,
                fill: '#fff',
                draggable: false,
                x: this.loopWidth*(level-1) + this.centerX + this.tjRadius * 3 - this.tjRadius / 2 + (this.loopWidth + tempRadius) * Math.cos(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                y: this.loopWidth*(level-1) + this.centerY + this.tjRadius * 3 - this.tjRadius / 2 + (this.loopWidth + tempRadius) * Math.sin(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                offsetX: (-this.loopWidth/3*2/5*2+4) * Math.sin(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                offsetY: (this.loopWidth/3*2/5*2-5) * Math.cos(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                width: this.loopWidth/3*2/5*2,
                height: this.loopWidth / 9,
                rotation: i * itemAngle + 117,
                around: 'center',

              });
              groundXtbg.add(yaoYangOne);

              const yaoYangTwo = Rect.one({
                fill: '#fff',
                draggable: false,
                y: this.loopWidth*(level-1) + this.centerY + this.tjRadius * 3 - this.tjRadius / 2 + (this.loopWidth + tempRadius) * Math.sin(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                x: this.loopWidth*(level-1) + this.centerX + this.tjRadius * 3 - this.tjRadius / 2 + (this.loopWidth + tempRadius) * Math.cos(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                offsetX: (this.loopWidth/3*2/3/5*2 + 5) * Math.sin(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                offsetY: (- this.loopWidth/3*2/5*2 + 4) * Math.cos(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 3)),
                width: this.loopWidth/3*2/5*2,
                height: this.loopWidth / 9,
                rotation: i * itemAngle + 117,
                around: 'center',

              });
              groundXtbg.add(yaoYangTwo);
            }
          }
          groundXtbg.add(item);
          const tempRadius = this.tjRadius - this.loopWidth/9*6-4 + this.loopWidth*(level-1);
          const text = new Text({
            fill: '#000',
            text: "     "+xtbg[i].txt,
            draggable: false,
            x: this.loopWidth*(level-1) + this.centerX + this.tjRadius * 3 - this.tjRadius / 2 + (this.loopWidth + tempRadius) * Math.cos(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 4)),
            y: this.loopWidth*(level-1) + this.centerY + this.tjRadius * 3 - this.tjRadius / 2 + (this.loopWidth + tempRadius) * Math.sin(Math.PI / 180 * (itemAngle * i + itemAngle / 2 + 4)),
            fontSize: 16,
            rotation: i * itemAngle + 290,
          });
          groundXtbg.add(text);
        }


        leafer.add(groundXtbg);
        return groundXtbg;
      },
      // 画太极
      drewTaiji(leafer){
        const groundTaiji = new Group({
          x: this.centerX+this.tjRadius,
          y: this.centerY+this.tjRadius,
          around: 'center',
          animation:{
            keyframes: [
              {
                x: this.centerX+this.tjRadius,
                y: this.centerY+this.tjRadius,
                rotation: 360,
                cornerRadius: 0
              }
            ],
            easing: 'linear',
            duration: this.tj_v, // 自动分配剩余的时长给未设置 duration 的关键帧: (3 - 0.5 - 0.2 - 0.1) / 2
            loop: true
          }
        });

        //太极大扇形-右边黑
        const tjBai = Ellipse.one({
          fill: '#000',
          draggable: false,
          x: this.centerX+this.tjRadius,
          y: this.centerY+this.tjRadius,
          width: this.tjRadius*2,
          height: this.tjRadius*2,
          startAngle: -90,
          endAngle: 90,
          shadow: {
            x: 0,
            y: 0,
            blur: 20,
            color: 'rgba(255,255,255,0.97)',
            box: true // box-shadow
          },
        });
        groundTaiji.add(tjBai);

        //太极大扇形-左边白
        const tjHei = Ellipse.one({
          fill: '#fff',
          draggable: false,
          x: this.centerX+this.tjRadius,
          y: this.centerY+this.tjRadius,
          width: this.tjRadius*2,
          height: this.tjRadius*2,
          startAngle: 90,
          endAngle: 270,
          shadow: {
            x: 0,
            y: 0,
            blur: 20,
            color: 'rgba(255,255,255,0.97)',
            box: true // box-shadow
          },
        })
        groundTaiji.add(tjHei);

        //太极中圆-白
        const tjZhongyuanBai = Rect.one({
          fill: '#fff',
          draggable: false,
          x: this.centerX+this.tjRadius*3/2,
          y: this.centerY+this.tjRadius,
          width: this.tjRadius,
          height: this.tjRadius,
          cornerRadius: this.tjRadius/2,
        });
        groundTaiji.add(tjZhongyuanBai);


        //太极中圆-黑
        const tjZhongyuanHei = Rect.one({
          fill: '#000',
          draggable: false,
          x: this.centerX+this.tjRadius*3/2,
          y: this.centerY+this.tjRadius*2,
          width: this.tjRadius,
          height: this.tjRadius,
          cornerRadius: this.tjRadius/2,
        });
        groundTaiji.add(tjZhongyuanHei);

        //太极小圆-白
        const tjXiaoyuanBai = Rect.one({
          fill: '#000',
          draggable: false,
          x: this.centerX+this.tjRadius*2 - this.tjRadius/6,
          y: this.centerY+this.tjRadius*3/2-this.tjRadius/6,
          width: this.tjRadius/6*2,
          height: this.tjRadius/6*2,
          cornerRadius: this.tjRadius/6,
        });
        groundTaiji.add(tjXiaoyuanBai);

        //太极小圆-黑
        const tjXiaoyuanHei = Rect.one({
          fill: '#fff',
          draggable: false,
          x: this.centerX+this.tjRadius*2 - this.tjRadius/6,
          y: this.centerY+this.tjRadius*2+this.tjRadius/2-this.tjRadius/6,
          width: this.tjRadius/6*2,
          height: this.tjRadius/6*2,
          cornerRadius: this.tjRadius/6,
        });
        groundTaiji.add(tjXiaoyuanHei);
        leafer.add(groundTaiji);
      }
    }
  };

</script>

<style scoped>
  #info{
    position: absolute;
    right: 100px;
    top: 10px;
    width: 200px;
    background-color: rgba(50, 205, 120, 0.5);
    color: white;
    padding-left: 10px;
  }
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值