Ver Fonte

修复iOS低版本无法打开的bug, 优化尺寸编辑UI

lianghongjie há 1 ano atrás
pai
commit
2877e3c40d

+ 1 - 0
.browserslistrc

@@ -2,3 +2,4 @@
 last 2 versions
 not dead
 not ie 11
+ios >= 9

+ 3 - 0
src/assets/icons/components/IconRelate.tsx

@@ -0,0 +1,3 @@
+
+import { createIcon } from '@queenjs/icons';
+export const IconRelate = createIcon(<svg viewBox="0 0 22 22"><g transform="translate(-2783 -4497)"><rect fill="none" width="22" height="22" transform="translate(2783 4497)"/><g transform="translate(2800.435 4511.481) rotate(180)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" d="M-189.919,68.962h-2.6A3.491,3.491,0,0,1-196,65.481h0A3.491,3.491,0,0,1-192.519,62h2.6" transform="translate(194 -62)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" d="M-196,68.962h2.6a3.491,3.491,0,0,0,3.481-3.481h0A3.491,3.491,0,0,0-193.4,62H-196" transform="translate(204.354 -62)"/></g></g></svg>)

+ 1 - 0
src/assets/icons/index.ts

@@ -38,6 +38,7 @@ export * from "./components/IconPlay2";
 export * from "./components/IconPreview";
 export * from "./components/IconProfile";
 export * from "./components/IconQueen";
+export * from "./components/IconRelate";
 export * from "./components/IconResizeY";
 export * from "./components/IconRight";
 export * from "./components/IconRotate";

+ 1 - 0
src/assets/icons/svg/relate.svg

@@ -0,0 +1 @@
+<svg viewBox="0 0 22 22"><g transform="translate(-2783 -4497)"><rect fill="none" width="22" height="22" transform="translate(2783 4497)"/><g transform="translate(2800.435 4511.481) rotate(180)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" d="M-189.919,68.962h-2.6A3.491,3.491,0,0,1-196,65.481h0A3.491,3.491,0,0,1-192.519,62h2.6" transform="translate(194 -62)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" d="M-196,68.962h2.6a3.491,3.491,0,0,0,3.481-3.481h0A3.491,3.491,0,0,0-193.4,62H-196" transform="translate(204.354 -62)"/></g></g></svg>

+ 1 - 5
src/modules/editor/components/CompUI/defines/createAttrsForm.tsx

@@ -7,16 +7,12 @@ import { Size } from "../formItems/Size";
 import Slider from "../formItems/Slider";
 import { createColorOpts } from "./formOpts/createColorOpts";
 import { Divider } from "ant-design-vue";
