canvas.uvue 3.9 KB
Newer Older
X
xty 已提交
1 2 3 4 5 6
<template>
    <view class="page-body">
        <canvas canvas-id="canvas" id="canvas" class="canvas"></canvas>
    </view>
</template>

雪洛's avatar
雪洛 已提交
7
<script setup lang="uts">
X
xty 已提交
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
    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++) {
雪洛's avatar
雪洛 已提交
84
			    let radius = this.getDistance(canvasWidth / 2, canvasHeight / 2) / this.layer * i
X
xty 已提交
85
			    for (let j = 0; j < this.ballInlayer; j++) {
雪洛's avatar
雪洛 已提交
86
			        let deg = j * 2 * Math.PI / this.ballInlayer,
X
xty 已提交
87 88 89 90 91 92
			            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
雪洛's avatar
雪洛 已提交
93
			        this.ballList.push(new Ball(x, y, vx, vy, this.ctx))
X
xty 已提交
94 95 96 97 98 99 100 101 102 103
			    }
			}
		}

		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()
		    })
雪洛's avatar
雪洛 已提交
104
		    this.ctx.draw(false)
X
xty 已提交
105 106 107 108 109
		}

		start(){
			//Todo.. requestAnimationFrame
			clearInterval(this.interval)
雪洛's avatar
雪洛 已提交
110 111
			this.interval = setInterval(() => {
			    this.animate(this.ballList)
X
xty 已提交
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
			}, 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
	})
135
	onPageShow((_ : OnShowOptions)=>{
X
xty 已提交
136 137 138
		animation?.start()
	})

139
	onPageHide(()=>{
X
xty 已提交
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
		animation?.stop()
	})

</script>

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

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