wangfumin 1 неделя назад
Родитель
Сommit
a887de4b7e
4 измененных файлов с 164 добавлено и 112 удалено
  1. 1 1
      pages/index/index.js
  2. 149 103
      pages/work/index.js
  3. 10 0
      pages/work/index.wxml
  4. 4 8
      pages/work/index.wxss

+ 1 - 1
pages/index/index.js

@@ -214,7 +214,7 @@ VueLikePage([], {
       //   currentScene:tmp[0].id
       // })
     },
-    // 横琴是ZHS2409020-1,替换
+    // 横琴是ZHS2409020-1,替换 ZHS2305758-1
     getData(prjId = "ZHS2305758-1", scenes) {
       this.setData({
         cdn_url: CDN_URL + "/" + prjId,

+ 149 - 103
pages/work/index.js

@@ -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
       });
     },
   },

+ 10 - 0
pages/work/index.wxml

@@ -15,6 +15,11 @@
     <view wx:if="{{!isZoom}}" class="w_video" style="background-image: url({{cdn_url+info.resourceImg.bg}});{{info.resourceImg.style}}">
       <video wx:if="{{type=='0'}}" style="opacity:{{loadCompele?1:0}};{{info.resourceImg.imgStyle}}" bindloadedmetadata="loadcompele" src="{{url_link}}" loop autoplay controls="{{false}}" enable-progress-gesture="{{false}}"></video>
       <image wx:else style="opacity:{{loadCompele?1:0}};{{info.resourceImg.imgStyle}}" bindload="loadcompele" show-menu-by-longpress="true" src="{{url_link}}" mode="widthFix" />
+      <block wx:if="{{projectid == 'ZHS2409020-1'}}">
+        <view wx:for="{{confirmedIps}}" wx:key="id" class="ip-overlay ip-overlay__confirmed confirmed-overlay" style="left:{{item.left}}px; top:{{item.top}}px; right:auto; bottom:auto;">
+          <image class="ip-main" src="{{item.imgUrl}}" style="transform:scale({{item.scaleX}}, {{item.scaleY}}) rotate({{item.rotate}}deg) translateZ(0); will-change: transform;" />
+        </view>
+      </block>
       <view wx:if="{{selectedIp && projectid == 'ZHS2409020-1'}}" class="ip-overlay {{ipConfirmed ? 'ip-overlay__confirmed' : ''}}" style="opacity:{{positionInitialized?1:0}}; {{positionInitialized ? 'left:'+ipLeft+'px; top:'+ipTop+'px; right: auto; bottom: auto;' : ''}}">
         <image class="ip-main" src="{{selectedIp.imgUrl}}" style="transform:scale({{ipScaleX}}, {{ipScaleY}}) rotate({{ipRotate}}deg) translateZ(0); will-change: transform;" catchtouchstart="dragStart" catchtouchmove="dragMove" />
         <image class="ip-btn ip-btn__rotate" src="/assets/img/icon_rorate.png" mode="widthFix" catchtouchstart="rotateStart" catchtouchmove="rotateMove" />
@@ -28,6 +33,11 @@
       <scroll-view scroll-x="true" class="zoom-scroll" show-scrollbar="{{false}}" bindscroll="onZoomScroll">
         <image class="zoom-image" mode="heightFix" bindload="loadcompele" show-menu-by-longpress="true" src="{{url_link}}" />
       </scroll-view>
+      <block wx:if="{{projectid == 'ZHS2409020-1'}}">
+        <view wx:for="{{confirmedIps}}" wx:key="id" class="ip-overlay ip-overlay__confirmed confirmed-overlay" style="left:{{item.left}}px; top:{{item.top}}px; right:auto; bottom:auto;">
+          <image class="ip-main" src="{{item.imgUrl}}" style="transform:scale({{item.scaleX}}, {{item.scaleY}}) rotate({{item.rotate}}deg) translateZ(0); will-change: transform;" />
+        </view>
+      </block>
       <view wx:if="{{selectedIp && projectid == 'ZHS2409020-1'}}" class="ip-overlay {{ipConfirmed ? 'ip-overlay__confirmed' : ''}}" style="opacity:{{positionInitialized?1:0}}; {{positionInitialized ? 'left:'+ipLeft+'px; top:'+ipTop+'px; right: auto; bottom: auto;' : ''}}">
         <image class="ip-main" src="{{selectedIp.imgUrl}}" style="transform:scale({{ipScaleX}}, {{ipScaleY}}) rotate({{ipRotate}}deg) translateZ(0); will-change: transform;" catchtouchstart="dragStart" catchtouchmove="dragMove" />
         <image class="ip-btn ip-btn__rotate" src="/assets/img/icon_rorate.png" mode="widthFix" catchtouchstart="rotateStart" catchtouchmove="rotateMove" />

+ 4 - 8
pages/work/index.wxss

@@ -194,18 +194,14 @@
   position: absolute;
   right: 40rpx;
   bottom: 40rpx;
-  min-width: 140rpx;
-  max-width: 220rpx;
-  min-height: 160rpx;
-  max-height: 240rpx;
+  width: 240rpx;
+  height: 240rpx;
   z-index: 10001;
 }
 
 .ip-main {
-  min-width: 140rpx;
-  max-width: 220rpx;
-  min-height: 160rpx;
-  max-height: 240rpx;
+  width: 240rpx;
+  height: 240rpx;
 }
 
 .ip-btn {