canvas.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // import item from "@/pages/website/routes/list/item";
  2. import { cloneDeep } from "lodash";
  3. import ListModule from "..";
  4. import { InitCanvasDragEvent, ListDraw } from "../objects/canvas";
  5. import { ShowItem } from "../objects/item";
  6. export default ListModule.action({
  7. async initListCanvasData(wWidth: number, wHeight: number) {
  8. const totalLines = this.store.animate.totalLines;
  9. const scrollType = this.store.animate.scrollType;
  10. const items = await this.actions.loadData();
  11. if (!items.length) {
  12. return;
  13. }
  14. const scale = Math.max(devicePixelRatio, 2);
  15. const canvas = {
  16. width: wWidth * scale,
  17. height: wHeight * scale,
  18. scale: scale,
  19. padding: this.store.animate.padding * scale,
  20. linesCount: Math.ceil(items.length / totalLines) * 2,
  21. };
  22. this.store.canvas = { ...this.store.canvas, ...canvas };
  23. if (scrollType == "vertical") {
  24. await this.actions.initVerticalList(items);
  25. }
  26. if (scrollType == "horizontal") {
  27. await this.actions.initHorizontalList(items);
  28. }
  29. return true;
  30. },
  31. async initVerticalList(items) {
  32. const totalLines = this.store.animate.totalLines;
  33. const canvas = cloneDeep(this.store.canvas);
  34. const itemOffset =
  35. (canvas.width - canvas.padding * (totalLines + 1)) / totalLines;
  36. this.store.canvas.itemOffset = itemOffset;
  37. const lines = [];
  38. for (let i = 0; i < totalLines; i++) {
  39. const off = i * canvas.linesCount;
  40. const arr: ShowItem[] = [];
  41. for (let k = 0; k < canvas.linesCount; k++) {
  42. arr.push(items[(off + k) % items.length]);
  43. }
  44. // this.actions.shuffleSelf(arr, totalLines);
  45. //计算总高度
  46. let halfOffset = 0;
  47. arr.forEach((item) => {
  48. const h = ((item.h * 1.0) / item.w) * itemOffset;
  49. item.offsetY = h + canvas.padding;
  50. halfOffset += item.offsetY;
  51. });
  52. let repeatArr: any = [];
  53. const times = Math.ceil((canvas.height * 2) / halfOffset);
  54. for (let i = 0; i < times; i++) {
  55. repeatArr = [...repeatArr, ...arr];
  56. }
  57. const linesItem = {
  58. items: repeatArr,
  59. offset: 0,
  60. halfOffset: halfOffset,
  61. dragging: false,
  62. speed: i % 2 == 0 ? 1 : 2,
  63. };
  64. lines.push(linesItem);
  65. }
  66. this.store.canvas.linesData = lines;
  67. },
  68. async initHorizontalList(items) {
  69. const totalLines = this.store.animate.totalLines;
  70. const canvas = cloneDeep(this.store.canvas);
  71. const itemOffset =
  72. (canvas.height - canvas.padding * (totalLines + 1)) / totalLines;
  73. this.store.canvas.itemOffset = itemOffset;
  74. const lines = [];
  75. for (let i = 0; i < totalLines; i++) {
  76. const off = i * totalLines;
  77. const arr: ShowItem[] = [];
  78. for (let k = 0; k < canvas.linesCount; k++) {
  79. arr.push(items[(off + k) % items.length]);
  80. }
  81. // this.actions.shuffleSelf(arr, canvas.linesCount);
  82. //计算总宽度
  83. let halfOffset = 0;
  84. arr.forEach((item) => {
  85. const w = ((item.w * 1.0) / item.h) * itemOffset;
  86. item.offsetX = w + canvas.padding;
  87. halfOffset += item.offsetX;
  88. });
  89. let repeatArr: any = [];
  90. const times = Math.ceil((canvas.width * 2) / halfOffset);
  91. for (let i = 0; i < times; i++) {
  92. repeatArr = [...repeatArr, ...arr];
  93. }
  94. const linesItem = {
  95. items: repeatArr,
  96. offset: 0,
  97. halfOffset: halfOffset,
  98. dragging: false,
  99. speed: i % 2 == 0 ? 1 : 2,
  100. };
  101. lines.push(linesItem);
  102. }
  103. this.store.canvas.linesData = lines;
  104. },
  105. async startListRunning(canvas: HTMLCanvasElement) {
  106. InitCanvasDragEvent.call(this, canvas);
  107. const storeCanvas = cloneDeep(this.store.canvas);
  108. canvas.width = storeCanvas.width;
  109. canvas.height = storeCanvas.height;
  110. const ctx = canvas.getContext("2d");
  111. const cacheCanvas = document.createElement("canvas");
  112. cacheCanvas.width = storeCanvas.width;
  113. cacheCanvas.height = storeCanvas.height;
  114. const cacheCtx = cacheCanvas.getContext("2d");
  115. if (!cacheCtx) {
  116. return;
  117. }
  118. cacheCtx.font = "24px sans-serif";
  119. cacheCtx.fillStyle = "#FFFFFF";
  120. cacheCtx.textBaseline = "top";
  121. let loopId = 0;
  122. let n = storeCanvas.linesData.length;
  123. let i = 0;
  124. let lastTime = Date.now();
  125. let dtaTime = 0;
  126. const loop = () => {
  127. dtaTime = Date.now() - lastTime;
  128. lastTime = Date.now();
  129. n = storeCanvas.linesData.length;
  130. while (n--) {
  131. const item = storeCanvas.linesData[n];
  132. if (!item.dragging) {
  133. //没有拖拽进行累积
  134. item.offset = Math.floor(item.offset + item.speed);
  135. }
  136. // console.log(item.offset);
  137. if (item.offset >= item.halfOffset) item.offset -= item.halfOffset;
  138. if (item.offset < 0) item.offset += item.halfOffset;
  139. this.store.canvas.linesData[n] = item;
  140. }
  141. cacheCtx?.clearRect(0, 0, storeCanvas.width, storeCanvas.height);
  142. n = storeCanvas.linesData.length;
  143. for (i = 0; i < n; i++) {
  144. ListDraw.call(this, storeCanvas.linesData[i], i, cacheCtx);
  145. }
  146. ctx?.clearRect(0, 0, storeCanvas.width, storeCanvas.height);
  147. ctx?.drawImage(cacheCanvas, 0, 0);
  148. loopId = requestAnimationFrame(loop);
  149. };
  150. loop();
  151. },
  152. });