成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

國慶微信頭像DIY:輕松打造個性化頭像!

開發 前端
國慶節馬上要到了,今天就教你如何從0到1使用canvas生成國慶風微信頭像。

前言

國慶節馬上要到了,今天就教你如何從0到1使用canvas生成國慶風微信頭像。

本文包含以下內容:

  • vue3項目搭建,需求分析
  • canvas合成圖片原理
  • github自動化部署
  • 開發過程遇到的問題及解決方案

搭建項目,分析需求

項目的話就直接使用腳手架生成一個 Vue3 + TS項目

npm create vue@latest

為了方便,使用了Element PlusUI庫

npm install element-plus --save

配置的話,可以查看文檔,全局導入、按需導入都可以看自己的需求

項目搭建完后,就可以來分析一下本次需求大概會涉及哪些功能了

  • 上傳頭像

這是一個合成微信頭像的工具,那就必須得讓用戶上傳自己的微信頭像了

  • 合成模版

為了方便,我們當然還需要提供多種模版供用戶自己選擇

  • 用戶自定義內容

為了讓生成的頭像更具獨一無二性,我們還需要提供用戶自定義內容的功能,比如:用戶輸入文字、選擇文字顏色等

  • 合成頭像

本次需求的重點當然是合成頭像了

  • 下載合成后的頭像

用戶合成完當然還得支持讓他下載

功能開發

上傳頭

<script setup lang="ts">
// 用戶頭像
const user_img = ref("");
const change = (file: any, fileList: any) => {
  console.log(file, fileList);
  const fileReader = new FileReader();
  fileReader.readAsDataURL(file.raw);
  fileReader.onload = (e: any) => {
    user_img.value = e.target.result;
  };
};

// 刪除用戶頭像
const remove = () => {
  user_img.value = "";
};
</script>

這部分比較簡單,主要是用戶上傳自己的微信頭像后再進行展示,UI部分就不貼了,后面有源碼。

合成模版

合成模版部分,這里主要是需要考慮各個模版所需要的合成功能有哪些

<script>
const gqList = ref([
  {
    id: 1,
    name: "模版1",
    img: getImg("gq0", "jpg"),
    template: getImg("tem1"),
    has: ["text"],
    textLabel: "請輸入你的姓",
    desc: "最多輸入1個字",
    text: "宋",
    textLength: 1,
  },
  {
    id: 2,
    name: "模版2",
    img: getImg("gq1", "jpg"),
    template: getImg("tem2"),
  },
  {
    id: 3,
    name: "模版3",
    img: getImg("gq2", "jpg"),
    template: getImg("tem3"),
  },
  {
    id: 4,
    name: "模版4",
    img: getImg("gq3", "jpg"),
    template: getImg("tem4"),
    has: ["text"],
    textLabel: "請輸入祝福語",
    textColor: "#FED800",
    text: "生在國旗下,長在春風里",
    desc: "最多輸入12個字, 請用中文逗號隔開",
    textLength: 12,
  },
  { id: 5, name: "模版5", img: getImg("gq4"), template: getImg("tem5") },
  {
    id: 6,
    name: "模版6",
    img: getImg("gq5", "jpg"),
    template: getImg("tem6"),
    has: ["text"],
    textLabel: "請輸入祝福語",
    textColor: "#FED800",
    desc: "最多輸入12個字, 請用中文逗號隔開",
    text: "不負韶華,只爭朝夕",
    textLength: 12,
  },
  { id: 7, name: "模版7", img: getImg("gq6"), template: getImg("tem7") },
]);
const template_id = ref(1);
// 選擇模版
const gqChange = (val: any) => {
  console.log(val);
  template_id.value = val;
  generateImgRef.value.clear();
  generateImgRef.value.init();
};
</script>

合成圖片

這里其實也不難,主要是使用canvas來繪制圖片以及文字,由于各個模版的合成邏輯不一樣,這里就不全部展示了,但整體上的合成流程是一樣

