|
@@ -1,166 +1,110 @@
|
|
|
// import item from "@/pages/website/routes/list/item";
|
|
|
+import { cloneDeep } from "lodash";
|
|
|
import ListModule from "..";
|
|
|
import { ShowItem, ColDataType } from "../objects/item";
|
|
|
+import { InitCanvasDragEvent, ListDraw } from "../objects/canvas";
|
|
|
|
|
|
-const cols: ColDataType[] = []; //{offset, items:[], halfOffset: 0, dragging: false}
|
|
|
-
|
|
|
-let CanvasWidth = 0;
|
|
|
-let CanvasHeight = 0;
|
|
|
-const textH = 0;
|
|
|
-let paddingOffset = 0;
|
|
|
-let totalSizeCount = 0; //每行或每列的数量
|
|
|
-let itemOffset = 0;
|
|
|
-
|
|
|
-let ctx: CanvasRenderingContext2D | null;
|
|
|
-let scale = 1;
|
|
|
-function listDraw(this: ListModule, col: ColDataType, row: number, ctx: any) {
|
|
|
- const scrollType = this.store.scrollType;
|
|
|
- let x = 0,
|
|
|
- y = 0;
|
|
|
- const offseStep = itemOffset + paddingOffset;
|
|
|
-
|
|
|
- if (scrollType == "vertical") {
|
|
|
- x = row > 0 ? Math.floor(row * offseStep) + paddingOffset : paddingOffset;
|
|
|
- y = col.offset + CanvasHeight;
|
|
|
- }
|
|
|
- if (scrollType == "horizontal") {
|
|
|
- x = col.offset + CanvasWidth;
|
|
|
- y = row > 0 ? Math.floor(row * offseStep) + paddingOffset : paddingOffset;
|
|
|
- }
|
|
|
-
|
|
|
- const items = col.items;
|
|
|
- const total = items.length;
|
|
|
-
|
|
|
- for (let k = 0; k < total; k++) {
|
|
|
- //绘制
|
|
|
- const item = items[k];
|
|
|
-
|
|
|
- if (scrollType == "vertical") {
|
|
|
- y -= item.offsetY; //从下往上绘制
|
|
|
- if (y > CanvasHeight || y < -item.offsetY) continue; //超出部分,不进行绘制提交
|
|
|
- ctx.drawImage(
|
|
|
- item.img,
|
|
|
- 0,
|
|
|
- 0,
|
|
|
- item.w,
|
|
|
- item.h,
|
|
|
- Math.floor(x),
|
|
|
- Math.floor(y),
|
|
|
- Math.floor(itemOffset),
|
|
|
- Math.floor(item.offsetY - textH - paddingOffset)
|
|
|
- );
|
|
|
- }
|
|
|
- if (scrollType == "horizontal") {
|
|
|
- x -= item.offsetX;
|
|
|
- if (x > CanvasWidth || x < -item.offsetX) continue;
|
|
|
- ctx.drawImage(
|
|
|
- item.img,
|
|
|
- 0,
|
|
|
- 0,
|
|
|
- item.w,
|
|
|
- item.h,
|
|
|
- Math.floor(x),
|
|
|
- Math.floor(y),
|
|
|
- Math.floor(item.offsetX - textH - paddingOffset),
|
|
|
- Math.floor(itemOffset)
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- // let text =
|
|
|
- // item.name.length > 20
|
|
|
- // ? item.name.substring(0, 19) + "..."
|
|
|
- // : item.name;
|
|
|
- // ctx.fillText(text, x, Math.round(y + item.offsetY - textH * 1.2));
|
|
|
- }
|
|
|
-}
|
|
|
export default ListModule.action({
|
|
|
- async initListCanvasDatas(wWidth: number, wHeight: number) {
|
|
|
- const totalRow = this.store.totalRow;
|
|
|
- const scrollType = this.store.scrollType;
|
|
|
- const items = await this.actions.loadData(wWidth, wHeight);
|
|
|
- scale = Math.max(devicePixelRatio, 2);
|
|
|
-
|
|
|
- // textH = 24 * scale;
|
|
|
- CanvasWidth = wWidth * scale;
|
|
|
- CanvasHeight = wHeight * scale;
|
|
|
- paddingOffset = 12 * scale;
|
|
|
- totalSizeCount = Math.ceil(items.length / totalRow) * 2;
|
|
|
+ async initListCanvasData(wWidth: number, wHeight: number) {
|
|
|
+ const totalLines = this.store.animate.totalLines;
|
|
|
+ const scrollType = this.store.animate.scrollType;
|
|
|
+ const items = await this.actions.loadData();
|
|
|
+ const scale = Math.max(devicePixelRatio, 2);
|
|
|
+
|
|
|
+ const canvas = {
|
|
|
+ width: wWidth * scale,
|
|
|
+ height: wHeight * scale,
|
|
|
+ padding: this.store.canvas.padding * scale,
|
|
|
+ linesCount: Math.ceil(items.length / totalLines) * 2,
|
|
|
+ };
|
|
|
+ this.store.canvas = { ...this.store.canvas, ...canvas };
|
|
|
|
|
|
if (scrollType == "vertical") {
|
|
|
- this.actions.initVerticalList(items);
|
|
|
+ await this.actions.initVerticalList(items);
|
|
|
}
|
|
|
if (scrollType == "horizontal") {
|
|
|
- this.actions.initHorizontalList(items);
|
|
|
+ await this.actions.initHorizontalList(items);
|
|
|
}
|
|
|
},
|
|
|
- initVerticalList(items) {
|
|
|
- const totalRow = this.store.totalRow;
|
|
|
- itemOffset = (CanvasWidth - paddingOffset * (totalRow + 1)) / totalRow;
|
|
|
- for (let i = 0; i < totalRow; i++) {
|
|
|
- const off = i * totalSizeCount;
|
|
|
+ async initVerticalList(items) {
|
|
|
+ const totalLines = this.store.animate.totalLines;
|
|
|
+ const canvas = cloneDeep(this.store.canvas);
|
|
|
+ const itemOffset =
|
|
|
+ (canvas.width - canvas.padding * (totalLines + 1)) / totalLines;
|
|
|
+ this.store.canvas.itemOffset = itemOffset;
|
|
|
+ const lines = [];
|
|
|
+ for (let i = 0; i < totalLines; i++) {
|
|
|
+ const off = i * canvas.linesCount;
|
|
|
const arr: ShowItem[] = [];
|
|
|
- for (let k = 0; k < totalSizeCount; k++) {
|
|
|
+ for (let k = 0; k < canvas.linesCount; k++) {
|
|
|
arr.push(items[(off + k) % items.length]);
|
|
|
}
|
|
|
- this.actions.shuffleSelf(arr, totalSizeCount);
|
|
|
+ this.actions.shuffleSelf(arr, totalLines);
|
|
|
//计算总高度
|
|
|
let halfOffset = 0;
|
|
|
arr.forEach((item) => {
|
|
|
const h = ((item.h * 1.0) / item.w) * itemOffset;
|
|
|
- item.offsetY = h + textH + paddingOffset; //y step;
|
|
|
+ item.offsetY = h + canvas.padding;
|
|
|
halfOffset += item.offsetY;
|
|
|
});
|
|
|
|
|
|
- const colData = {
|
|
|
+ const linesItem = {
|
|
|
items: [...arr, ...arr],
|
|
|
offset: 0,
|
|
|
halfOffset: halfOffset,
|
|
|
dragging: false,
|
|
|
speed: i % 2 == 0 ? 1 : 2,
|
|
|
};
|
|
|
- cols.push(colData);
|
|
|
+ lines.push(linesItem);
|
|
|
}
|
|
|
+ this.store.canvas.linesData = lines;
|
|
|
},
|
|
|
- initHorizontalList(items) {
|
|
|
- const totalRow = this.store.totalRow;
|
|
|
- itemOffset = (CanvasHeight - paddingOffset * (totalRow + 1)) / totalRow;
|
|
|
- for (let i = 0; i < totalRow; i++) {
|
|
|
- const off = i * totalSizeCount;
|
|
|
+ async initHorizontalList(items) {
|
|
|
+ const totalLines = this.store.animate.totalLines;
|
|
|
+ const canvas = cloneDeep(this.store.canvas);
|
|
|
+ const itemOffset =
|
|
|
+ (canvas.height - canvas.padding * (totalLines + 1)) / totalLines;
|
|
|
+ this.store.canvas.itemOffset = itemOffset;
|
|
|
+ const lines = [];
|
|
|
+ for (let i = 0; i < totalLines; i++) {
|
|
|
+ const off = i * totalLines;
|
|
|
const arr: ShowItem[] = [];
|
|
|
- for (let k = 0; k < totalSizeCount; k++) {
|
|
|
+ for (let k = 0; k < canvas.linesCount; k++) {
|
|
|
arr.push(items[(off + k) % items.length]);
|
|
|
}
|
|
|
- this.actions.shuffleSelf(arr, totalSizeCount);
|
|
|
+ this.actions.shuffleSelf(arr, canvas.linesCount);
|
|
|
|
|
|
//计算总高度
|
|
|
let halfOffset = 0;
|
|
|
arr.forEach((item) => {
|
|
|
const w = ((item.w * 1.0) / item.h) * itemOffset;
|
|
|
- item.offsetX = w + textH + paddingOffset; //y step;
|
|
|
+ item.offsetX = w + canvas.padding;
|
|
|
halfOffset += item.offsetX;
|
|
|
});
|
|
|
|
|
|
- const colData = {
|
|
|
+ const linesItem = {
|
|
|
items: [...arr, ...arr],
|
|
|
offset: 0,
|
|
|
halfOffset: halfOffset,
|
|
|
dragging: false,
|
|
|
speed: i % 2 == 0 ? 1 : 2,
|
|
|
};
|
|
|
- cols.push(colData);
|
|
|
+ lines.push(linesItem);
|
|
|
}
|
|
|
+ this.store.canvas.linesData = lines;
|
|
|
},
|
|
|
async startListRunning(canvas: HTMLCanvasElement) {
|
|
|
- this.actions.initDragEvents(canvas);
|
|
|
- canvas.width = CanvasWidth;
|
|
|
- canvas.height = CanvasHeight;
|
|
|
+ InitCanvasDragEvent.call(this, canvas);
|
|
|
+ const storeCanvas = cloneDeep(this.store.canvas);
|
|
|
+ canvas.width = storeCanvas.width;
|
|
|
+ canvas.height = storeCanvas.height;
|
|
|
|
|
|
- ctx = canvas.getContext("2d");
|
|
|
+ const ctx = canvas.getContext("2d");
|
|
|
|
|
|
- const cache = document.createElement("canvas");
|
|
|
- cache.width = CanvasWidth;
|
|
|
- cache.height = CanvasHeight;
|
|
|
- const cacheCtx = cache.getContext("2d");
|
|
|
+ const cacheCanvas = document.createElement("canvas");
|
|
|
+ cacheCanvas.width = storeCanvas.width;
|
|
|
+ cacheCanvas.height = storeCanvas.height;
|
|
|
+ const cacheCtx = cacheCanvas.getContext("2d");
|
|
|
if (!cacheCtx) {
|
|
|
return;
|
|
|
}
|
|
@@ -170,16 +114,16 @@ export default ListModule.action({
|
|
|
|
|
|
let loopId = 0;
|
|
|
|
|
|
- let n = cols.length;
|
|
|
+ let n = storeCanvas.linesData.length;
|
|
|
let i = 0;
|
|
|
let lastTime = Date.now();
|
|
|
let dtaTime = 0;
|
|
|
const loop = () => {
|
|
|
dtaTime = Date.now() - lastTime;
|
|
|
lastTime = Date.now();
|
|
|
- n = cols.length;
|
|
|
+ n = storeCanvas.linesData.length;
|
|
|
while (n--) {
|
|
|
- const item = cols[n];
|
|
|
+ const item = storeCanvas.linesData[n];
|
|
|
if (!item.dragging) {
|
|
|
//没有拖拽进行累积
|
|
|
item.offset = Math.floor(item.offset + item.speed);
|
|
@@ -188,198 +132,16 @@ export default ListModule.action({
|
|
|
if (item.offset >= item.halfOffset) item.offset -= item.halfOffset;
|
|
|
if (item.offset < 0) item.offset += item.halfOffset;
|
|
|
}
|
|
|
- cacheCtx?.clearRect(0, 0, CanvasWidth, CanvasHeight);
|
|
|
- n = cols.length;
|
|
|
+ cacheCtx?.clearRect(0, 0, storeCanvas.width, storeCanvas.height);
|
|
|
+ n = storeCanvas.linesData.length;
|
|
|
for (i = 0; i < n; i++) {
|
|
|
- listDraw.call(this, cols[i], i, cacheCtx);
|
|
|
+ ListDraw.call(this, storeCanvas.linesData[i], i, cacheCtx);
|
|
|
}
|
|
|
- ctx?.clearRect(0, 0, CanvasWidth, CanvasHeight);
|
|
|
- ctx?.drawImage(cache, 0, 0);
|
|
|
+ ctx?.clearRect(0, 0, storeCanvas.width, storeCanvas.height);
|
|
|
+ ctx?.drawImage(cacheCanvas, 0, 0);
|
|
|
loopId = requestAnimationFrame(loop);
|
|
|
};
|
|
|
loop();
|
|
|
},
|
|
|
-
|
|
|
- initDragEvents(canvas: HTMLCanvasElement) {
|
|
|
- let down = false;
|
|
|
- let downIndex = -1;
|
|
|
- let downY = 0;
|
|
|
- let downX = 0;
|
|
|
-
|
|
|
- let initOffset = 0;
|
|
|
- let downTime = 0;
|
|
|
- let moving = false;
|
|
|
- const fingers: { [name: number]: any } = {};
|
|
|
- const scrollType = this.store.scrollType;
|
|
|
-
|
|
|
- const onMouseDown = (e: MouseEvent) => {
|
|
|
- const x = e.clientX * scale;
|
|
|
- const y = e.clientY * scale;
|
|
|
- downY = e.clientY * scale;
|
|
|
- downX = e.clientX * scale;
|
|
|
- down = true;
|
|
|
- downIndex =
|
|
|
- scrollType == "vertical"
|
|
|
- ? Math.floor(x / (itemOffset + paddingOffset))
|
|
|
- : Math.floor(y / (itemOffset + paddingOffset));
|
|
|
-
|
|
|
- cols[downIndex].dragging = true;
|
|
|
- initOffset = cols[downIndex].offset;
|
|
|
- downTime = Date.now();
|
|
|
- };
|
|
|
-
|
|
|
- const onMouseMove = (e: MouseEvent) => {
|
|
|
- if (!down || downIndex < 0) return;
|
|
|
- moving = true;
|
|
|
-
|
|
|
- console.log("move");
|
|
|
- let dtaOffset = 0;
|
|
|
- if (scrollType == "vertical") {
|
|
|
- dtaOffset = e.clientY * scale - dtaOffset;
|
|
|
- }
|
|
|
- if (scrollType == "horizontal") {
|
|
|
- dtaOffset = e.clientX * scale - dtaOffset;
|
|
|
- }
|
|
|
-
|
|
|
- cols[downIndex].offset = initOffset + dtaOffset;
|
|
|
- };
|
|
|
- const onMouseUp = (e: MouseEvent) => {
|
|
|
- console.log("up");
|
|
|
- down = false;
|
|
|
- if (downIndex >= 0) {
|
|
|
- cols[downIndex].dragging = false;
|
|
|
- const dtaTime = Date.now() - downTime;
|
|
|
- if (dtaTime < 200 && !moving) {
|
|
|
- const col = cols[downIndex];
|
|
|
- let offset = col.offset;
|
|
|
- if (offset >= col.halfOffset) offset -= col.halfOffset;
|
|
|
- if (offset < 0) offset += col.halfOffset;
|
|
|
-
|
|
|
- const n = col.items.length;
|
|
|
- let z =
|
|
|
- scrollType == "vertical"
|
|
|
- ? offset + CanvasHeight
|
|
|
- : offset + CanvasWidth;
|
|
|
- for (let k = 0; k < n; k++) {
|
|
|
- const item = col.items[k];
|
|
|
- if (scrollType == "vertical") {
|
|
|
- z -= item.offsetY;
|
|
|
- if (downY > z && downY < z + item.offsetY) {
|
|
|
- console.log("click->", item.name);
|
|
|
- this.actions.popDialog(e, item);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (scrollType == "horizontal") {
|
|
|
- z -= item.offsetX;
|
|
|
- if (downX > z && downX < z + item.offsetX) {
|
|
|
- console.log("click->", item.name);
|
|
|
- this.actions.popDialog(e, item);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- downIndex = -1;
|
|
|
- moving = false;
|
|
|
- };
|
|
|
- const onTouchstart = (e: TouchEvent) => {
|
|
|
- const touches = e.touches;
|
|
|
- for (let i = 0; i < touches.length; i++) {
|
|
|
- const touch = touches[i];
|
|
|
- if (fingers[touch.identifier]) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- const x = touch.clientX * scale;
|
|
|
- const y = touch.clientY * scale;
|
|
|
- const downIndex =
|
|
|
- scrollType == "vertical"
|
|
|
- ? Math.floor(x / (itemOffset + paddingOffset))
|
|
|
- : Math.floor(y / (itemOffset + paddingOffset));
|
|
|
- cols[downIndex].dragging = true;
|
|
|
- const offset = cols[downIndex].offset;
|
|
|
- fingers[touch.identifier] = {
|
|
|
- identifier: touch.identifier,
|
|
|
- downY: y,
|
|
|
- downX: x,
|
|
|
- downIndex: downIndex,
|
|
|
- offset: offset,
|
|
|
- downTime: Date.now(),
|
|
|
- };
|
|
|
- }
|
|
|
- };
|
|
|
- const onTouchMove = (e: TouchEvent) => {
|
|
|
- const touches = e.changedTouches;
|
|
|
- for (let i = 0; i < touches.length; i++) {
|
|
|
- const touch = touches[i];
|
|
|
- const finger = fingers[touch.identifier];
|
|
|
- if (!finger) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- finger.moving = true;
|
|
|
- let dtaOffset = 0;
|
|
|
- if (scrollType == "vertical") {
|
|
|
- dtaOffset = touch.clientY * scale - finger.downY;
|
|
|
- }
|
|
|
- if (scrollType == "horizontal") {
|
|
|
- dtaOffset = touch.clientX * scale - finger.downY;
|
|
|
- }
|
|
|
- cols[finger.downIndex].offset = finger.offset + dtaOffset;
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- const onTouchEnd = (e: TouchEvent) => {
|
|
|
- const touches = e.changedTouches;
|
|
|
- for (let i = 0; i < touches.length; i++) {
|
|
|
- const touch = touches[i];
|
|
|
- const finger = fingers[touch.identifier];
|
|
|
-
|
|
|
- if (!finger) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- cols[finger.downIndex].dragging = false;
|
|
|
- const dtaTime = Date.now() - finger.downTime;
|
|
|
- if (dtaTime < 200 && !finger.moving) {
|
|
|
- const col = cols[finger.downIndex];
|
|
|
- let offset = col.offset;
|
|
|
- if (offset >= col.halfOffset) offset -= col.halfOffset;
|
|
|
- if (offset < 0) offset += col.halfOffset;
|
|
|
- const n = col.items.length;
|
|
|
- let z =
|
|
|
- scrollType == "vertical"
|
|
|
- ? offset + CanvasHeight
|
|
|
- : offset + CanvasWidth;
|
|
|
- for (let k = 0; k < n; k++) {
|
|
|
- const item = col.items[k];
|
|
|
-
|
|
|
- if (scrollType == "vertical") {
|
|
|
- z -= item.offsetY;
|
|
|
- if (finger.downY > z && finger.downY < z + item.offsetY) {
|
|
|
- this.actions.popDialog(touch, item);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (scrollType == "horizontal") {
|
|
|
- z -= item.offsetX;
|
|
|
- if (finger.downX > z && finger.downX < z + item.offsetX) {
|
|
|
- this.actions.popDialog(touch, item);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- delete fingers[touch.identifier];
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- canvas.addEventListener("mousedown", onMouseDown, false);
|
|
|
- canvas.addEventListener("mousemove", onMouseMove, false);
|
|
|
- document.addEventListener("mouseup", onMouseUp, false);
|
|
|
-
|
|
|
- canvas.addEventListener("touchstart", onTouchstart, false);
|
|
|
- canvas.addEventListener("touchmove", onTouchMove, false);
|
|
|
- document.addEventListener("touchend", onTouchEnd, false);
|
|
|
- },
|
|
|
+ // loopRunning() {},
|
|
|
});
|