canvas.uvue 3.8 KB
Newer Older
X
xty 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
<template>
    <view class="page-body">
        <canvas canvas-id="canvas" id="canvas" class="canvas"></canvas>
    </view>
</template>

<script setup>
    class Ball {
		private canvasWidth : number
        private canvasHeight : number
        private ctx : CanvasRenderingContext2D
        private x : number
        private y : number
        private vx : number
        private vy : number
        private radius : number = 5

		constructor(x: number, y: number, vx: number, vy: number, ctx: CanvasRenderingContext2D){
			this.ctx = ctx
			this.canvasWidth = ctx.canvas.width
			this.canvasHeight = ctx.canvas.height
			this.x = x
			this.y = y
			this.vx = vx
			this.vy = vy
		}

		draw() {
		    this.ctx.fillStyle = '#007AFF'
		    this.ctx.beginPath()
		    this.ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI)
		    this.ctx.closePath()
		    this.ctx.fill()
		}

		move() {
		    this.x += this.vx
		    this.y += this.vy
		    // 回到中心
		    // if (getDistance(this.x - this.canvasWidth / 2, this.y - this.canvasHeight / 2) >
		    // 	getDistance(this.canvasWidth / 2, this.canvasHeight / 2) + this.radius) {
		    // 	this.x = this.canvasWidth / 2
		    // 	this.y = this.canvasHeight / 2
		    // }

		    // 边框反弹
		    if (this.x < this.radius) {
		        this.vx = Math.abs(this.vx)
		        return
		    }
		    if (this.x > this.canvasWidth - this.radius) {
		        this.vx = -Math.abs(this.vx)
		    }
		    if (this.y < this.radius) {
		        this.vy = Math.abs(this.vy)
		        return
		    }
		    if (this.y > this.canvasWidth - 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
		constructor(ctx : CanvasRenderingContext2D){
			this.ctx = ctx
			this.initBall()
		}

		private getDistance(x: number, y: number) : number{
		    return Math.pow((Math.pow(x, 2) + Math.pow(y, 2)), 0.5)
		}

		private initBall() {
			let canvasWidth = this.ctx.canvas.width,
			    canvasHeight = this.ctx.canvas.height
			for (let i = 0; i < this.layer; i++) {
			    let radius = getDistance(canvasWidth / 2, canvasHeight / 2) / layer * i
			    for (let j = 0; j < this.ballInlayer; j++) {
			        let deg = j * 2 * Math.PI / 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
			        ballList.push(new Ball(x, y, vx, vy, ctx))
			    }
			}
		}

		private animate(ballList: Array<Ball>) {
		    this.ctx.clearRect(0, 0, this.ctx.canvas.width,  this.ctx.canvas.height )
		    ballList.forEach(function(item) {
		        item.move()
		        item.draw()
		    })
		    this.ctx.draw()
		}

		start(){
			//Todo.. requestAnimationFrame
			clearInterval(this.interval)
			interval = setInterval(function() {
			    animate(ballList)
			}, 17)
		}
		stop(){
			clearInterval(this.interval)
		}
	}

	var animation : BallAnimation|null = null
	onReady(() => {
		let canvas = uni.getElementById("canvas") as UniCanvasElementImpl
	    let canvasContext = canvas.getContext("2d");
		if(canvasContext != null) {
			animation = new BallAnimation(canvasContext)
			animation?.start()
		} else {
			console.log("canvas.getContext error!!")
		}
	})

	onUnload(()=> {
	    animation?.stop()
		animation = null
	})
	onAppShow((_ : OnShowOptions)=>{
		animation?.start()
	})

	onAppHide(()=>{
		animation?.stop()
	})

</script>

<style>
    .page-body-wrapper {
        text-align: center;
    }

    .canvas {
        width: 610rpx;
        height: 610rpx;
        margin: auto;
        background-color: #fff;
    }
</style>