// 模版4
const drawImg4 = (ctx: any) => {
  const img = new Image();
  img.src = user_img.value;
  const gqImg = new Image();
  gqImg.src = gqList.value[template_id.value - 1].img;
  img.onload = () => {
    ctx.drawImage(img, 0, 0, 300, 300); // 繪制頭像
    gqImg.onload = () => {
      ctx.drawImage(gqImg, 0, 0, 300, 300); // 繪制國慶圖
      ctx.fillStyle = textColor.value; // 設置文字顏色
      ctx.font = "20px kaiti"; // 設置文字大小及字體
      const textList = text.value?.split(",") ?? []; // 以中文逗號分割文字
      textList.forEach((item: string, i: number) => {
        drawVerticalText(ctx, item ?? "", 20 + i * 20, 186 + i * 20, {
          size: 20,
        }); // 繪制文字
      });
    };
    canDownload.value = true; // 合成完成
  };
};

這里主要的難點在于canvas默認不支持文字豎排繪制,所以這里需要特殊處理,原理其實就是遍歷文字,計算文字高度,然后再一個一個去繪制

// 文字豎排
const drawVerticalText = (
  context: any,
  text: string,
  x: number,
  y: number,
  font: any
) => {
  context.save();
  context.font = font;
  for (var i = 0; i < text.length; i++) {
    context.fillText(text[i], x, y + i * font.size);
  }
  context.restore();
};

下載圖片

這里主要是借助a標簽的download屬性,這里在手機上有點坑,后面會提到...

const downloadImg = () => {
  if (!canDownload.value) {
    ElMessage({
      message: "請先合成頭像~",
      type: "warning",
    });
    return;
  }

  const url = canvas.value.toDataURL("image/png");
  const a = document.createElement("a");
  a.href = url;
  a.download = "國慶頭像.png";
  a.click();
};

自動化部署

這里其實之前有寫過文章,主要是使用github action來完成。

搭建完就是這樣的,我們寫完代碼只需要將代碼提交上去就能夠自動打包部署了

對這個不了解的可以去看我之前的文章:使用GitHub Actions實現自動化部署

體驗

開發部署完就可以來體驗一下了

PC上體驗下來,效果還可以。

問題及解決方案

開發過程中也遇到一些問題,來看看是如何解決的吧

保存圖片不清晰

canvas繪制圖片不清晰的原因主要是:

  • 圖片被放大或縮小
  • 圖片沒處于完整像素的位置

因為canvas是點陣圖,由一個個像素組成,當圖像被放大時,一個像素會被強形拉伸至一個以上,多出來的像素均勻的分部在圖像中,計算機為了使拉伸后的圖像看起來平滑,會給這些多出來的像素計算出一個過渡色,縮小圖像時,多個像素合成一個像素,計算機會用這多個像素的色彩值計算出一個過渡色來填充這個像素,不管是放大還是縮小,都會造成圖像原有像素信息丟失。

所以只需要加上以下代碼就能解決

const dpr = window.devicePixelRatio || 1; // 獲取設備的devicePixelRatio
canvas.value.width = 300 * dpr; // 畫布寬高放大dpr倍,繪制后再縮小dpr倍,解決模糊問題
canvas.value.height = 300 * dpr; // 畫布寬高放大dpr倍,繪制后再縮小dpr倍,解決模糊問題
canvas.value.style.width = "300px"; // 顯示高
canvas.value.style.height = "300px"; // 顯示高
ctx.value.scale(dpr, dpr); // 按比例縮放畫布,解決模糊問題

優化完,清晰度提升還是非常明顯的

移動端體驗問題

手機上下載圖片會失敗,這主要是因為blob格式在手機上不能下載,base64格式有點大,那就只能上傳CDN再進行下載了?

不需要,我們可以利用手機上的長按圖片保存來實現

const downloadImg = () => {
  if (!canDownload.value) {
    ElMessage({
      message: "請先合成頭像~",
      type: "warning",
    });
    return;
  }

  const url = canvas.value.toDataURL("image/png");
  if (devices.some((item) => ua.includes(item))) {
    ElMessageBox.alert(
      `
    請長按圖片保存
    <img src="${url}" style="width: 100%;height: 100%;object-fit: contain;" />
    `,
      "保存圖片",
      {
        dangerouslyUseHTMLString: true,
      }
    );
    return;
  }
  const a = document.createElement("a");
  a.href = url;
  a.download = "國慶頭像.png";
  a.click();
};

