<template>
<div class="canvas_bubble">
<canvas id="c" width="100%" height="100%"></canvas>
</div>
</template>
<script>
import { Bubble, World } from '@/views/faultDiagnosis/aiForecast/options/bubble'
export default {
name: 'canvasBubble',
data () {
return {
bubbleList: ['支架群协调联动', '安全阀开启识别', '液压阀失效识别', '破碎风险超前预警', '故障诊断事故追忆', '风险自主辨识', '来压风险超前预警', '健康诊断运维策略', '异常识别智能标定'],
}
},
mounted () {
this.init()
},
methods: {
init () {
// 主程序开始
const c = document.getElementById('c') // 获取 canvas 对象
const ctx = c.getContext('2d') // 获取 canvas 的绘图环境进行渲染
const objects = [] // 创建一个数组存储所有的Bubble对象
c.width = 350 // 设置canvas的宽度
c.height = 224 // 设置canvas的高度
const createBubbles = (list, width, height) => {
const maxYVelocity = .8 // 泡泡的最大上升速度
const maxRadius = 42 // 泡泡的最大半径
const minRadius = 23 // 泡泡的最小半径
list.forEach((item, index) => {
const speed = -Math.random() * maxYVelocity
// const speed = -Math.random() * maxYVelocity > -0.2 ? -0.3 : -Math.random() * maxYVelocity
objects.push(new Bubble(Math.random() * width, Math.random() * height, speed, Math.random() * maxRadius + minRadius, Math.random() * 80 - 40, item))
})
}
createBubbles(this.bubbleList, c.width, c.height) // 随机创建20个气泡
const world = new World({ width: c.width, height: c.height, friction: 0.997 }, objects, ctx) // 创建World对象
world.animate() // 开始动画
// 监听特定事件,改变动画的播放/暂停状态
c.addEventListener('mouseenter', () => world.togglePause())
c.addEventListener('mouseleave', () => world.togglePause())
},
},
}
</script>
<style scoped lang="scss">
.canvas_bubble {
width: 100%;
height: 100%;
text-align: center;
canvas {
clip-path: polygon(0% 0%, 100% 0%, 100% 60%, 70% 100%, 30% 100%, 0% 60%, 0% 0%);
}
}
</style>
js 封装
// Bubble 类定义
const backgroundImage = new Image()
backgroundImage.src = require('@/assets/image/aiImages/可识别目标-浮球.png')
export class Bubble {
// 构造函数,初始化Bubble对象的属性
constructor (x, y, speed, radius, swing, title) {
Object.assign(this, { x, y, startX: x, speed, radius, swing, title })
}
// 更新Bubble对象的状态的方法
update (world) {
this.x = this.startX + Math.cos(this.y / 80) * this.swing
this.y += this.speed
if (this.y < -this.radius)
{this.y = world.physicalProperties.height + this.radius}
}
// 在canvas上绘制Bubble对象的方法
render (ctx) {
if (!backgroundImage.complete) {
// 确保图片加载完成
setTimeout(() => this.render(ctx), 50)
return
}
ctx.globalAlpha = this.radius / (0.42 * 100)
const imgX = this.x - this.radius
const imgY = this.y - this.radius
ctx.drawImage(backgroundImage, imgX, imgY, this.radius * 2, this.radius * 2)
// 文字样式设置
let fontSize = this.radius * 0.25
ctx.font = `${ fontSize }px Arial` // 替换为您想要的样式和大小
ctx.textAlign = 'center' // 使文本在气泡中心对齐
ctx.textBaseline = 'middle' // 以气泡中心为基线
ctx.fillStyle = '#fff' // 如果背景很暗,建议使用白色或其他亮色文字
const str1 = this.title.substring(0, 4)
const str2 = this.title.substring(4, this.title.length)
// 绘制文本
ctx.fillText(str1, this.x, this.y - fontSize / 1.8) // '文本内容' 替换为您想要显示的文字
ctx.fillText(str2, this.x, this.y + fontSize / 1.8) // '文本内容' 替换为您想要显示的文字
ctx.globalAlpha = 1 // 设置透明度为0.5
}
}
// World类负责维护Bubble对象与canvas的交互
export class World {
constructor (physicalProperties, objects, ctx) {
Object.assign(this, { physicalProperties, objects, ctx, frameID: 0, paused: false })
}
// 更新所有Bubble对象的状态的方法
update () {
if (!this.paused)
{this.objects.forEach(obj => obj.update(this))}
}
// 清空canvas并重新绘制所有Bubble对象的方法
render () {
const { width, height } = this.physicalProperties
this.ctx.clearRect(0, 0, width, height)
this.objects.forEach(obj => obj.render(this.ctx))
}
// 更新并重新绘制canvas的动画循环
animate () {
this.update()
this.render()
this.frameID = requestAnimationFrame(this.animate.bind(this))
}
// 切换动画的播放/暂停状态的方法
togglePause () {
this.paused = !this.paused
}
}