Browse Source

新增背景渐变填充功能

pipipi-pikachu 5 years atrás
parent
commit
d06c1068b1

+ 12 - 1
src/hooks/useSlideBackgroundStyle.ts

@@ -10,6 +10,9 @@ export default (background: Ref<SlideBackground | undefined>) => {
       color,
       image,
       imageSize,
+      gradientColor,
+      gradientRotate,
+      gradientType,
     } = background.value
 
     if(type === 'solid') return { backgroundColor: color }
@@ -25,9 +28,17 @@ export default (background: Ref<SlideBackground | undefined>) => {
       return {
         backgroundImage: `url(${image}`,
         backgroundRepeat: 'no-repeat',
-        backgroundSize: imageSize,
+        backgroundSize: imageSize || 'cover',
       }
     }
+    else if(type === 'gradient') {
+      const rotate = gradientRotate || 0
+      const color1 = gradientColor ? gradientColor[0] : '#fff'
+      const color2 = gradientColor ? gradientColor[1] : '#fff'
+      
+      if(gradientType === 'radial') return { backgroundImage: `radial-gradient(${color1}, ${color2}` }
+      return { backgroundImage: `linear-gradient(${rotate}deg, ${color1}, ${color2}` }
+    }
 
     return { backgroundColor: '#fff' }
   })

+ 5 - 2
src/types/slides.ts

@@ -73,7 +73,7 @@ export interface PPTImageElement {
 }
 
 export interface ShapeGradient {
-  type: 'line' | 'radial';
+  type: 'linear' | 'radial';
   color: [string, string];
   rotate: number;
 }