-import { GroupNumber } from "../formItems/GroupNumber";
 
 export const layoutColumns: ColumnItem[] = [
   {
-    // label: "尺寸",
+    label: "尺寸",
     dataIndex: "layout.size",
     component: Size,
-    props: {
-      labels: ["宽度", "高度"],
-    },
   },
   // {
   //   label: "对齐",

+ 129 - 55
src/modules/editor/components/CompUI/formItems/Size.tsx

@@ -1,92 +1,166 @@
+import { IconHeight, IconWidth } from "@/assets/icons";
 import { CompSizeOpts } from "@/modules/editor/objects/DesignTemp/creates/CompSize";
+import { Layout } from "@/modules/editor/typings";
+import { css } from "@linaria/core";
 import { InputNumber, Select } from "ant-design-vue";
-import { defineComponent } from "vue";
+import { AnyFun } from "queenjs/typing";
+import { defineComponent, reactive } from "vue";
 import { any } from "vue-types";
+import { TipIcons } from "../../TipIcons";
 
 const selectOptions = [
-  { value: "px", label: "像素", options: { step: 1 } },
-  { value: "%", label: "比例", options: { step: 0.1, max: 100, min: 0 } },
+  { value: "px", label: "PX", options: { step: 1 } },
+  { value: "%", label: "%", options: { step: 0.1 } },
 ];
 
 export const Size = defineComponent({
   props: {
-    value: any<[number, number, string?, string?]>().def([0, 0]),
+    value: any<Layout["size"]>().def([0, 0]),
   },
   emits: ["change"],
   setup(props, { emit }) {
     const CompSizeOptsList = [CompSizeOpts.w, CompSizeOpts.h];
+    const state = reactive({
+      relateRatio: 0,
+    });
 
-    function changeVal(unit: any, index: number, v: any) {
+    function changeVal(index: number, v: any) {
       const { value } = props;
+      const unit = value[2]?.unit;
       value[index] = parseFloat(v) || 0;
+
       if (unit === "%") {
         value[index] = CompSizeOptsList[index].getPxSize(
           value[index] as number
         );
       }
+
+      if (state.relateRatio) {
+        const isChangeW = index === 0;
+        if (isChangeW) {
+          value[1] = value[0] / state.relateRatio;
+        } else {
+          value[0] = value[1] * state.relateRatio;
+        }
+      }
+
       emit("change", value);
     }
 
-    function changeUnit(index: number, unit: any) {
+    function changeUnit(unit: any) {
       const { value } = props;
-      value[index + 2] = unit;
+      if (!value[2]?.unit) {
+        value[2] = { unit };
+      } else {
+        value[2].unit = unit;
+      }
       emit("change", value);
     }
 
-    function fmtVal(val: number, unit: string, index: number) {
+    function changeRelate() {
+      state.relateRatio = !state.relateRatio
+        ? props.value[0] / props.value[1]
+        : 0;
+    }
+
+    function fmtVal(index: number) {
+      const unit = props.value[2]?.unit;
+      const val = props.value[index] as number;
       switch (unit) {
-        case "px":
-          return val.toFixed(0);
         case "%":
-          return CompSizeOptsList[index].getVSize(val).toFixed(1);
+          return CompSizeOptsList[index].getVSize(val).toFixed(0);
         default:
-          return "";
+          return val.toFixed(0);
       }
     }
 
-    return () => {
-      const values = props.value.slice(0, 2) as number[];
-      const units = props.value.slice(2) as string[];
-
-      return (
-        <div class="flex space-x-10px">
-          {values.map((value, i) => {
-            const unit = units[i] || selectOptions[0].value;
-            const inputOpts =
-              selectOptions.find((d) => d.value === unit)?.options || {};
-            return (
-              <InputNumber
-                key={i + unit}
-                value={fmtVal(value as number, unit, i)}
-                onChange={changeVal.bind(null, unit, i)}
-                {...inputOpts}
-              >
-                {{
-                  addonBefore() {
-                    return (
-                      <span class="-mx-8px">
-                        {CompSizeOptsList[i].label}
-                        <Select
-                          value={unit}
-                          onChange={changeUnit.bind(null, i)}
-                        >
-                          {selectOptions.map((d) => {
-                            return (
-                              <Select.Option key={d.value}>
-                                {d.value === "%" ? CompSizeOptsList[i].vUnit : d.value}
-                              </Select.Option>
-                            );
-                          })}
-                        </Select>
-                      </span>
-                    );
-                  },
-                }}
-              </InputNumber>
-            );
-          })}
+    return () => (
+      <div class="space-y-10px flex-1">
+        <div class="flex justify-between">
+          <SizeInput
+            label="X"
+            icon={IconWidth}
+            value={fmtVal(0)}
+            onChange={(v) => changeVal(0, v)}
+          />
+          <TipIcons.Relate
+            class={[relateIconCls, state.relateRatio && "active"]}
+            onClick={changeRelate}
+          />
         </div>
-      );
-    };
+        <div class="flex justify-between">
+          <SizeInput
+            label="Y"
+            icon={IconHeight}
+            value={fmtVal(1)}
+            onChange={(v) => changeVal(1, v)}
+          />
+          <Select
+            class={selUnitCls}
+            bordered={false}
+            value={props.value[2]?.unit || selectOptions[0].value}
+            onChange={(v) => changeUnit(v)}
+          >
+            {selectOptions.map((d) => {
+              return <Select.Option key={d.value}>{d.label}</Select.Option>;
+            })}
+          </Select>
+        </div>
+      </div>
+    );
   },
 });
+
+const SizeInput = (props: {
+  label: string;
+  icon: any;
+  value: string;
+  onChange: AnyFun;
+}) => {
+  const { label, icon, ...inputProps } = props;
+  return (
+    <div class={numberInputCls}>
+      <span class="pl-14px pr-1px text-14px">{label}</span>
+      <InputNumber class="flex-1" bordered={false} {...inputProps} />
+      <icon class="tipIcon" />
+    </div>
+  );
+};
+
+const numberInputCls = css`
+  @apply inline-flex items-center flex-1 w-0 mr-12px;
+  background-color: #303030;
+  border-radius: 4px;
+  overflow: hidden;
+
+  .tipIcon {
+    font-size: 24px;
+    padding: 3px 5px;
+    background-color: #373737;
+  }
+`;
+
+const relateIconCls = css`
+  padding: 3px 17px;
+  font-size: 24px;
+  border-radius: 4px;
+  background-color: #303030;
+  cursor: pointer;
+
+  &.active {
+    background-color: rgba(234, 158, 64, 0.2);
+    color: #ea9e40;
+  }
+`;
+
+const selUnitCls = css`
+  width: 58px;
+  height: 30px;
+  border-radius: 4px;
+  background-color: #303030;
+  cursor: pointer;
+
+  .ant-select-selector {
+    padding: 0 8px;
+  }
+`;

+ 7 - 5
src/modules/editor/components/TipIcons/index.ts

@@ -26,6 +26,7 @@ import {
   IconWidth,
   IconHeight,
   IconDelete,
+  IconRelate,
 } from "@/assets/icons";
 import {
   IconCamera,
@@ -41,9 +42,6 @@ import {
 import { createTipIcon } from "./create";
 import { FontSize } from "./TipIcon";
 
-
-
-
 export const TipIcons = {
   Rename: createTipIcon({
     icons: [IconEdit],
@@ -69,7 +67,7 @@ export const TipIcons = {
     icons: [IconEdit],
     tips: ["编辑"],
   }),
-  
+
   Position: createTipIcon({
     icons: [IconFloatOff, IconFloatOn],
     tips: ["开启浮动", "关闭浮动"],
@@ -143,7 +141,7 @@ export const TipIcons = {
     tips: ["裁剪"],
   }),
   AlignXLeft: createTipIcon({
-    icons: [FontSize(IconAlignXLeft,28)],
+    icons: [FontSize(IconAlignXLeft, 28)],
     tips: ["左对齐"],
   }),
   AlignXCenter: createTipIcon({
@@ -182,4 +180,8 @@ export const TipIcons = {
     icons: [FontSize(IconHeight, 28)],
     tips: ["相同高度"],
   }),
+  Relate: createTipIcon({
+    icons: [IconRelate],
+    tips: ["锁定宽高比"],
+  }),
 };

+ 0 - 2
src/modules/editor/components/index.ts

@@ -1,9 +1,7 @@
 import Preview from "./Preview";
-import Viewport from "./Viewport";
 import CompSave from "./CompSave";
 
 export default {
-  Viewport,
   Preview,
   CompSave,
 };

+ 2 - 2
src/modules/editor/objects/DesignTemp/creates/createCompStyle.ts

@@ -78,12 +78,12 @@ export function createCompStyle(
   }
 
   if (layout.size) {
-    const [w, h, wUnit, hUnit] = layout.size;
+    const [w, h, sizeOpts] = layout.size;
     if (w) {
       style.width = designToNaturalSize(w);
     }
     if (h) {
-      style.height = designToNaturalSize(h, { adaptiveH: hUnit === "%" });
+      style.height = designToNaturalSize(h, { adaptiveH: sizeOpts?.unit === "%" });
     }
   }
 

+ 3 - 2
src/modules/editor/typings.ts

@@ -2,12 +2,13 @@ import { CompUI } from "./components/CompUI";
 
 export type ICompKeys = keyof typeof CompUI;
 
-export type EditorMode = "editPage" | "editComp" | "preview" | "display"
+export type EditorMode = "editPage" | "editComp" | "preview" | "display";
 
 export type Layout = {
   position?: "absolute";
   visible?: boolean;
-  size: [number, number, string?, string?]; // width height wUnit hUnit
+  size: [number, number, { unit?: "px" | "%" }?]; // width height wUnit hUnit
+  direction?: "top" | "bottom"; // 默认top
   mask?: string;
   alignSelf?: string;
   transform?: {

+ 2 - 1
src/pages/editor/EditPage/index.tsx

@@ -1,4 +1,5 @@
 import { initEditor } from "@/modules/editor";
+import Viewport from "@/modules/editor/components/Viewport";
 import { EditorMode } from "@/modules/editor/typings";
 import { useResource } from "@/modules/resource";
 import { SelectOneImage } from "@/pages/website/Material2/modal";
@@ -41,5 +42,5 @@ export default defineComponent(() => {
     return resource.treeController.selectOnePackScene();
   };
 
-  return () => <editor.components.Viewport class="!h-100vh" />;
+  return () => <Viewport class="!h-100vh" />;
 });