123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- <template>
- <view class="page-body">
- <canvas id="canvas" class="canvas"></canvas>
- </view>
- </template>
- <script setup>
- class Ball {
- private width : number
- private height : number
- public x : number
- public y : number
- public vx : number
- public vy : number
- public radius : number = 5
- constructor(w : number, h : number, x : number, y : number, vx : number, vy : number) {
- this.width = w
- this.height = h
- this.x = x
- this.y = y
- this.vx = vx
- this.vy = vy
- }
- move() {
- this.x += this.vx
- this.y += this.vy
- // 边框反弹
- if (this.x < this.radius) {
- this.vx = Math.abs(this.vx)
- return
- }
- if (this.x > this.width - this.radius) {
- this.vx = -Math.abs(this.vx)
- }
- if (this.y < this.radius) {
- this.vy = Math.abs(this.vy)
- return
- }
- if (this.y > this.width - this.radius) {
- this.vy = -Math.abs(this.vy)
- }
- }
- }
- class BallAnimation {
- private ctx : CanvasRenderingContext2D
- private ballList : Array<Ball> = []
- private speed = 3
- private layer = 3
- private ballInlayer = 20
- private interval : number = 0
- private runningFlag : boolean = false
- // #ifdef WEB
- private _bindAnimate: Function = null
- // #endif
- constructor(ctx : CanvasRenderingContext2D) {
- this.ctx = ctx
- this.initBall()
- this.ctx.fillStyle = '#007AFF'
- // #ifdef WEB
- this._bindAnimate = this.animate.bind(this)
- // #endif
- }
- private getDistance(x : number, y : number) : number {
- return Math.pow((Math.pow(x, 2) + Math.pow(y, 2)), 0.5)
- }
- private initBall() {
- const canvasWidth = this.ctx.canvas.offsetWidth;
- const canvasHeight = this.ctx.canvas.offsetHeight;
- for (let i = 0; i < this.layer; i++) {
- let radius = this.getDistance(canvasWidth / 2, canvasHeight / 2) / this.layer * i
- for (let j = 0; j < this.ballInlayer; j++) {
- let deg = j * 2 * Math.PI / this.ballInlayer,
- sin = Math.sin(deg),
- cos = Math.cos(deg),
- x = radius * cos + canvasWidth / 2,
- y = radius * sin + canvasHeight / 2,
- vx = this.speed * cos,
- vy = this.speed * sin
- this.ballList.push(new Ball(canvasWidth, canvasHeight, x, y, vx, vy))
- }
- }
- }
- public animate() {
- this.ctx.clearRect(0, 0, this.ctx.canvas.offsetWidth, this.ctx.canvas.offsetHeight)
- this.ballList.forEach((item) => {
- item.move()
- this.ctx.beginPath()
- this.ctx.arc(item.x, item.y, item.radius, 0, 2 * Math.PI)
- // this.ctx.ellipse(item.x, item.y, item.radius, item.radius, 0, 0, Math.PI * 2)
- this.ctx.fill()
- })
- // #ifdef APP
- this.ctx.draw()
- // #endif
- // #ifdef WEB
- if (!this.runningFlag) {
- return
- }
- requestAnimationFrame(this._bindAnimate)
- // #endif
- }
- start() {
- // #ifdef WEB
- cancelAnimationFrame(this._bindAnimate)
- this.runningFlag = true
- this.animate()
- // #endif
- // #ifdef APP
- //Todo.. requestAnimationFrame
- clearInterval(this.interval)
- this.interval = setInterval(() => {
- this.animate()
- }, 17)
- // #endif
- }
- stop() {
- // #ifdef WEB
- this.runningFlag = false
- cancelAnimationFrame(this._bindAnimate)
- // #endif
- // #ifdef APP
- //Todo.. requestAnimationFrame
- clearInterval(this.interval)
- // #endif
- }
- }
- let animation : BallAnimation | null = null
- onReady(() => {
- let canvas = uni.getElementById("canvas") as UniCanvasElement
- let canvasContext = canvas.getContext("2d");
- if (canvasContext != null) {
- const dpr = uni.getSystemInfoSync().pixelRatio
- canvas.width = canvas.offsetWidth * dpr
- canvas.height = canvas.offsetHeight * dpr
- canvasContext.scale(dpr, dpr)
- animation = new BallAnimation(canvasContext)
- animation?.start()
- } else {
- console.log("canvas.getContext error!!")
- }
- })
- onUnload(() => {
- animation?.stop()
- animation = null
- })
- onPageShow(() => {
- animation?.start()
- })
- onPageHide(() => {
- animation?.stop()
- })
- </script>
- <style>
- .page-body-wrapper {
- text-align: center;
- }
- .canvas {
- width: 300px;
- height: 300px;
- margin: auto;
- background-color: #fff;
- }
- </style>
|