ball.uvue 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. <template>
  2. <view class="page-body">
  3. <canvas id="canvas" class="canvas"></canvas>
  4. </view>
  5. </template>
  6. <script setup>
  7. class Ball {
  8. private width : number
  9. private height : number
  10. public x : number
  11. public y : number
  12. public vx : number
  13. public vy : number
  14. public radius : number = 5
  15. constructor(w : number, h : number, x : number, y : number, vx : number, vy : number) {
  16. this.width = w
  17. this.height = h
  18. this.x = x
  19. this.y = y
  20. this.vx = vx
  21. this.vy = vy
  22. }
  23. move() {
  24. this.x += this.vx
  25. this.y += this.vy
  26. // 边框反弹
  27. if (this.x < this.radius) {
  28. this.vx = Math.abs(this.vx)
  29. return
  30. }
  31. if (this.x > this.width - this.radius) {
  32. this.vx = -Math.abs(this.vx)
  33. }
  34. if (this.y < this.radius) {
  35. this.vy = Math.abs(this.vy)
  36. return
  37. }
  38. if (this.y > this.width - this.radius) {
  39. this.vy = -Math.abs(this.vy)
  40. }
  41. }
  42. }
  43. class BallAnimation {
  44. private ctx : CanvasRenderingContext2D
  45. private ballList : Array<Ball> = []
  46. private speed = 3
  47. private layer = 3
  48. private ballInlayer = 20
  49. private interval : number = 0
  50. private runningFlag : boolean = false
  51. // #ifdef WEB
  52. private _bindAnimate: Function = null
  53. // #endif
  54. constructor(ctx : CanvasRenderingContext2D) {
  55. this.ctx = ctx
  56. this.initBall()
  57. this.ctx.fillStyle = '#007AFF'
  58. // #ifdef WEB
  59. this._bindAnimate = this.animate.bind(this)
  60. // #endif
  61. }
  62. private getDistance(x : number, y : number) : number {
  63. return Math.pow((Math.pow(x, 2) + Math.pow(y, 2)), 0.5)
  64. }
  65. private initBall() {
  66. const canvasWidth = this.ctx.canvas.offsetWidth;
  67. const canvasHeight = this.ctx.canvas.offsetHeight;
  68. for (let i = 0; i < this.layer; i++) {
  69. let radius = this.getDistance(canvasWidth / 2, canvasHeight / 2) / this.layer * i
  70. for (let j = 0; j < this.ballInlayer; j++) {
  71. let deg = j * 2 * Math.PI / this.ballInlayer,
  72. sin = Math.sin(deg),
  73. cos = Math.cos(deg),
  74. x = radius * cos + canvasWidth / 2,
  75. y = radius * sin + canvasHeight / 2,
  76. vx = this.speed * cos,
  77. vy = this.speed * sin
  78. this.ballList.push(new Ball(canvasWidth, canvasHeight, x, y, vx, vy))
  79. }
  80. }
  81. }
  82. public animate() {
  83. this.ctx.clearRect(0, 0, this.ctx.canvas.offsetWidth, this.ctx.canvas.offsetHeight)
  84. this.ballList.forEach((item) => {
  85. item.move()
  86. this.ctx.beginPath()
  87. this.ctx.arc(item.x, item.y, item.radius, 0, 2 * Math.PI)
  88. // this.ctx.ellipse(item.x, item.y, item.radius, item.radius, 0, 0, Math.PI * 2)
  89. this.ctx.fill()
  90. })
  91. // #ifdef APP
  92. this.ctx.draw()
  93. // #endif
  94. // #ifdef WEB
  95. if (!this.runningFlag) {
  96. return
  97. }
  98. requestAnimationFrame(this._bindAnimate)
  99. // #endif
  100. }
  101. start() {
  102. // #ifdef WEB
  103. cancelAnimationFrame(this._bindAnimate)
  104. this.runningFlag = true
  105. this.animate()
  106. // #endif
  107. // #ifdef APP
  108. //Todo.. requestAnimationFrame
  109. clearInterval(this.interval)
  110. this.interval = setInterval(() => {
  111. this.animate()
  112. }, 17)
  113. // #endif
  114. }
  115. stop() {
  116. // #ifdef WEB
  117. this.runningFlag = false
  118. cancelAnimationFrame(this._bindAnimate)
  119. // #endif
  120. // #ifdef APP
  121. //Todo.. requestAnimationFrame
  122. clearInterval(this.interval)
  123. // #endif
  124. }
  125. }
  126. let animation : BallAnimation | null = null
  127. onReady(() => {
  128. let canvas = uni.getElementById("canvas") as UniCanvasElement
  129. let canvasContext = canvas.getContext("2d");
  130. if (canvasContext != null) {
  131. const dpr = uni.getSystemInfoSync().pixelRatio
  132. canvas.width = canvas.offsetWidth * dpr
  133. canvas.height = canvas.offsetHeight * dpr
  134. canvasContext.scale(dpr, dpr)
  135. animation = new BallAnimation(canvasContext)
  136. animation?.start()
  137. } else {
  138. console.log("canvas.getContext error!!")
  139. }
  140. })
  141. onUnload(() => {
  142. animation?.stop()
  143. animation = null
  144. })
  145. onPageShow(() => {
  146. animation?.start()
  147. })
  148. onPageHide(() => {
  149. animation?.stop()
  150. })
  151. </script>
  152. <style>
  153. .page-body-wrapper {
  154. text-align: center;
  155. }
  156. .canvas {
  157. width: 300px;
  158. height: 300px;
  159. margin: auto;
  160. background-color: #fff;
  161. }
  162. </style>