LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

使用 fabric.js 開發(fā)移動(dòng)端 H5 圖片編輯器

freeflydom
2024年12月10日 9:3 本文熱度 743

大家好,我是開源圖片編輯器的 https://github.com/ikuaitu/vue-fabric-editor 的作者,它是一款基于 PC 版本的開源圖片編輯器。

最近很多開發(fā)者咨詢,是否可以將開源圖片編輯器改造為一款適用于移動(dòng)端的 H5 版本圖片編輯器,最近 H5 版本的圖片編輯器剛剛上線,就將實(shí)現(xiàn)思路和產(chǎn)品細(xì)節(jié)整理成筆記分享出來,供大家參考。

基礎(chǔ)

開源的圖片編輯器的基本功能都有了,例如切換模板、添加元素、自定義字體等,不過相較于移動(dòng)端的交互會(huì)有很大的差異,做了很多改造,這次筆記主要分享一下移動(dòng)端圖片編輯器實(shí)現(xiàn)思路和細(xì)節(jié)


大綱

  1. 切換模板
  2. 添加圖片
  3. 添加組合元素
  4. 設(shè)置背景色
  5. 修改畫布尺寸
  6. 快捷菜單
  7. 屬性工具條
  8. 特效字體
  9. 切換字體
  10. 輸入文字
  11. 文字排版
  12. 邊框
  13. 陰影
  14. 下載圖片

注:部分代碼示例為封裝后的代碼,非 fabric.js 原生方法。

1. 切換模板

編輯器基于 fabric.js 開發(fā),所有的模板都是以 json 的格式存儲(chǔ),切換模板只需要請求詳情接口,將 json 格式的數(shù)據(jù)調(diào)添加到畫布當(dāng)中即可,需要注意的點(diǎn)是需要將模板中使用的字體名稱,并加載字體文件后再進(jìn)行渲染,否則字體樣式?jīng)]辦法正常渲染。

const loadInfo = async (res: any) => {
  const info = res.data
  templName.value = info.name;
  await canvasEditor.getFontList(JSON.stringify(info.json));
  canvasEditor.loadJSON(JSON.stringify(info.json), () => LoadingPlugin(false));
};

2. 添加圖片

fabric.js 中添加圖片提供了很多種方法,我們使用通過最簡單的fabric.Image.fromURL即可,另外,經(jīng)常有圖片尺寸大于畫布的情況,還需要將圖片按畫布寬度的一般進(jìn)行縮放,更方便用戶操作。

const toEditor = async (e: MouseEvent) => {
  visible.value = false
  LoadingPlugin(true)
  const item = await canvasEditor.createImgByElement(e.target as HTMLImageElement)
  await canvasEditor.addBaseType(item, { scale: true })
  LoadingPlugin(false)
}

3. 添加組合元素

fabric.js 支持將單個(gè)元素按照 JSON 格式導(dǎo)出/導(dǎo)入,我們將導(dǎo)出的數(shù)據(jù)存儲(chǔ)在數(shù)據(jù)庫中的,導(dǎo)入時(shí)按元素類型導(dǎo)入即可,需要獲取 JSON 中元素的類型,并作為方法名調(diào)用,同樣需要在導(dǎo)入前做字體加載,倒入后做縮放。

const capitalizeFirstLetter = (str: string) => {
  return str.charAt(0).toUpperCase() + str.slice(1);
}
const toEditor = async (item: ItemProps) => {
  visible.value = false
  LoadingPlugin(true)
  await canvasEditor.downFontByJSON(JSON.stringify(item.json));
  const el = JSON.parse(JSON.stringify(item.json));
  const elType = capitalizeFirstLetter(el.type);
  new fabric[elType].fromObject(el, (fabricEl: fabric.Object) => {
    canvasEditor.dragAddItem(fabricEl);
    LoadingPlugin(false)
  });
}

4. 設(shè)置背景色

設(shè)置背景色較為簡單,按照 fabric.js 的 API 設(shè)置顏色即可,需要注意的是大部分 PC 端的顏色組件并不適配移動(dòng)端 H5 的場景,不支持 touch 事件,我們使用了 @jaames/iro這個(gè)組件,它在移動(dòng)端表現(xiàn)出色,完全適配我們的場景,而且它的 API 很靈活,我們將它封裝成一個(gè)通用的顏色組件,在多處調(diào)用。

<template>
  <div ref="pickerContainer">
  </div>
