hitFistEffect.vue 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. <template>
  2. <view>
  3. <view class="HitFistEffect-parent">
  4. <view class="HitFistEffect-container">
  5. <canvas canvas-id="fistCanvas" style="width: 375px;height: 100px;"></canvas>
  6. </view>
  7. </view>
  8. <!-- <view>
  9. <button style="width: 200rpx;" @tap="onTestRed">onTestRed</button>
  10. <button style="width: 200rpx;" @tap="onTestBlue">onTestBlue</button>
  11. </view> -->
  12. </view>
  13. </template>
  14. <script>
  15. var Timing = {
  16. easeIn: function easeIn(pos) {
  17. return Math.pow(pos, 3);
  18. },
  19. easeOut: function easeOut(pos) {
  20. return Math.pow(pos - 1, 3) + 1;
  21. },
  22. easeInOut: function easeInOut(pos) {
  23. if ((pos /= 0.5) < 1) {
  24. return 0.5 * Math.pow(pos, 3);
  25. } else {
  26. return 0.5 * (Math.pow(pos - 2, 3) + 2);
  27. }
  28. },
  29. linear: function linear(pos) {
  30. return pos;
  31. }
  32. };
  33. function Animation(opts) {
  34. // console.log(opts);
  35. this.isStop = false;
  36. opts.duration = typeof opts.duration === 'undefined' ? 1000 : opts.duration;
  37. opts.timing = opts.timing || 'linear';
  38. var delay = 17;
  39. function createAnimationFrame() {
  40. if (typeof setTimeout !== 'undefined') {
  41. return function(step, delay) {
  42. setTimeout(function() {
  43. var timeStamp = +new Date();
  44. step(timeStamp);
  45. }, delay);
  46. };
  47. } else if (typeof requestAnimationFrame !== 'undefined') {
  48. return requestAnimationFrame;
  49. } else {
  50. return function(step) {
  51. step(null);
  52. };
  53. }
  54. };
  55. var animationFrame = createAnimationFrame();
  56. var startTimeStamp = null;
  57. var _step = function step(timestamp) {
  58. if (timestamp === null || this.isStop === true) {
  59. opts.onProcess && opts.onProcess(1);
  60. opts.onAnimationFinish && opts.onAnimationFinish();
  61. return;
  62. }
  63. if (startTimeStamp === null) {
  64. startTimeStamp = timestamp;
  65. }
  66. if (timestamp - startTimeStamp < opts.duration) {
  67. var process = (timestamp - startTimeStamp) / opts.duration;
  68. var timingFunction = Timing[opts.timing];
  69. process = timingFunction(process);
  70. opts.onProcess && opts.onProcess(process);
  71. animationFrame(_step, delay);
  72. } else {
  73. opts.onProcess && opts.onProcess(1);
  74. opts.onAnimationFinish && opts.onAnimationFinish();
  75. }
  76. };
  77. _step = _step.bind(this);
  78. animationFrame(_step, delay);
  79. }
  80. export default {
  81. props: {
  82. bLeft: {
  83. type: Boolean,
  84. default: false
  85. },
  86. },
  87. data() {
  88. return {
  89. //拳头
  90. fistRedImage: "/static/effectHit/fist-red.png",
  91. fistBlueImage: "/static/effectHit/fist-blue.png",
  92. animation: 'left-play',
  93. fistList: [],
  94. fistBlueList: [],
  95. //限制生成个数
  96. createRedFistLimit: 5,
  97. createBlueFistLimit: 5,
  98. //已经生成的对象
  99. createRedList: {
  100. 'small': [],
  101. 'medium': [],
  102. 'large': []
  103. },
  104. createBlueList: {
  105. 'small': [],
  106. 'medium': [],
  107. 'large': []
  108. },
  109. fistRed: null,
  110. fistBlue: null,
  111. setInterval: null,
  112. };
  113. },
  114. created() {
  115. let _self = this;
  116. this.fistCanvas = uni.createCanvasContext("fistCanvas", this);
  117. uni.getImageInfo({
  118. src: "../../../static/effectHit/fist-red.png",
  119. success: function(image) {
  120. _self.fistRed = image;
  121. }
  122. });
  123. uni.getImageInfo({
  124. src: "../../../static/effectHit/fist-blue.png",
  125. success: function(image) {
  126. _self.fistBlue = image;
  127. }
  128. });
  129. //{scale:1, red:{x:260,y:0} blue:{x:30,y:0}}
  130. //{scale:0.8, red:{x:350,y:20} blue:{x:50,y:20}}
  131. //{scale:0.6, red:{x:490,y:40} blue:{x:90,y:40}}
  132. // setTimeout(() => {
  133. // let _scale = 0.6;
  134. // let _dWidth = _scale * _self.fistRed.width;
  135. // let _dHeight = _scale * _self.fistRed.height;
  136. // _self.fistCanvas.save();
  137. // _self.fistCanvas.scale(_scale, _scale);
  138. // // _self.fistCanvas.translate(x, 0);
  139. // _self.fistCanvas.drawImage(_self.fistRed.path, 490, 40, _dWidth, _dHeight);
  140. // _self.fistCanvas.restore();
  141. // _self.fistCanvas.save();
  142. // _self.fistCanvas.scale(-_scale, _scale);
  143. // _self.fistCanvas.drawImage(_self.fistBlue.path, -90 - _dWidth, 40,
  144. // _dWidth, _dHeight);
  145. // _self.fistCanvas.restore();
  146. // _self.fistCanvas.draw();
  147. // }, 1000)
  148. this.onDetectionPosition();
  149. // setInterval(()=>{
  150. // this.onTestBlue();
  151. // },500)
  152. },
  153. beforeDestroy() {},
  154. methods: {
  155. onDetectionPosition() {
  156. let _self = this;
  157. if (_self.setInterval != null) {
  158. clearInterval(_self.setInterval);
  159. _self.setInterval = null;
  160. }
  161. //100毫秒检测一次位置
  162. _self.setInterval = setInterval(() => {
  163. _self.fistCanvas.clearRect(0, 0, 750, 150);
  164. drawFistType('small');
  165. drawFistType('medium');
  166. drawFistType('large');
  167. _self.fistCanvas.draw();
  168. }, 20)
  169. function drawFistType(type) {
  170. let smallRedList = _self.createRedList[type];
  171. let smallBlueList = _self.createBlueList[type];
  172. for (let i = 0; i < smallRedList.length; i++) {
  173. let _scale = smallRedList[i].scale;
  174. let _dWidth = _scale * _self.fistRed.width;
  175. let _dHeight = _scale * _self.fistRed.height;
  176. _self.fistCanvas.save();
  177. _self.fistCanvas.scale(_scale, _scale);
  178. _self.fistCanvas.drawImage(_self.fistRed.path, smallRedList[i].red.x, smallRedList[i].red.y, _dWidth, _dHeight);
  179. _self.fistCanvas.restore();
  180. if (smallBlueList.length > i) {
  181. if (smallRedList[i].red.x.sub(smallBlueList[i].blue.x) < 0.5) {
  182. smallRedList[i].animationInstance.isStop = true;
  183. smallBlueList[i].animationInstance.isStop = true;
  184. }
  185. }
  186. }
  187. for (let i = 0; i < smallBlueList.length; i++) {
  188. let _scale = smallBlueList[i].scale;
  189. let _dWidth = _scale * _self.fistBlue.width;
  190. let _dHeight = _scale * _self.fistBlue.height;
  191. _self.fistCanvas.save();
  192. _self.fistCanvas.scale(-_scale, _scale);
  193. _self.fistCanvas.drawImage(_self.fistBlue.path, - smallBlueList[i].blue.x - _dWidth, smallBlueList[i].blue.y,
  194. _dWidth, _dHeight);
  195. _self.fistCanvas.restore();
  196. }
  197. }
  198. },
  199. onCreateFist(data, callback) {
  200. if (data.createFistLimit > 0) {
  201. data.createFistLimit--;
  202. let _item = {
  203. scale: data.scale,
  204. type: data.type, //尺寸 small, medium and large
  205. time: data.time,
  206. red:data.red,
  207. blue:data.blue,
  208. animationInstance: null
  209. };
  210. data.createList[_item.type].push(_item);
  211. _item.animationInstance = new Animation({
  212. timing: 'linear',
  213. duration: _item.time,
  214. onProcess: function(process) {
  215. if (data.createType == 'red') {
  216. _item.red.x -= process * 15;
  217. } else {
  218. _item.blue.x += process * 15;
  219. }
  220. },
  221. onAnimationFinish: function onAnimationFinish() {
  222. // console.log("finishblue:",_item.animationInstance.isStop);
  223. if (!_item.animationInstance.isStop) {
  224. //如果isStop 是false 的,说明没有抵消,则击中
  225. if (callback) {
  226. callback({
  227. hit: true
  228. })
  229. }
  230. }
  231. data.createFistLimit++;
  232. data.createList[_item.type].shift();
  233. }
  234. });
  235. }
  236. },
  237. onTestRed() {
  238. let num = Math.floor(Math.random() * 3) + 1;
  239. // console.log("num:", num);
  240. this.onPlay({
  241. bloodPoint: num,
  242. createType: 'red',
  243. callback: (res) => {
  244. console.log("红色拳头击中对方:", res);
  245. }
  246. });
  247. },
  248. onTestBlue() {
  249. let num = Math.floor(Math.random() * 3) + 1;
  250. // console.log("num:", num);
  251. this.onPlay({
  252. bloodPoint: num,
  253. createType: 'blue',
  254. callback: (res) => {
  255. console.log("蓝色拳头击中对方:", res);
  256. }
  257. });
  258. },
  259. onPlay(context) {
  260. let {
  261. bloodPoint,
  262. callback,
  263. createType
  264. } = context;
  265. //{scale:1, red:{x:260,y:0} blue:{x:30,y:0}}
  266. //{scale:0.8, red:{x:350,y:20} blue:{x:50,y:20}}
  267. //{scale:0.6, red:{x:490,y:40} blue:{x:90,y:40}}
  268. let temp = {};
  269. if (bloodPoint == 3) {
  270. //大拳头
  271. temp.scale = 1;
  272. temp.time = 500;
  273. temp.type = 'large';
  274. temp.red = {x: 260,y: 0};
  275. temp.blue = {x: 30,y: 0};
  276. } else if (bloodPoint == 2) {
  277. //中拳头
  278. temp.scale = 0.8;
  279. temp.time = 700;
  280. temp.type = 'medium';
  281. temp.red = {x:350,y:20};
  282. temp.blue = {x:50,y:20};
  283. } else {
  284. //小拳头
  285. temp.scale = 0.6;
  286. temp.time = 900;
  287. temp.type = 'small';
  288. temp.red = {x:490,y:40};
  289. temp.blue = {x:90,y:40};
  290. }
  291. if (createType == 'red') {
  292. temp.createFistLimit = this.createRedFistLimit;
  293. temp.createList = this.createRedList;
  294. temp.createType = "red";
  295. this.onCreateFist(temp, callback);
  296. } else {
  297. temp.createFistLimit = this.createBlueFistLimit;
  298. temp.createList = this.createBlueList;
  299. temp.createType = "blue";
  300. this.onCreateFist(temp, callback);
  301. }
  302. },
  303. onStop() {
  304. }
  305. }
  306. }
  307. </script>
  308. <style lang="scss">
  309. .HitFistEffect-parent {
  310. // border: 1rpx solid #ffaa7f;
  311. position: absolute;
  312. display: flex;
  313. justify-content: center;
  314. overflow: hidden;
  315. top: 0;
  316. width: 750rpx;
  317. }
  318. .HitFistEffect-container {
  319. width: 100%;
  320. height: 65px;
  321. // border: 1rpx solid #000000;
  322. position: relative;
  323. // display: flex;
  324. }
  325. .HitFistEffect {
  326. // background-color: #007AFF;
  327. position: absolute;
  328. background-size: cover;
  329. height: 65px;
  330. width: 86px;
  331. // position: relative;
  332. top: 0;
  333. // left: -500rpx;
  334. }
  335. .left-play {
  336. animation: leftHitFistEffectRun calc(var(--time) * 1s) ease calc(var(--delay) * 1s) 1;
  337. animation-play-state: running;
  338. }
  339. .right-play {
  340. animation: rightHitFistEffectRun calc(var(--time) * 1s) ease calc(var(--delay) * 1s) 1;
  341. animation-play-state: running;
  342. }
  343. @keyframes leftHitFistEffectRun {
  344. 0% {
  345. left: 150rpx;
  346. }
  347. 100% {
  348. left: 450rpx;
  349. }
  350. }
  351. @keyframes rightHitFistEffectRun {
  352. 0% {
  353. left: 450rpx;
  354. }
  355. 100% {
  356. left: 150rpx;
  357. }
  358. }
  359. </style>