圖片

打包部署問題

打包生成的_plugin-vue_export-helper.cdc0426e.js文件訪問404,剛開始我還以為是打包路徑配置的有問題,但如果是打包路徑的問題的話也不會只有這一個文件有問題。

最終,我在vite的issues中找到了答案

簡單點講就是Github Pages 阻止了以下劃線字符開頭的文件,所以會導致這個文件訪問返回404。

解決方法就是修改打包邏輯:

const INVALID_CHAR_REGEX = /[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g;
const DRIVE_LETTER_REGEX = /^[a-z]:/i;

build: {
    outDir: "dist",
    assetsDir: "assets",
    chunkSizeWarningLimit: 2000, // 解決包大小超過500kb的警告
    rollupOptions: {
      output: {
        manualChunks: {
          // elementPlus: ["element-plus"],
          // highlightjs: ["highlight.js"],
        },
        chunkFileNames: "assets/[name]-[hash].js",
        entryFileNames: "assets/[name]-[hash].js",
        assetFileNames: "assets/[name]-[hash].[ext]",
        sanitizeFileName: (name) => {
          const match = DRIVE_LETTER_REGEX.exec(name);
          const driveLetter = match ? match[0] : "";
          return (
            driveLetter +
            name.slice(driveLetter.length).replace(INVALID_CHAR_REGEX, "") // 處理文件名中的非法字符
          );
        },
      },
    },
  },

vite.config.ts中加上以上代碼,重新提交部署就可以了。

最后

整個內容到這里就結束了

體驗地址:https://bettersong.github.io/nanjiu-tools/#/generate_image

責任編輯:華軒 來源: 前端南玖
相關推薦

2023-09-29 11:32:07

2011-08-18 18:53:30

win7

2025-02-04 11:18:49

Spring安全應用

2023-06-16 08:00:00

語音助手GPTWhisper

2019-09-25 08:26:20

Python微信頭像

2012-09-24 17:15:57

傲游瀏覽器

2022-09-30 15:02:06

Python國慶紅旗

2020-06-28 07:00:00

推薦系統智能商務服務平臺

2022-03-02 14:31:00

微信來電移動應用

2024-10-05 00:00:25

Cursor網站代碼

2023-10-17 08:42:13

ChatGPT定制指令

2022-11-01 07:19:45

推薦系統非個性化

2024-03-25 07:57:10

ChatGPTPromote人工智能

2025-02-11 10:30:00

2014-12-19 10:02:33

華為智慧城市

2021-10-31 08:52:34

微信電腦版騰訊

2011-01-20 10:19:21

PowerShell個性化

2015-04-17 15:36:50

Teradata數字化

2010-01-11 17:41:26

MXN旅游頻道

2014-07-30 12:08:04

微盟
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 中文字幕成人网 | 亚洲精品国产区 | 日韩精品一区二区三区中文在线 | 一区二区三区视频在线观看 | 久久久久亚洲 | 亚洲欧美在线观看 | 一区二区三区久久久 | 久久精品视频99 | 亚洲人人 | 国产一区二区 | 欧美精品一区二区免费视频 | 成年网站在线观看 | 国产高清无av久久 | 日韩精品一区二区三区免费视频 | 狠狠狠干 | 日韩中文字幕在线不卡 | 精品三级在线观看 | 久久噜噜噜精品国产亚洲综合 | 日韩国产一区二区 | av中文字幕在线播放 | 欧美三区在线观看 | 超碰超碰 | 欧美久久国产精品 | 久草中文在线 | 日本高清视频在线播放 | 毛片在线看片 | 久久成人一区 | 黄色免费在线网址 | 北条麻妃99精品青青久久 | 黄色成人在线网站 | 国产精品一区二区三区四区 | 99精品亚洲国产精品久久不卡 | 久久免费香蕉视频 | 成人一区二区三区在线观看 | 极品销魂美女一区二区 | 国产婷婷色综合av蜜臀av | 97色免费视频 | 精品国产一区二区三区久久久四川 | 欧美一区二区三区,视频 | 黑人巨大精品欧美一区二区免费 | 久久久妇女国产精品影视 |