</template>
<script setup lang="ts">
import iro from '@jaames/iro';
const emit = defineEmits(['update:modelValue', 'change']);
const props = defineProps({
  modelValue: {
    type: String,
    default: '#000000'
  },
  width: {
    type: Number,
    default: 200
  }
});
const pickerContainer = ref<HTMLButtonElement | string>('');
let colorPicker: any = null;
onMounted(() => {
  // 創(chuàng)建iro.js顏色選擇器
  colorPicker = iro.ColorPicker(pickerContainer.value, {
    width: props.width,
    color: props.modelValue,
    borderWidth: 1,
    borderColor: "#fff",
    layoutDirection: 'horizontal',
    layout: [
      {
        component: iro.ui.Slider,
        options: {
          id: 'hue-slider',
          sliderType: 'hue'
        }
      },
      {
        component: iro.ui.Box,
      },
      {
        component: iro.ui.Slider,
        options: {
          sliderType: 'alpha'
        }
      }
    ]
  });
  // 監(jiān)聽顏色變化事件并發(fā)射自定義事件
  colorPicker.on('color:change', (color: any) => {
    const rgbaString = color.rgbaString;
    emit('update:modelValue', rgbaString);
    emit('change', rgbaString);
  });
});
</script>

5. 修改畫布尺寸

日常使用圖片編輯器都有修改畫布尺寸的需要,在開源項(xiàng)目中已經(jīng)封裝好了相應(yīng)的方法,直接調(diào)用即可,需要注意的是,當(dāng)修改尺寸彈框彈出時(shí),為了達(dá)到所見即所得的效果,要避免彈框遮擋畫布,其他屬性修改同理。


const resizeEditor = async () => {
    await nextTick()
    const editorWorkspase = document.querySelector('#workspace') as HTMLElement
    const popElement = document.querySelector('.my-editor-popup') as HTMLElement
    const headerElement = document.querySelector('.t-navbar') as HTMLElement
    if (popElement) {
      editorWorkspase.style.height = `calc(100vh - ${popElement?.offsetHeight + headerElement?.offsetHeight || 0}px)`
    } else {
      editorWorkspase.style.height = ''
    }
  }

6. 快捷菜單

很多快捷操作需要能夠讓用戶快速找的并完成操作,我們?yōu)樵靥砑恿丝旖莶藛喂δ埽苊庾屢恍┖唵蔚牟僮髯層脩粼诘撞坎藛螜邳c(diǎn)來點(diǎn)去,當(dāng)選中元素時(shí)自動(dòng)展示,取消選中時(shí)隱藏即可,需要注意的是在快捷菜單并不總是在元素上方,快捷菜單應(yīng)該根據(jù)元素位置和畫布的尺寸進(jìn)行定位,當(dāng)菜單超出畫布區(qū)域時(shí)我們要及時(shí)調(diào)整菜單位置;另外 當(dāng)屬性彈框出現(xiàn),畫布尺寸變化時(shí),需要同步修改菜單位置。

// 更新位置信息
const upDatePosition = async () => {
  const activeObject = canvasEditor.canvas.getActiveObject();
  if (activeObject) {
    canvasEditor.canvas.renderAll();
    fixLeft.value = 10;
    fixTop.value = 10;
    await nextTick();
    isIncluded(activeObject);
    await nextTick();
  }
}
// 監(jiān)聽選中對象變化更新位置信息
getObjectAttr(upDatePosition)
canvasEditor.canvas.on('selection:updated', upDatePosition)
canvasEditor.canvas.on('mouse:move', upDatePosition)
canvasEditor.on('workspaceAutoEvent', upDatePosition)

7. 屬性工具條

參考了其他圖片編輯器,部分屬性在點(diǎn)擊元素后才會(huì)出現(xiàn)可修改選項(xiàng),取消選中時(shí)便隱藏選項(xiàng),另外 選中的元素不同,可修改選項(xiàng)也不同,這是一個(gè)在移動(dòng)端做復(fù)雜圖片編輯器中非常棒的一個(gè)交互。

我們封裝了通用的選中類型和方法,針對每個(gè)屬性組件單獨(dú)設(shè)置隱藏/展示。

8. 特效字體

特效字體主要是文字元素的顏色、邊框、陰影的組合,我們將來文字設(shè)置樣式后的 JSON 導(dǎo)出并保存在數(shù)據(jù)庫中,當(dāng)選中某一個(gè)特效時(shí),將屬性按 JSON 中的數(shù)據(jù)設(shè)置給元素即可。

