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>
6305

被折叠的 条评论
为什么被折叠?



