Browse Source

feat: support canvas scaling

Casper Dai 3 years ago
parent
commit
cb230c0dd3

BIN
src/assets/dot.png


+ 17 - 12
src/views/bigscreen/core/base.js

@@ -27,7 +27,9 @@ export default {
       program: null,
       snapping: false,
       loading: true,
-      scale: 1,
+      scale: 100,
+      minScale: 100,
+      maxScale: 100,
       selectedWidgetIndex: -1,
       node: null,
       bgm: '',
@@ -37,7 +39,7 @@ export default {
   computed: {
     transformStyles () {
       return {
-        transform: `scale(${this.scale})`,
+        transform: `scale(${this.scale / 100})`,
         'transform-origin': '0 0'
       }
     },
@@ -47,7 +49,7 @@ export default {
         return {
           width: `${width}px`,
           height: `${height}px`,
-          'background-color': backgroundColor,
+          color: backgroundColor,
           'background-image': backgroundImage[0] ? `url("${getThumbnailUrl(backgroundImage[0].keyName)}")` : 'none'
         }
       }
@@ -150,16 +152,19 @@ export default {
         const width = wrapper.offsetWidth
         const height = wrapper.offsetHeight
         const { width: cWidth, height: cHeight } = this.node
+        const wScale = width / cWidth
+        const hScale = height / cHeight
         if (cWidth > width || cHeight > height) {
-          const wScale = width / cWidth
-          const hScale = height / cHeight
-          this.scale = Math.min(wScale, hScale)
-          console.log('wScale vs hScale', wScale, hScale)
+          this.scale = Math.min(wScale, hScale) * 100 | 0
+          this.maxScale = Math.max(1, wScale, hScale) * 100 | 0
         } else {
-          this.scale = 1
+          this.scale = 100
+          this.maxScale = Math.max(2, wScale, hScale) * 100 | 0
         }
-        console.log('width: layout -> window', cWidth, '->', width)
-        console.log('height: layout -> window', cHeight, '->', height)
+        this.minScale = this.scale
+        console.log('width: layout -> window', cWidth, '->', width, wScale)
+        console.log('height: layout -> window', cHeight, '->', height, hScale)
+        console.log(this.scale, this.maxScale)
       }
     },
     showMessage (type, message) {
@@ -289,8 +294,8 @@ export default {
           }
           return tagName !== 'VIDEO' && tagName !== 'IFRAME'
         },
-        width: this.node.width * this.scale | 0,
-        height: this.node.height * this.scale | 0,
+        width: this.node.width * this.scale / 100 | 0,
+        height: this.node.height * this.scale / 100 | 0,
         quality: 0.1
       }).finally(() => {
         this.snapping = false

+ 6 - 6
src/views/bigscreen/core/components/Draggable.vue

@@ -468,7 +468,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-$active: rgba(115, 170, 229, .5);
+$active: rgba(115, 170, 229, 0.5);
 $border: #0099ff;
 
 .c-draggable {
@@ -497,7 +497,7 @@ $border: #0099ff;
   }
 
   &--move {
-    opacity: .6;
+    opacity: 0.6;
     background-color: $active;
   }
 
@@ -532,7 +532,7 @@ $border: #0099ff;
       color: $border;
       font-size: 18px;
       white-space: nowrap;
-      transform: translate(-100%,-100%);
+      transform: translate(-100%, -100%);
       cursor: move;
     }
   }
