canvas/unpackage/dist/dev/app-plus/app-service.js
2025-06-26 18:15:12 +08:00

469 lines
17 KiB
JavaScript

if (typeof Promise !== "undefined" && !Promise.prototype.finally) {
Promise.prototype.finally = function(callback) {
const promise = this.constructor;
return this.then(
(value) => promise.resolve(callback()).then(() => value),
(reason) => promise.resolve(callback()).then(() => {
throw reason;
})
);
};
}
;
if (typeof uni !== "undefined" && uni && uni.requireGlobal) {
const global = uni.requireGlobal();
ArrayBuffer = global.ArrayBuffer;
Int8Array = global.Int8Array;
Uint8Array = global.Uint8Array;
Uint8ClampedArray = global.Uint8ClampedArray;
Int16Array = global.Int16Array;
Uint16Array = global.Uint16Array;
Int32Array = global.Int32Array;
Uint32Array = global.Uint32Array;
Float32Array = global.Float32Array;
Float64Array = global.Float64Array;
BigInt64Array = global.BigInt64Array;
BigUint64Array = global.BigUint64Array;
}
;
if (uni.restoreGlobal) {
uni.restoreGlobal(Vue, weex, plus, setTimeout, clearTimeout, setInterval, clearInterval);
}
(function(vue) {
"use strict";
function formatAppLog(type, filename, ...args) {
if (uni.__log__) {
uni.__log__(type, filename, ...args);
} else {
console[type].apply(console, [...args, filename]);
}
}
const _export_sfc = (sfc, props) => {
const target = sfc.__vccOpts || sfc;
for (const [key, val] of props) {
target[key] = val;
}
return target;
};
const _sfc_main$2 = {
data() {
return {
ctx: null,
canvasWidth: 300,
canvasHeight: 500,
seatSize: 30,
gap: 10,
rows: 8,
cols: 10,
seats: [],
selectedSeats: [],
touchStartX: 0,
touchStartY: 0,
offsetX: 0,
offsetY: 0
};
},
onReady() {
this.initSeats();
this.initAndroidCanvas();
},
methods: {
initSeats() {
for (let i = 0; i < this.rows; i++) {
this.seats[i] = [];
for (let j = 0; j < this.cols; j++) {
const isSold = Math.random() < 0.2;
this.seats[i][j] = {
row: i,
col: j,
status: isSold ? "sold" : "available",
x: 0,
y: 0
};
}
}
},
// 替换原来的 initAndroidCanvas 方法
initAndroidCanvas() {
return new Promise((resolve) => {
this.ctx = uni.createCanvasContext("seatCanvas", this);
formatAppLog("log", "at pages/index/step2.vue:77", this.ctx, "ctx123123123");
const query = uni.createSelectorQuery().in(this);
query.select(".seat-canvas").boundingClientRect((rect) => {
if (!rect) {
formatAppLog("error", "at pages/index/step2.vue:83", "获取Canvas尺寸失败");
return resolve(false);
}
this.canvasWidth = rect.width;
this.canvasHeight = rect.height;
const totalWidth = this.cols * (this.seatSize + this.gap) - this.gap;
const totalHeight = this.rows * (this.seatSize + this.gap) - this.gap;
this.offsetX = (this.canvasWidth - totalWidth) / 2;
this.offsetY = (this.canvasHeight - totalHeight) / 2;
this.drawSeats();
resolve(true);
}).exec();
});
},
drawSeats() {
if (!this.ctx)
return;
this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
for (let i = 0; i < this.rows; i++) {
for (let j = 0; j < this.cols; j++) {
const seat = this.seats[i][j];
const x = j * (this.seatSize + this.gap) + this.offsetX;
const y = i * (this.seatSize + this.gap) + this.offsetY;
seat.x = x;
seat.y = y;
switch (seat.status) {
case "available":
this.ctx.setFillStyle("#4CAF50");
break;
case "selected":
this.ctx.setFillStyle("#2196F3");
break;
case "sold":
this.ctx.setFillStyle("#9E9E9E");
break;
}
this.ctx.fillRect(x, y, this.seatSize, this.seatSize);
this.ctx.setFillStyle("#FFFFFF");
this.ctx.setFontSize(12);
this.ctx.setTextAlign("center");
this.ctx.fillText(
`${String.fromCharCode(65 + i)}${j + 1}`,
x + this.seatSize / 2,
y + this.seatSize / 2 + 4
// 安卓平台文字垂直对齐需要微调
);
}
}
this.ctx.draw();
},
// 触摸事件处理(安卓专用优化)
handleTouchStart(e) {
this.touchStartX = e.touches[0].x;
this.touchStartY = e.touches[0].y;
},
handleTouchMove(e) {
const touchX = e.touches[0].x;
const touchY = e.touches[0].y;
const dx = touchX - this.touchStartX;
const dy = touchY - this.touchStartY;
this.offsetX += dx;
this.offsetY += dy;
const minX = this.canvasWidth - (this.cols * (this.seatSize + this.gap) - this.gap);
const minY = this.canvasHeight - (this.rows * (this.seatSize + this.gap) - this.gap);
this.offsetX = Math.max(minX, Math.min(0, this.offsetX));
this.offsetY = Math.max(minY, Math.min(0, this.offsetY));
this.touchStartX = touchX;
this.touchStartY = touchY;
this.drawSeats();
},
handleTouchEnd(e) {
const touchX = e.changedTouches[0].x;
const touchY = e.changedTouches[0].y;
for (let i = 0; i < this.rows; i++) {
for (let j = 0; j < this.cols; j++) {
const seat = this.seats[i][j];
if (touchX >= seat.x && touchX <= seat.x + this.seatSize && touchY >= seat.y && touchY <= seat.y + this.seatSize) {
this.toggleSeatSelection(seat);
return;
}
}
}
},
toggleSeatSelection(seat) {
if (seat.status === "sold")
return;
if (seat.status === "available") {
seat.status = "selected";
this.selectedSeats.push(`${String.fromCharCode(65 + seat.row)}${seat.col + 1}`);
} else {
seat.status = "available";
this.selectedSeats = this.selectedSeats.filter(
(s) => s !== `${String.fromCharCode(65 + seat.row)}${seat.col + 1}`
);
}
this.drawSeats();
}
}
};
function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "container" }, [
vue.createElementVNode("view", { class: "screen" }, "银幕"),
vue.createElementVNode(
"canvas",
{
"canvas-id": "seatCanvas",
type: "2d",
class: "seat-canvas",
onTouchstart: _cache[0] || (_cache[0] = (...args) => $options.handleTouchStart && $options.handleTouchStart(...args)),
onTouchmove: _cache[1] || (_cache[1] = (...args) => $options.handleTouchMove && $options.handleTouchMove(...args)),
onTouchend: _cache[2] || (_cache[2] = (...args) => $options.handleTouchEnd && $options.handleTouchEnd(...args))
},
null,
32
/* NEED_HYDRATION */
),
vue.createElementVNode("view", { class: "legend" }, [
vue.createElementVNode("view", { class: "legend-item" }, [
vue.createElementVNode("view", { class: "seat-icon available" }),
vue.createElementVNode("text", null, "可选")
]),
vue.createElementVNode("view", { class: "legend-item" }, [
vue.createElementVNode("view", { class: "seat-icon selected" }),
vue.createElementVNode("text", null, "已选")
]),
vue.createElementVNode("view", { class: "legend-item" }, [
vue.createElementVNode("view", { class: "seat-icon sold" }),
vue.createElementVNode("text", null, "已售")
])
]),
vue.createElementVNode("view", { class: "selected-seats" }, [
vue.createElementVNode(
"text",
null,
"已选座位:" + vue.toDisplayString($data.selectedSeats.join(", ") || "无"),
1
/* TEXT */
)
])
]);
}
const PagesIndexStep2 = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$1], ["__file", "/Users/sunmeng/Desktop/wx/canvas/pages/index/step2.vue"]]);
const _sfc_main$1 = {
data() {
return {
ctx: null,
canvasWidth: 0,
canvasHeight: 0,
seatSize: 30,
gap: 10,
rows: 8,
cols: 10,
seats: [],
selectedSeats: [],
touchStartX: 0,
touchStartY: 0,
offsetX: 0,
offsetY: 0,
scale: 1
};
},
onReady() {
this.initSeats();
this.initCanvas();
},
methods: {
initSeats() {
for (let i = 0; i < this.rows; i++) {
this.seats[i] = [];
for (let j = 0; j < this.cols; j++) {
const isSold = Math.random() < 0.2;
this.seats[i][j] = {
row: i,
col: j,
status: isSold ? "sold" : "available",
// available, selected, sold
x: 0,
y: 0
};
}
}
},
async initCanvas() {
const { canvas, width, height } = await this.getCanvasNode("seatCanvas");
this.canvasWidth = width;
this.canvasHeight = height;
this.ctx = canvas.getContext("2d");
const totalWidth = this.cols * (this.seatSize + this.gap) - this.gap;
const totalHeight = this.rows * (this.seatSize + this.gap) - this.gap;
this.offsetX = (this.canvasWidth - totalWidth) / 2;
this.offsetY = (this.canvasHeight - totalHeight) / 2;
this.drawSeats();
},
getCanvasNode(id) {
return new Promise((resolve) => {
const query = uni.createSelectorQuery().in(this);
query.select(`#${id}`).fields({ node: true, size: true }).exec((res) => {
formatAppLog("log", "at pages/index/index.vue:94", "给我看看", res);
formatAppLog("log", "at pages/index/index.vue:95", "给我看看", res);
formatAppLog("log", "at pages/index/index.vue:96", "给我看看", res);
formatAppLog("log", "at pages/index/index.vue:97", "给我看看", res);
formatAppLog("log", "at pages/index/index.vue:98", "给我看看", res);
formatAppLog("log", "at pages/index/index.vue:99", "给我看看", res);
const canvas = res[0].node;
const width = res[0].width;
const height = res[0].height;
canvas.width = width * uni.getSystemInfoSync().pixelRatio;
canvas.height = height * uni.getSystemInfoSync().pixelRatio;
resolve({ canvas, width, height });
});
});
},
drawSeats() {
if (!this.ctx)
return;
this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
this.ctx.save();
this.ctx.translate(this.offsetX, this.offsetY);
this.ctx.scale(this.scale, this.scale);
for (let i = 0; i < this.rows; i++) {
for (let j = 0; j < this.cols; j++) {
const seat = this.seats[i][j];
const x = j * (this.seatSize + this.gap);
const y = i * (this.seatSize + this.gap);
seat.x = x;
seat.y = y;
switch (seat.status) {
case "available":
this.ctx.fillStyle = "#4CAF50";
break;
case "selected":
this.ctx.fillStyle = "#2196F3";
break;
case "sold":
this.ctx.fillStyle = "#9E9E9E";
break;
}
this.ctx.beginPath();
this.ctx.roundRect(x, y, this.seatSize, this.seatSize, 4);
this.ctx.fill();
this.ctx.fillStyle = "#FFFFFF";
this.ctx.font = "12px Arial";
this.ctx.textAlign = "center";
this.ctx.textBaseline = "middle";
this.ctx.fillText(
`${String.fromCharCode(65 + i)}${j + 1}`,
x + this.seatSize / 2,
y + this.seatSize / 2
);
}
}
this.ctx.restore();
},
handleTouchStart(e) {
this.touchStartX = e.touches[0].x;
this.touchStartY = e.touches[0].y;
},
handleTouchMove(e) {
const touchX = e.touches[0].x;
const touchY = e.touches[0].y;
const dx = touchX - this.touchStartX;
const dy = touchY - this.touchStartY;
this.offsetX += dx;
this.offsetY += dy;
const minX = this.canvasWidth - (this.cols * (this.seatSize + this.gap) - this.gap) * this.scale;
const minY = this.canvasHeight - (this.rows * (this.seatSize + this.gap) - this.gap) * this.scale;
this.offsetX = Math.max(minX, Math.min(0, this.offsetX));
this.offsetY = Math.max(minY, Math.min(0, this.offsetY));
this.touchStartX = touchX;
this.touchStartY = touchY;
this.drawSeats();
},
handleTouchEnd(e) {
const touchX = e.changedTouches[0].x;
const touchY = e.changedTouches[0].y;
const canvasX = (touchX - this.offsetX) / this.scale;
const canvasY = (touchY - this.offsetY) / this.scale;
for (let i = 0; i < this.rows; i++) {
for (let j = 0; j < this.cols; j++) {
const seat = this.seats[i][j];
if (canvasX >= seat.x && canvasX <= seat.x + this.seatSize && canvasY >= seat.y && canvasY <= seat.y + this.seatSize) {
this.toggleSeatSelection(seat);
return;
}
}
}
},
toggleSeatSelection(seat) {
if (seat.status === "sold")
return;
if (seat.status === "available") {
seat.status = "selected";
this.selectedSeats.push(`${String.fromCharCode(65 + seat.row)}${seat.col + 1}`);
} else {
seat.status = "available";
this.selectedSeats = this.selectedSeats.filter(
(s) => s !== `${String.fromCharCode(65 + seat.row)}${seat.col + 1}`
);
}
this.drawSeats();
}
}
};
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "container" }, [
vue.createElementVNode("view", { class: "screen" }, "银幕"),
vue.createElementVNode(
"canvas",
{
"canvas-id": "seatCanvas",
type: "2d",
class: "seat-canvas",
onTouchstart: _cache[0] || (_cache[0] = (...args) => $options.handleTouchStart && $options.handleTouchStart(...args)),
onTouchmove: _cache[1] || (_cache[1] = (...args) => $options.handleTouchMove && $options.handleTouchMove(...args)),
onTouchend: _cache[2] || (_cache[2] = (...args) => $options.handleTouchEnd && $options.handleTouchEnd(...args))
},
null,
32
/* NEED_HYDRATION */
),
vue.createElementVNode("view", { class: "legend" }, [
vue.createElementVNode("view", { class: "legend-item" }, [
vue.createElementVNode("view", { class: "seat-icon available" }),
vue.createElementVNode("text", null, "可选")
]),
vue.createElementVNode("view", { class: "legend-item" }, [
vue.createElementVNode("view", { class: "seat-icon selected" }),
vue.createElementVNode("text", null, "已选")
]),
vue.createElementVNode("view", { class: "legend-item" }, [
vue.createElementVNode("view", { class: "seat-icon sold" }),
vue.createElementVNode("text", null, "已售")
])
]),
vue.createElementVNode("view", { class: "selected-seats" }, [
vue.createElementVNode(
"text",
null,
"已选座位:" + vue.toDisplayString($data.selectedSeats.join(", ") || "无"),
1
/* TEXT */
)
])
]);
}
const PagesIndexIndex = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render], ["__file", "/Users/sunmeng/Desktop/wx/canvas/pages/index/index.vue"]]);
__definePage("pages/index/step2", PagesIndexStep2);
__definePage("pages/index/index", PagesIndexIndex);
const _sfc_main = {
onLaunch: function() {
formatAppLog("log", "at App.vue:4", "App Launch");
},
onShow: function() {
formatAppLog("log", "at App.vue:7", "App Show");
},
onHide: function() {
formatAppLog("log", "at App.vue:10", "App Hide");
}
};
const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["__file", "/Users/sunmeng/Desktop/wx/canvas/App.vue"]]);
function createApp() {
const app = vue.createVueApp(App);
return {
app
};
}
const { app: __app__, Vuex: __Vuex__, Pinia: __Pinia__ } = createApp();
uni.Vuex = __Vuex__;
uni.Pinia = __Pinia__;
__app__.provide("__globalStyles", __uniConfig.styles);
__app__._component.mpType = "app";
__app__._component.render = () => {
};
__app__.mount("#app");
})(Vue);