JavaScript在圖片繪制文字兩種方法的實現(xiàn)與對比
序言
本文實現(xiàn)了在圖片上繪制文字的兩種思路,并通過demo的方式,去具體實現(xiàn),實現(xiàn)代碼為組件形式,支持即粘即貼即用。
效果展示
需求簡介
遇到一個這樣的需求,產(chǎn)品要求根據(jù)B端用戶上傳的圖片模板,在C端繪制上個性字體且展示,最后也支持C端用戶下載繪制后的圖片。
解決思路
我們先梳理一下這個需求的一些關(guān)鍵的點,即圖片來源、圖片傳遞路徑、獲取圖片、圖片繪制文字、下載圖片
那最關(guān)鍵的步驟就是圖片繪制
我這里想到了兩種方案:
方案一:定位+html2canvas
將圖片用Image渲染出來并放在一個DOM中,然后將文字再單獨寫一個DOM,通過定位的形式將其定位到對應(yīng)的位置,最后通過html2canvas,將整個DOM繪制成一個canvas,轉(zhuǎn)成圖片下載下來。
代碼實現(xiàn)
import React from "react"; import html2Canvas from "html2canvas"; import { Button, Image } from "antd-mobile"; type LoadCanvasImgProps = { containerStyle?: React.CSSProperties; // 最外層父組件的樣式 backgroundImageSrc?: string; // 背景圖 ImageWidth?: string | number; text?: string; // 需要寫的值 textStyle?: React.CSSProperties; // 渲染文本的樣式 buttonValue?: string; // button值 onClickButton?: () => void; // 點擊下載前執(zhí)行的函數(shù) loadName?: string; // 下載后的文件名稱 }; const LoadCanvasImg: React.FC<LoadCanvasImgProps> = ({ text = "我是名字", loadName = "load", buttonValue = "點擊下載", backgroundImageSrc = "", textStyle = { position: "absolute", top: "0px", left: "0px" }, containerStyle, ImageWidth = 100, onClickButton, }) => { const onHtml2Canvas = async () => { try { const loadBody = document.getElementById("loadBody") as HTMLElement; const canvas = await html2Canvas(loadBody, { useCORS: true, allowTaint: false, }); downloadCanvasImg(canvas); onClickButton && onClickButton(); } catch (error) { console.error("Error generating canvas image:", error); } }; // 下載canvas const downloadCanvasImg = (canvas: HTMLCanvasElement) => { const dataURL = canvas.toDataURL("image/png") || ""; const downloadLink = document.createElement("a"); downloadLink.href = dataURL; downloadLink.download = `${loadName}.png`; document.body.appendChild(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); }; return ( <div className="loadCanvasImg" style={containerStyle}> <div id="loadBody"> <div style={textStyle}>{text}</div> <Image src={backgroundImageSrc} width={ImageWidth} alt="Background" /> </div> <Button onClick={onHtml2Canvas} color="primary"> {buttonValue} </Button> </div> ); }; export default LoadCanvasImg;
使用方式
import React from "react"; import LoadCanvasImg from "..."; // 這里的路徑是你的組件路徑 const Demo1 = () => { return ( <div> <LoadCanvasImg backgroundImageSrc={""} // 圖片的url text={"我是名字"} // 需要繪制的值 containerStyle={{ position: "relative" }} textStyle={{ position: "absolute", top: "10px", left: "100px", fontSize: "20px", }} buttonValue="保存證書" onClickButton={() => {}} // 點擊下載前執(zhí)行的函數(shù) ImageWidth={200} /> </div> ); };
方案二:canvas繪制
先用canvas繪制圖片,再用canvas繪制字體,最后轉(zhuǎn)成圖片下載下來。
代碼實現(xiàn)
import React, { useEffect, useRef } from "react"; import { Button } from "antd-mobile"; interface CanvasFontSizeProps { text?: string; // 要繪制的文字 backgroundImageSrc?: string; // 圖片的url鏈接 x?: number; // 圖片的x軸定位 y?: number; // 圖片的y軸定位 textStyle?: React.CSSProperties; // 繪制的文字樣式 fillStyle?: string | CanvasGradient | CanvasPattern; // canvas繪制文字的樣式 canvasStyle?: React.CSSProperties; // canvas的樣式 } const CanvasFontSize: React.FC<CanvasFontSizeProps> = ({ text = "姓名", backgroundImageSrc = "", x = 100, y = 100, textStyle = { fontFamily: "e1kcQpNW_GBK_ry", fontSize: "22px" }, fillStyle = "#000", canvasStyle = { width: 800, height: 600 }, }) => { const canvasRef = useRef<HTMLCanvasElement>(null); const downloadCanvasImage = () => { const canvas = canvasRef.current; const dataURL = canvas?.toDataURL("image/png") || ""; const downloadLink = document.createElement("a"); downloadLink.href = dataURL; downloadLink.download = "canvas_image.png"; document.body.appendChild(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); }; useEffect(() => { const canvas = canvasRef.current as HTMLCanvasElement; const ctx = canvas.getContext("2d") as CanvasRenderingContext2D; const backgroundImage = new Image(); backgroundImage.setAttribute('crossOrigin', 'Anonymous'); // 跨域的時候加上 backgroundImage.src = backgroundImageSrc; backgroundImage.onload = () => { ctx.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height); ctx.font = `${textStyle.fontSize} ${textStyle.fontFamily}`; ctx.fillStyle = fillStyle; ctx.fillText(text, x, y); }; }, [text, x, y, backgroundImageSrc, textStyle, fillStyle]); return ( <div> <canvas ref={canvasRef} style={canvasStyle} /> <Button onClick={downloadCanvasImage} color="primary"> 下載鏈接 </Button> </div> ); }; export default CanvasFontSize;
使用方式
import React from "react"; import CanvasFontSize from "..."; // 這里的路徑是你的組件路徑 const Demo1 = () => { return ( <div> <CanvasFontSize backgroundImageSrc={""} // 圖片的url text={"我是名字"} // 需要繪制的值 x={10} // x軸坐標(biāo) y={10} // y軸坐標(biāo) textStyle = { fontFamily: "e1kcQpNW_GBK_ry", fontSize: "22px" } // 文字樣式 fillStyle = "#000" // 文字顏色 canvasStyle = { width: 800, height: 600 } // canvas樣式 /> </div> ); };
兩種思路的優(yōu)缺點對比
優(yōu)點 | 缺點 | |
---|---|---|
定位+html2canvas | 對繪制復(fù)雜樣式支持友好 | 需要安裝第三方依賴 |
canvas繪制 | 使用簡單,canvas原生支持 | 遇到復(fù)雜樣式繪制較為困難 |
遇到的一些坑
圖片跨域
使用canvas畫圖片的時候,當(dāng)圖片域名與項目域名不一致的時候,瀏覽器會報跨域錯誤,或執(zhí)行到const dataURL = canvas?.toDataURL("image/png") || ""
這一步報錯;
解決辦法:在使用 Image對象時添加上backgroundImage.setAttribute('crossOrigin', 'Anonymous')
。
到此這篇關(guān)于JavaScript在圖片繪制文字兩種方法的實現(xiàn)與對比的文章就介紹到這了,更多相關(guān)JavaScript圖片繪制文字內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
d3.js入門教程之?dāng)?shù)據(jù)綁定詳解
這篇文章主要介紹了關(guān)于d3.js數(shù)據(jù)綁定的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)只d3.js具有一定的參考價值,需要的朋友下面來一起看看吧。2017-04-04使用plupload自定義參數(shù)實現(xiàn)多文件上傳
這篇文章主要介紹了使用plupload自定義參數(shù)實現(xiàn)多文件上傳的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-07-07Js實現(xiàn)雙擊鼠標(biāo)自動滾動屏幕的示例代碼
這篇文章主要介紹了Js實現(xiàn)雙擊鼠標(biāo)自動滾動屏幕的示例代碼。需要的朋友可以過來參考下,希望對大家有所幫助2013-12-12