概述
基于three.js的3d饼图
使用
<template>
<div id="app">
<three-pie
ref="pie"
:data="pieData"
:delay="3000"
:colors="[0x3da6ff, 0x2ceef5, 0xf2c62a, 0x26c7b7, 0xff823b]"
:opacity="0.7"
class="pieCanvas"
>
<template v-slot:default="slotProps">
<div class="pieCanvas-content">
<div class="pieCanvas-content-value">
<count-to
ref="countTo"
:startVal="0"
:endVal="getNumber(slotProps)"
:decimals="2"
:duration="1000"
:autoplay="true"
></count-to>
%
</div>
<div class="pieCanvas-content-name">{{ slotProps.data.name }}</div>
</div>
</template>
</three-pie>
</div>
</template>
<script>
import ThreePie from '@/components/threePie'
import CountTo from '@/components/CountTo'
export default {
components: {
ThreePie,
CountTo,
},
data() {
return {
pieData: [
{
name: '搜索引擎',
value: 22,
},
{
name: '邮件',
value: 23,
},
{
name: '广告',
value: 27,
},
{
name: '视频广告',
value: 19,
},
{
name: '地推',
value: 25,
},
],
}
},
methods: {
getNumber(slotProps) {
return Number(((slotProps.data.value / slotProps.data.count) * 100).toFixed(2))
}
},
}
</script>
<style lang="scss">
* {
padding: 0;
margin: 0;
}
html,
body,
#app {
background-color: #000;
width: 100%;
height: 100%;
overflow: hidden;
}
#app {
display: flex;
justify-content: center;
align-items: center;
}
.pieCanvas {
background-color: #111;
width: 400px;
}
.pieCanvas-content {
width: 100px;
height: 100px;
margin-bottom: 30px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: #fff;
font-size: 14px;
&-value {
font-size: 24px;
font-weight: bold;
text-shadow: 0 0 10px rgb(0 0 0);
}
&-name {
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: #999;
text-align: center;
}
}
.top-tools {
position: absolute;
top: 0;
left: 0;
right: 0;
background: #222;
color: #fff;
a {
padding: 10px 10px;
}
}
</style>
部分代码解析
1.圆环旋转
外层装饰是由3个贴图组合而成,中间圆环旋转使用了TWEEN,沿着z轴旋转
// 创建饼图外层3个圆环
this.createPlane({
url: 'texture/ring2.png',
width: 5,
position: new THREE.Vector3(0, 0, -0.01),
color: '#00ffff',
})
this.createPlane({
url: 'texture/ring3.png',
width: 6.5,
position: new THREE.Vector3(0, 0, -0.02),
color: '#00ffff',
})
this.createPlane({
url: 'texture/ring4.png',
width: 5.5,
position: new THREE.Vector3(0, 0, -0.03),
animate: true,
color: '#00ffff',
})
createPlane(opt) {
let defaultOpt = {
url: 'texture/ring1.png',
width: 5.5,
z: 0,
position: new THREE.Vector3(0, 0, 0),
animate: false,
color: null,
}
let options = Object.assign(defaultOpt, opt)
const geometry = new THREE.PlaneBufferGeometry(options.width, options.width)
const material = new THREE.MeshBasicMaterial({
map: this.getTexture(options.url),
transparent: true,
side: THREE.DoubleSide,
depthTest: false,
})
if (options.color) {
material.color = new THREE.Color(options.color)
}
const mesh = new THREE.Mesh(geometry, material)
mesh.position.copy(options.position)
mesh.rotation.x = (-1 * Math.PI) / 2
// 如果设置了动画,沿Z轴旋转
if (options.animate) {
new TWEEN.Tween({ z: 0 })
.to({ z: 2 * Math.PI })
.repeat(Infinity)
.onUpdate(obj => {
mesh.rotation.z = obj.z
})
.start()
}
scene.add(mesh)
},
2.饼图
// 通过数据,计算出百分比,再计算出每个环的开始角度和起始角度
createPie() {
let startAngle = 0
let endAngle = 0
for (var i = 0; i < this.data.length; i++) {
let percent = this.data[i].value / this.count
if (i == 0) {
startAngle = 0
} else {
startAngle = endAngle + 0.0001
}
endAngle = endAngle + 2 * Math.PI * percent - 0.0001
let ring = this.addRing({
startAngle: startAngle,
endAngle: endAngle,
color: this.colors[i % this.colors.length],
})
ring.name = 'ring' + i
pieGroup.add(ring)
}
scene.add(pieGroup)
this.chooseRing(this.activeIndex, true)
this.timer = setInterval(() => {
this.loopChange()
}, this.delay)
},
获取完整源码可咸鱼搜索:three.js饼图
最后
以上就是活力夕阳为你收集整理的封装的three.js饼图vue组件的全部内容,希望文章能够帮你解决封装的three.js饼图vue组件所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复