@@ -547,9 +547,9 @@ $border: #0099ff;
 
     &--left,
     &--right {
-      top:50%;
+      top: 50%;
 
-      &:hover{
+      &:hover {
         cursor: ew-resize;
       }
     }
@@ -568,7 +568,7 @@ $border: #0099ff;
     &--bottom {
       left: 50%;
 
-      &:hover{
+      &:hover {
         cursor: ns-resize;
       }
     }

+ 1 - 1
src/views/bigscreen/core/utils.js

@@ -19,7 +19,7 @@ export const widgets = Object.freeze([
   widgetLive
 ])
 
-let scale = 1
+let scale = null
 export function create (node) {
   const canvasDefaults = widgetCanvas.defaults()
   const canvas = {

+ 114 - 5
src/views/bigscreen/designer/index.vue

@@ -103,6 +103,46 @@
             @click="clear"
           />
         </el-tooltip>
+        <el-tooltip
+          class="c-designer__btn"
+          content="缩放"
+          :hide-after="2000"
+        >
+          <div
+            class="o-scale-slider"
+            @click="toScale"
+          >
+            <div
+              class="l-flex--row o-scale-slider__wrapper"
+              :class="{ expand: dragScale }"
+            >
+              <i
+                class="el-icon-zoom-out"
+                @click="scaleDown"
+              />
+              <el-slider
+                v-model="scale"
+                class="o-scale-slider__slider"
+                :min="minScale"
+                :max="maxScale"
+                @change="toScale"
+              />
+              <i
+                class="el-icon-zoom-in"
+                @click="scaleUp"
+              />
+            </div>
+            <svg-icon
+              v-if="dragScale"
+              icon-class="exit-fullscreen"
+              @click.stop="hideScale"
+            />
+            <svg-icon
+              v-else
+              icon-class="fullscreen"
+            />
+          </div>
+        </el-tooltip>
         <el-tooltip
           v-if="hasAudio"
           class="c-designer__btn"
@@ -133,12 +173,13 @@
         </el-tooltip>
       </div>
       <div
-        class="l-flex--col c-designer__content"
+        class="c-designer__content"
         @mousedown="onScreenClick"
       >
         <div
           ref="wrapper"
-          class="l-flex__fill"
+          class="c-designer__wrapper"
+          :style="wrapperStyles"
         >
           <div
             ref="canvas"
@@ -156,7 +197,7 @@
               v-for="(item, index) in widgets"
               :key="item.id"
               ref="widgets"
-              :scale="1 / scale"
+              :scale="100 / scale"
               :node="item"
               :root="node"
               @focus="onWidgetFocus(index)"
@@ -387,7 +428,8 @@ export default {
       sources: null,
       dialogServerData: false,
       assetOptions: createListOptions(),
-      dragging: false
+      dragging: false,
+      dragScale: false
     }
   },
   computed: {
@@ -424,6 +466,12 @@ export default {
     },
     selectedWidgetId () {
       return this.widget.id
+    },
+    wrapperStyles () {
+      return this.node ? {
+        width: `${this.node.width * this.scale / 100}px`,
+        height: `${this.node.height * this.scale / 100}px`
+      } : null
     }
   },
   watch: {
@@ -681,6 +729,18 @@ export default {
     },
     onSourceDragEnd () {
       this.dragging = false
+    },
+    toScale () {
+      this.dragScale = true
+    },
+    hideScale () {
+      this.dragScale = false
+    },
+    scaleDown () {
+      this.scale = Math.max(this.scale - 10, this.minScale)
+    },
+    scaleUp () {
+      this.scale = Math.min(this.scale + 10, this.maxScale)
     }
   }
 }
@@ -715,7 +775,8 @@ $drak: #242a30;
     flex: 1 0 0;
     position: relative;
     padding: 10px;
-    overflow: hidden;
+    overflow: auto;
+    background: url("~@/assets/dot.png") repeat;
   }
 
   &__tool {
@@ -760,9 +821,26 @@ $drak: #242a30;
     }
   }
 
+  &__wrapper {
+    min-width: 100%;
+    min-height: 100%;
+  }
+
   &__canvas {
     position: relative;
     overflow: visible;
+    background-color: #000;
+
+    &::after {
+      content: "";
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      background-color: currentColor;
+      z-index: -1;
+    }
 
     &.dragging::after {
       content: "";
@@ -950,4 +1028,35 @@ $drak: #242a30;
   background-size: contain;
   background-repeat: no-repeat;
 }
+
+.o-scale-slider {
+  justify-content: flex-start;
+  min-width: 48px;
+  width: auto;
+  padding: 0 $spacing;
+  font-size: 20px;
+
+  &__wrapper {
+    width: 0;
+    transition: width 0.1s;
+    overflow: hidden;
+
+    &.expand {
+      width: 184px;
+    }
+  }
+
+  &__slider {
+    width: 100px;
+    margin: 0 16px;
+  }
+
+  .el-icon-zoom-in + .svg-icon {
+    margin-left: 16px;
+  }
+
+  .svg-icon {
+    font-size: 16px;
+  }
+}
 </style>

+ 13 - 2
src/views/bigscreen/viewer/index.vue

@@ -175,6 +175,17 @@ export default {
   &__canvas {
     position: relative;
     overflow: hidden;
+
+    &::after {
+      content: "";
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      background-color: currentColor;
+      z-index: -1;
+    }
   }
 }
 
@@ -206,7 +217,7 @@ export default {
 .c-card {
   display: inline-block;
   position: relative;
-  background-color: rgba(0, 0, 0, .8);
+  background-color: rgba(0, 0, 0, 0.8);
 
   &__content {
     position: relative;
@@ -222,7 +233,7 @@ export default {
     color: $gray;
     font-size: 14px;
     text-align: center;
-    background-color: rgba(0, 0, 0, .6);
+    background-color: rgba(0, 0, 0, 0.6);
   }
 
   &__text {