iT邦幫忙

2021 iThome 鐵人賽

DAY 18
2
Modern Web

Canvas 小錦囊系列 第 18

Day 18 - 用 canvas 製作電子賀卡

  • 分享至 

  • xImage
  •  

前述

接續昨天做的『文字換行』,今天利用上一篇的操作來做一個應用,
這次的應用靈感是從這個網站來的,滑到最下方,有一個填上文字、修改位置與大小,就可以下載成為賀卡的功能,偷看了一下他的程式碼是用 jQuery 完成的,這邊我用 React 帶大家試試看!

實踐

建立材料

首先我們將觀察到的材料準備好

需要一個主要的 canvas 以及幾個控制項

  const canvasRef = useRef(null);
  const [style, setStyle] = useState({ size: 14, top: 10, left: 10 });
  const [text, setText] = useState("");
  const [image, setImage] = useState(new Image());
  
  return <div>
      <canvas ref={canvasRef}></canvas>
      <div className="mt-8 max-w-xl mx-auto px-8">
        請輸入文字
        <input
          type="text"
          value={text}
          onChange={(e) => setText(e.target.value)}
        />
      </div>
      <div>
        左右
        <input
          type="range"
          value={style?.left}
          onChange={(e) => updateStyle(e, "left")}
        />
      </div>
      <div>
        上下
        <input
          type="range"
          value={style?.top}
          onChange={(e) => updateStyle(e, "top")}
        />
      </div>
      <div>
        大小
        <input
          type="range"
          value={style?.size}
          onChange={(e) => updateStyle(e, "size")}
        />
      </div>
      <button onClick={download}>下載</button>
    </div>

再來就是依據不同的控制項作出不同的處理


/** 放上背景圖 **/
  useEffect(() => {
    if (canvasRef.current) {
      const drawImage = () => {
        const base_image = new Image();
        base_image.setAttribute("crossorigin", "anonymous");
        base_image.src = exampleImg;
        base_image.onload = () => {
          setImage(base_image);
        };
      };
      drawImage();
    }
  }, [canvasRef]);


/** 依照不同的控制項目對文字做改變 **/
  useEffect(() => {
    const drawText = async () => {
      const canvas = canvasRef.current;
      const ctx = canvas.getContext("2d");
      ctx.fillStyle = "#FFF";
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
      ctx.font = `bold ${style?.size}px Arial`;
      ctx.strokeStyle = "white";
      ctx.lineWidth = 3;
      ctx.fillStyle = "black";
      ctx.fillText(text, style?.left, style?.top);
    };

    drawText();
  }, [text, style, image]);

  const updateStyle = (e, key) => {
    setStyle((prev) => ({ ...prev, [key]: e.target.value }));
  };

這裡有一個很重要需要注意的地方!
在改變控制項的時候
需要隨時清掉畫面,如果不將畫面清掉,就會反覆在畫布上增加文字,造成畫面混亂
所以
ctx.fillRect(0, 0, canvas.width, canvas.height);

這個是必要得存在!

再來重複複習昨天的換行功能,
將上方的 fillText 改為 canvasTextAutoLine(text, canvas, style?.left, style?.top, style?.size);
也可以將 textarea 內的 \n作為判斷條件來達成文字換行。

今天的電子賀卡就完成啦~
也可以像上面的範例一樣,增加選擇圖片或是文字顏色來增加賀卡的豐富度~

查看完成程式碼 codesendbox


上一篇
Day 17 - canvas 文字換行
下一篇
Day 19 - 建立 canvas QRCode
系列文
Canvas 小錦囊30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言