const setStyle = (item: ImgItem) => {
  const activeObject = canvasEditor.canvas.getActiveObjects()[0];
  if (activeObject) {
    const values = toRaw(item.json);
    const keys = ['fill', 'stroke', 'strokeWidth', 'shadow', 'strokeLineCap'];
    activeObject.set('paintFirst', 'stroke');
    keys.forEach((key) => {
      activeObject.set(key, values[key]);
      if (key === 'fill' && typeof values[key] != 'string') {
        activeObject.set(key, new fabric.Gradient(values[key]));
      }
    });
    canvasEditor.canvas.renderAll();
  }
};

9. 切換字體

修改字體只需要調(diào)用 fabric.js 元素的fontFamily屬性即可,在修改之前要確保字體加載完成。


const changeCommon = async (key: string, value: any) => {
  const activeObject = canvasEditor.canvas.getActiveObjects()[0];
  if (activeObject) {
    LoadingPlugin(true);
    baseAttr.fontFamily = value;
    try {
      await canvasEditor.loadFont(value)
    } catch (error) {
      console.log(error)
    }
    LoadingPlugin(false);
    activeObject && activeObject.set(key, value);
    canvasEditor.canvas.renderAll();
  }
};

10. 輸入文字

fabric.js 可直接雙擊文字元素進(jìn)行修改,不過在移動(dòng)端這種交互并不醒目,我們單獨(dú)為文本元素進(jìn)行了修改,選中元素后,再次點(diǎn)擊時(shí)彈出輸入框,可以在底部菜單欄點(diǎn)擊按鈕進(jìn)行修改。

11. 文字排版

文字排版較為簡單,我們只需要按照 fabric.js 的文字屬性對文字進(jìn)行屬性設(shè)置即可,如 fontSize、lineHeight、charSpacing 等。

// 屬性值
const baseAttr = reactive({
  fontSize: 0,
  lineHeight: 0,
  charSpacing: 0,
  textAlign: '',
  fontWeight: '',
  fontStyle: '',
  underline: false,
  linethrough: false,
  overline: false,
});

12. 邊框

邊框樣式和文字樣式類似,配合顏色組件可以很快捷的實(shí)現(xiàn)功能。

// 屬性值
const baseAttr = reactive({
  stroke: '#fff',
  strokeWidth: 0,
  strokeDashArray: [],
});

13. 陰影

引用屬性主要是元素的 shadow 子屬性的修改,代碼如下:

// 屬性值
const baseAttr = reactive({
  shadow: {
    color: '#fff',
    blur: 0,
    offsetX: 1,
    offsetY: 1,
  }
});
// 通用屬性改變
const changeCommon = () => {
  const activeObject = canvasEditor.canvas.getActiveObjects()[0];
  if (activeObject) {
    activeObject.set('shadow', new fabric.Shadow(baseAttr.shadow));
    canvasEditor.canvas.renderAll();
  }
};

14. 下載圖片

fabric.js 可以導(dǎo)出 Png/Jpeg/Base64 格式的圖片,同時(shí) JPEG 格式還可以指定圖片質(zhì)量與尺寸倍數(shù),詳見 fabric.js 的 API 文檔。

結(jié)尾

以上就是 fabric.js 開發(fā)移動(dòng)端編輯器的實(shí)現(xiàn)細(xì)節(jié)了,結(jié)合我們的開源項(xiàng)目和插件化架構(gòu)可以很方便的完成項(xiàng)目開發(fā),如果你在做類似項(xiàng)目或者做類似的項(xiàng)目,歡迎與我交流。

開源項(xiàng)目:https://github.com/ikuaitu/vue-fabric-editor/blob/main/README-zh.md

?轉(zhuǎn)自https://www.cnblogs.com/nihaojob/p/18426386


該文章在 2024/12/10 9:03:32 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲(chǔ)管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

黄频国产免费高清视频,久久不卡精品中文字幕一区,激情五月天AV电影在线观看,欧美国产韩国日本一区二区
亚洲人成aⅴ在线播放橙子 中文AV高清不卡在线 | 一日本道a高清免费播放 | 亚洲a∨激情综合五月 | 最新在线精品国自 | 精品亚洲成AV片在线观看 | 亚洲国产大片一区官网 |