|
|
@@ -37,7 +37,9 @@ VueLikePage([], {
|
|
|
canvasHeight: 600,
|
|
|
widgetVisible: true,
|
|
|
zoomScrollLeft: 0,
|
|
|
- scaleOrientation: ''
|
|
|
+ scaleOrientation: '',
|
|
|
+ baseUniformScale: 1,
|
|
|
+ confirmedIps: []
|
|
|
},
|
|
|
methods: {
|
|
|
zoom() {
|
|
|
@@ -49,6 +51,8 @@ VueLikePage([], {
|
|
|
ipScaleY: 1,
|
|
|
ipRotate: 0,
|
|
|
ipConfirmed: false,
|
|
|
+ confirmedIps: [],
|
|
|
+ zoomScrollLeft: 0
|
|
|
});
|
|
|
},
|
|
|
onLoad: function (options) {
|
|
|
@@ -83,10 +87,10 @@ VueLikePage([], {
|
|
|
},
|
|
|
initIpsList(projectid) {
|
|
|
const list = [];
|
|
|
- for (let i = 1; i <= 44; i++) {
|
|
|
+ for (let i = 1; i <= 34; i++) {
|
|
|
list.push({
|
|
|
name: String(i),
|
|
|
- imgUrl: `${CDN_URL}/ZHS2409020-1/ip/${i}.png`,
|
|
|
+ imgUrl: `${CDN_URL}/${projectid}/ip/${i}.png`,
|
|
|
});
|
|
|
}
|
|
|
this.setData({
|
|
|
@@ -159,10 +163,12 @@ VueLikePage([], {
|
|
|
if (this.data.selectedIp) {
|
|
|
query.select('.ip-overlay').boundingClientRect();
|
|
|
}
|
|
|
+ query.selectAll('.confirmed-overlay').boundingClientRect();
|
|
|
|
|
|
const res = await new Promise(resolve => query.exec(resolve));
|
|
|
const container = res[0];
|
|
|
const overlay = this.data.selectedIp ? res[1] : null;
|
|
|
+ const confirmedRects = this.data.selectedIp ? (res[2] || []) : (res[1] || []);
|
|
|
|
|
|
if (!container) throw new Error('Cannot find container');
|
|
|
|
|
|
@@ -223,49 +229,92 @@ VueLikePage([], {
|
|
|
|
|
|
await widget.renderToCanvas({ wxml, style });
|
|
|
|
|
|
- if (this.data.selectedIp && overlay) {
|
|
|
- const ctx = widget.ctx;
|
|
|
- const use2d = widget.data.use2dCanvas;
|
|
|
- const stickerUrl = this.data.selectedIp.imgUrl;
|
|
|
-
|
|
|
- // Get local path
|
|
|
- const stickerInfo = await new Promise((resolve, reject) => {
|
|
|
- wx.getImageInfo({
|
|
|
- src: stickerUrl,
|
|
|
- success: resolve,
|
|
|
- fail: reject
|
|
|
- })
|
|
|
+ const ctx = widget.ctx;
|
|
|
+ const use2d = widget.data.use2dCanvas;
|
|
|
+ const ratio = canvasWidth / container.width;
|
|
|
+
|
|
|
+ // Draw confirmed overlays
|
|
|
+ for (let i = 0; i < this.data.confirmedIps.length; i++) {
|
|
|
+ const ov = this.data.confirmedIps[i];
|
|
|
+ const rect = confirmedRects[i];
|
|
|
+ if (!ov || !rect) continue;
|
|
|
+
|
|
|
+ const stickerInfo = await new Promise((resolve, reject) => {
|
|
|
+ wx.getImageInfo({
|
|
|
+ src: ov.imgUrl,
|
|
|
+ success: resolve,
|
|
|
+ fail: reject
|
|
|
+ })
|
|
|
+ });
|
|
|
+
|
|
|
+ let imgToDraw = stickerInfo.path;
|
|
|
+ if (use2d) {
|
|
|
+ const canvas = widget.canvas;
|
|
|
+ const img = canvas.createImage();
|
|
|
+ await new Promise((resolve, reject) => {
|
|
|
+ img.onload = resolve;
|
|
|
+ img.onerror = reject;
|
|
|
+ img.src = stickerInfo.path;
|
|
|
});
|
|
|
-
|
|
|
- let imgToDraw = stickerInfo.path;
|
|
|
- if (use2d) {
|
|
|
- const canvas = widget.canvas;
|
|
|
- const img = canvas.createImage();
|
|
|
- await new Promise((resolve, reject) => {
|
|
|
- img.onload = resolve;
|
|
|
- img.onerror = reject;
|
|
|
- img.src = stickerInfo.path;
|
|
|
- });
|
|
|
- imgToDraw = img;
|
|
|
- }
|
|
|
-
|
|
|
- const ratio = canvasWidth / container.width;
|
|
|
- const cx = ((overlay.left - container.left + overlay.width / 2) + (this.data.isZoom ? this.data.zoomScrollLeft : 0)) * ratio;
|
|
|
- const cy = (overlay.top - container.top + overlay.height / 2) * ratio;
|
|
|
- const overlayWidth = overlay.width * ratio;
|
|
|
- const overlayHeight = overlay.height * ratio;
|
|
|
-
|
|
|
- ctx.save();
|
|
|
- ctx.translate(cx, cy);
|
|
|
- ctx.rotate(this.data.ipRotate * Math.PI / 180);
|
|
|
- ctx.scale(this.data.ipScaleX, this.data.ipScaleY);
|
|
|
- ctx.drawImage(imgToDraw, -overlayWidth / 2, -overlayHeight / 2, overlayWidth, overlayHeight);
|
|
|
- ctx.restore();
|
|
|
-
|
|
|
- // If legacy, might need draw()
|
|
|
- if (!use2d) {
|
|
|
- await new Promise(resolve => ctx.draw(true, resolve));
|
|
|
- }
|
|
|
+ imgToDraw = img;
|
|
|
+ }
|
|
|
+
|
|
|
+ const cx = ((rect.left - container.left + rect.width / 2) + (this.data.isZoom ? this.data.zoomScrollLeft : 0)) * ratio;
|
|
|
+ const cy = (rect.top - container.top + rect.height / 2) * ratio;
|
|
|
+ const overlayWidth = rect.width * ratio;
|
|
|
+ const overlayHeight = rect.height * ratio;
|
|
|
+
|
|
|
+ ctx.save();
|
|
|
+ ctx.translate(cx, cy);
|
|
|
+ ctx.rotate(ov.rotate * Math.PI / 180);
|
|
|
+ ctx.scale(ov.scaleX, ov.scaleY);
|
|
|
+ ctx.drawImage(imgToDraw, -overlayWidth / 2, -overlayHeight / 2, overlayWidth, overlayHeight);
|
|
|
+ ctx.restore();
|
|
|
+
|
|
|
+ if (!use2d) {
|
|
|
+ await new Promise(resolve => ctx.draw(true, resolve));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Draw active overlay if exists
|
|
|
+ if (this.data.selectedIp && overlay) {
|
|
|
+ const stickerUrl = this.data.selectedIp.imgUrl;
|
|
|
+
|
|
|
+ const stickerInfo = await new Promise((resolve, reject) => {
|
|
|
+ wx.getImageInfo({
|
|
|
+ src: stickerUrl,
|
|
|
+ success: resolve,
|
|
|
+ fail: reject
|
|
|
+ })
|
|
|
+ });
|
|
|
+
|
|
|
+ let imgToDraw = stickerInfo.path;
|
|
|
+ if (use2d) {
|
|
|
+ const canvas = widget.canvas;
|
|
|
+ const img = canvas.createImage();
|
|
|
+ await new Promise((resolve, reject) => {
|
|
|
+ img.onload = resolve;
|
|
|
+ img.onerror = reject;
|
|
|
+ img.src = stickerInfo.path;
|
|
|
+ });
|
|
|
+ imgToDraw = img;
|
|
|
+ }
|
|
|
+
|
|
|
+ const cx = ((overlay.left - container.left + overlay.width / 2) + (this.data.isZoom ? this.data.zoomScrollLeft : 0)) * ratio;
|
|
|
+ const cy = (overlay.top - container.top + overlay.height / 2) * ratio;
|
|
|
+ const overlayWidth = overlay.width * ratio;
|
|
|
+ const overlayHeight = overlay.height * ratio;
|
|
|
+
|
|
|
+ ctx.save();
|
|
|
+ ctx.translate(cx, cy);
|
|
|
+ ctx.rotate(this.data.ipRotate * Math.PI / 180);
|
|
|
+ ctx.scale(this.data.ipScaleX, this.data.ipScaleY);
|
|
|
+ ctx.drawImage(imgToDraw, -overlayWidth / 2, -overlayHeight / 2, overlayWidth, overlayHeight);
|
|
|
+ ctx.restore();
|
|
|
+
|
|
|
+ if (!use2d) {
|
|
|
+ await new Promise(resolve => ctx.draw(true, resolve));
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
const { tempFilePath } = await widget.canvasToTempFilePath();
|
|
|
@@ -357,7 +406,7 @@ VueLikePage([], {
|
|
|
}
|
|
|
},
|
|
|
|
|
|
- // 横琴是ZHS2409020-1,替换
|
|
|
+ // 横琴是ZHS2409020-1,替换 ZHS2305758-1
|
|
|
getData(prjId = "ZHS2305758-1") {
|
|
|
wx.showLoading({
|
|
|
title: "资源加载中",
|
|
|
@@ -388,33 +437,39 @@ VueLikePage([], {
|
|
|
const index = e.currentTarget.dataset.index;
|
|
|
const item = this.data.ipsImgList[index];
|
|
|
if (!item) return;
|
|
|
- this.setData({
|
|
|
- selectedIpIndex: index,
|
|
|
- selectedIp: item,
|
|
|
- ipScaleX: 1,
|
|
|
- ipScaleY: 1,
|
|
|
- ipRotate: 0,
|
|
|
- ipConfirmed: false,
|
|
|
- positionInitialized: false,
|
|
|
- }, () => {
|
|
|
- this.getOverlayRect();
|
|
|
-
|
|
|
- // Initialize position
|
|
|
- const query = wx.createSelectorQuery();
|
|
|
- query.select('.w_video').boundingClientRect();
|
|
|
- query.select('.ip-overlay').boundingClientRect();
|
|
|
- query.exec((res) => {
|
|
|
- const container = res[0];
|
|
|
- const overlay = res[1];
|
|
|
- if (container && overlay) {
|
|
|
- this.setData({
|
|
|
- ipLeft: overlay.left - container.left,
|
|
|
- ipTop: overlay.top - container.top,
|
|
|
- positionInitialized: true
|
|
|
- });
|
|
|
- }
|
|
|
+ if (this.data.selectedIp && !this.data.ipConfirmed) {
|
|
|
+ this.setData({
|
|
|
+ selectedIpIndex: index,
|
|
|
+ selectedIp: item
|
|
|
});
|
|
|
- });
|
|
|
+ } else {
|
|
|
+ this.setData({
|
|
|
+ selectedIpIndex: index,
|
|
|
+ selectedIp: item,
|
|
|
+ ipScaleX: 1,
|
|
|
+ ipScaleY: 1,
|
|
|
+ ipRotate: 0,
|
|
|
+ ipConfirmed: false,
|
|
|
+ positionInitialized: false,
|
|
|
+ }, () => {
|
|
|
+ this.getOverlayRect();
|
|
|
+
|
|
|
+ const query = wx.createSelectorQuery();
|
|
|
+ query.select('.w_video').boundingClientRect();
|
|
|
+ query.select('.ip-overlay').boundingClientRect();
|
|
|
+ query.exec((res) => {
|
|
|
+ const container = res[0];
|
|
|
+ const overlay = res[1];
|
|
|
+ if (container && overlay) {
|
|
|
+ this.setData({
|
|
|
+ ipLeft: overlay.left - container.left,
|
|
|
+ ipTop: overlay.top - container.top,
|
|
|
+ positionInitialized: true
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
dragStart(e) {
|
|
|
@@ -484,43 +539,18 @@ VueLikePage([], {
|
|
|
this.setData({
|
|
|
startX: touch.clientX,
|
|
|
startY: touch.clientY,
|
|
|
- baseIpScaleX: this.data.ipScaleX,
|
|
|
- baseIpScaleY: this.data.ipScaleY,
|
|
|
- scaleOrientation: ''
|
|
|
+ baseUniformScale: (this.data.ipScaleX + this.data.ipScaleY) / 2
|
|
|
});
|
|
|
},
|
|
|
|
|
|
scaleMove(e) {
|
|
|
const touch = e.touches[0];
|
|
|
- const dx = touch.clientX - this.data.startX;
|
|
|
const dy = touch.clientY - this.data.startY;
|
|
|
const factor = 0.005;
|
|
|
- let { scaleOrientation } = this.data;
|
|
|
-
|
|
|
- if (!scaleOrientation) {
|
|
|
- const adx = Math.abs(dx);
|
|
|
- const ady = Math.abs(dy);
|
|
|
- if (adx > ady && adx > 3) {
|
|
|
- scaleOrientation = 'x';
|
|
|
- } else if (ady >= adx && ady > 3) {
|
|
|
- scaleOrientation = 'y';
|
|
|
- } else {
|
|
|
- return;
|
|
|
- }
|
|
|
- this.setData({ scaleOrientation });
|
|
|
- }
|
|
|
-
|
|
|
- if (scaleOrientation === 'x') {
|
|
|
- let nextScaleX = this.data.baseIpScaleX + (-dx) * factor;
|
|
|
- if (nextScaleX < 0.2) nextScaleX = 0.2;
|
|
|
- if (nextScaleX > 4) nextScaleX = 4;
|
|
|
- this.setData({ ipScaleX: nextScaleX });
|
|
|
- } else {
|
|
|
- let nextScaleY = this.data.baseIpScaleY + (-dy) * factor;
|
|
|
- if (nextScaleY < 0.2) nextScaleY = 0.2;
|
|
|
- if (nextScaleY > 4) nextScaleY = 4;
|
|
|
- this.setData({ ipScaleY: nextScaleY });
|
|
|
- }
|
|
|
+ let nextScale = this.data.baseUniformScale + (-dy) * factor;
|
|
|
+ if (nextScale < 0.2) nextScale = 0.2;
|
|
|
+ if (nextScale > 4) nextScale = 4;
|
|
|
+ this.setData({ ipScaleX: nextScale, ipScaleY: nextScale });
|
|
|
},
|
|
|
|
|
|
rotateIp() {
|
|
|
@@ -556,8 +586,24 @@ VueLikePage([], {
|
|
|
},
|
|
|
confirmIp() {
|
|
|
if (!this.data.selectedIp) return;
|
|
|
+ const overlayItem = {
|
|
|
+ id: Date.now(),
|
|
|
+ imgUrl: this.data.selectedIp.imgUrl,
|
|
|
+ scaleX: this.data.ipScaleX,
|
|
|
+ scaleY: this.data.ipScaleY,
|
|
|
+ rotate: this.data.ipRotate,
|
|
|
+ left: this.data.ipLeft,
|
|
|
+ top: this.data.ipTop
|
|
|
+ };
|
|
|
this.setData({
|
|
|
- ipConfirmed: true,
|
|
|
+ confirmedIps: [...this.data.confirmedIps, overlayItem],
|
|
|
+ selectedIp: null,
|
|
|
+ selectedIpIndex: -1,
|
|
|
+ ipScaleX: 1,
|
|
|
+ ipScaleY: 1,
|
|
|
+ ipRotate: 0,
|
|
|
+ ipConfirmed: false,
|
|
|
+ positionInitialized: false
|
|
|
});
|
|
|
},
|
|
|
},
|