@@ -167,10 +167,13 @@ export interface PPTAnimation {
 }
 
 export interface SlideBackground {
-  type: 'solid' | 'image';
+  type: 'solid' | 'image' | 'gradient';
   color?: string;
   image?: string;
   imageSize?: 'cover' | 'contain' | 'repeat' | 'initial';
+  gradientType?: 'linear' | 'radial';
+  gradientColor?: [string, string];
+  gradientRotate?: number;
 }
 
 export interface Slide {

+ 3 - 3
src/views/Editor/Toolbar/ElementStylePanel/ShapeStylePanel.vue

@@ -25,7 +25,7 @@
         @change="value => updateGradient({ type: value })"
         v-else
       >
-        <SelectOption value="line">线性渐变</SelectOption>
+        <SelectOption value="linear">线性渐变</SelectOption>
         <SelectOption value="radial">径向渐变</SelectOption>
       </Select>
     </div>
@@ -55,7 +55,7 @@
           <ColorButton :color="gradient.color[1]" style="flex: 3;" />
         </Popover>
       </div>
-      <div class="row" v-if="gradient.type === 'line'">
+      <div class="row" v-if="gradient.type === 'linear'">
         <div style="flex: 2;">渐变角度:</div>
         <Slider
           :min="0"
@@ -109,7 +109,7 @@ export default defineComponent({
       if(!handleElement.value) return
       fill.value = handleElement.value.fill || '#000'
 
-      gradient.value = handleElement.value.gradient || { type: 'line', rotate: 0, color: [fill.value, '#fff'] }
+      gradient.value = handleElement.value.gradient || { type: 'linear', rotate: 0, color: [fill.value, '#fff'] }
 
       fillType.value = handleElement.value.gradient ? 'gradient' : 'fill'
     }, { deep: true, immediate: true })

+ 66 - 3
src/views/Editor/Toolbar/SlideStylePanel.vue

@@ -9,8 +9,10 @@
       >
         <SelectOption value="solid">纯色填充</SelectOption>
         <SelectOption value="image">图片填充</SelectOption>
+        <SelectOption value="gradient">渐变填充</SelectOption>
       </Select>
       <div style="flex: 1;"></div>
+
       <Popover trigger="click" v-if="background.type === 'solid'">
         <template #content>
           <ColorPicker
@@ -20,18 +22,30 @@
         </template>
         <ColorButton :color="background.color || '#fff'" style="flex: 10;" />
       </Popover>
+
       <Select 
         style="flex: 10;" 
         :value="background.size || 'cover'" 
         @change="value => updateBackground({ imageSize: value })"
-        v-else
+        v-else-if="background.type === 'image'"
       >
         <SelectOption value="initial">原始大小</SelectOption>
         <SelectOption value="contain">缩放</SelectOption>
         <SelectOption value="repeat">拼贴</SelectOption>
         <SelectOption value="cover">缩放铺满</SelectOption>
       </Select>
+
+      <Select 
+        style="flex: 10;" 
+        :value="background.gradientType" 
+        @change="value => updateBackground({ gradientType: value })"
+        v-else
+      >
+        <SelectOption value="linear">线性渐变</SelectOption>
+        <SelectOption value="radial">径向渐变</SelectOption>
+      </Select>
     </div>
+
     <div class="background-image-wrapper" v-if="background.type === 'image'">
       <FileInput @change="files => uploadBackgroundImage(files)">
         <div class="background-image">
@@ -41,6 +55,45 @@
         </div>
       </FileInput>
     </div>
+
+    <div class="background-gradient-wrapper" v-if="background.type === 'gradient'">
+      <div class="row">
+        <div style="flex: 2;">起点颜色:</div>
+        <Popover trigger="click">
+          <template #content>
+            <ColorPicker
+              :modelValue="background.gradientColor[0]"
+              @update:modelValue="value => updateBackground({ gradientColor: [value, background.gradientColor[1]] })"
+            />
+          </template>
+          <ColorButton :color="background.gradientColor[0]" style="flex: 3;" />
+        </Popover>
+      </div>
+      <div class="row">
+        <div style="flex: 2;">终点颜色:</div>
+        <Popover trigger="click">
+          <template #content>
+            <ColorPicker
+              :modelValue="background.gradientColor[1]"
+              @update:modelValue="value => updateBackground({ gradientColor: [background.gradientColor[0], value] })"
+            />
+          </template>
+          <ColorButton :color="background.gradientColor[1]" style="flex: 3;" />
+        </Popover>
+      </div>
+      <div class="row" v-if="background.gradientType === 'linear'">
+        <div style="flex: 2;">渐变角度:</div>
+        <Slider
+          :min="0"
+          :max="360"
+          :step="15"
+          :value="background.gradientRotate"
+          style="flex: 3;"
+          @change="value => updateBackground({ gradientRotate: value })" 
+        />
+      </div>
+    </div>
+
     <div class="row"><Button style="flex: 1;" @click="applyAllSlide()">应用到全部</Button></div>
   </div>
 </template>
@@ -77,7 +130,7 @@ export default defineComponent({
 
     const { addHistorySnapshot } = useHistorySnapshot()
 
-    const updateBackgroundType = (type: 'solid' | 'image') => {
+    const updateBackgroundType = (type: 'solid' | 'image' | 'gradient') => {
       if(type === 'solid') {
         const newBackground: SlideBackground = {
           ...background.value,
@@ -86,7 +139,7 @@ export default defineComponent({
         }
         store.commit(MutationTypes.UPDATE_SLIDE, { background: newBackground })
       }
-      else {
+      else if(type === 'image') {
         const newBackground: SlideBackground = {
           ...background.value,
           type: 'image',
@@ -95,6 +148,16 @@ export default defineComponent({
         }
         store.commit(MutationTypes.UPDATE_SLIDE, { background: newBackground })
       }
+      else {
+        const newBackground: SlideBackground = {
+          ...background.value,
+          type: 'gradient',
+          gradientType: background.value.gradientType || 'linear',
+          gradientColor: background.value.gradientColor || ['#fff', '#fff'],
+          gradientRotate: background.value.gradientRotate || 0,
+        }
+        store.commit(MutationTypes.UPDATE_SLIDE, { background: newBackground })
+      }
       addHistorySnapshot()
     }
 

+ 2 - 2
src/views/components/element/ShapeElement/GradientDefs.vue

@@ -1,6 +1,6 @@
 <template>
   <linearGradient 
-    v-if="type === 'line'"
+    v-if="type === 'linear'"
     :id="id" 
     x1="0%" 
     y1="0%" 
@@ -29,7 +29,7 @@ export default defineComponent({
       required: true,
     },
     type: {
-      type: String as PropType<'line' | 'radial'>,
+      type: String as PropType<'linear' | 'radial'>,
     },
     color1: {
       type: String,