<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      文本轉(zhuǎn)圖片 (text-to-image)

      /**
       * 文本轉(zhuǎn)圖片
       * @param {Object} options - 配置項
       * @param {string} text - 文本
       * @param {number} [width=200] - 圖片寬度
       * @param {number} [height=200] - 圖片高度
       * @param {string} [backgroundColor='transparent'] - 背景色
       * @param {string} [fontFamily='Arial'] - 字體
       * @param {number} [fontSize=16] - 字體大小
       * @param {string} [fontColor='black'] - 字體顏色
       * @param {number} [lineHeight=1.2] - 行高
       * @param {boolean} [horizontalCenter=false] - 水平居中
       * @param {boolean} [verticalCenter=false] - 垂直居中
       * @param {number} [padding=10] - 邊距
       * @returns {string} base64
       */
      function textToImage(options) {
        const {
          text,
          width = 200,
          height = 200,
          backgroundColor = 'transparent',
          fontFamily = 'Arial',
          fontSize = 16,
          fontColor = 'black',
          lineHeight = 1.2,
          horizontalCenter = false,
          verticalCenter = false,
          padding = 10,
        } = options;
      
        const dpr = devicePixelRatio || 1;
      
        // const canvas = new OffscreenCanvas(width, height)
      
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
      
        canvas.width = width * dpr;
        canvas.height = height * dpr;
        canvas.style.width = `${width}px`;
        canvas.style.height = `${height}px`;
      
        ctx.scale(dpr, dpr);
      
        // 設(shè)置背景色
        ctx.fillStyle = backgroundColor;
        ctx.fillRect(0, 0, width, height);
      
        // 設(shè)置字體
        ctx.font = `${fontSize}px ${fontFamily}`;
        ctx.fillStyle = fontColor;
      
        const words = text.split(' ');
        let line = '';
        const lines = [];
      
        // 計算每行的最大寬度
        const maxWidth = width - padding * 2;
      
        for (const word of words) {
          const testLine = line + word + ' ';
          const metrics = ctx.measureText(testLine);
      
          // 如果超出最大寬度,則換行
          if (metrics.width > maxWidth) {
            lines.push(line);
            line = word + ' ';
          } else {
            line = testLine;
          }
        }
        lines.push(line);
      
        // 計算文本位置
        const drawableWidth = width - padding * 2;
        const drawableHeight = height - padding * 2;
        // const totalTextHeight = lines.length * fontSize * lineHeight;
      
        // 限制文本行數(shù)
        const maxLines = Math.floor(drawableHeight / (fontSize * lineHeight));
        const displayLines = lines.slice(0, maxLines);
      
        let startX = horizontalCenter ? width / 2 : padding;
      
        let startY = verticalCenter
          ? (height - displayLines.length * fontSize * lineHeight) / 2 + (fontSize * lineHeight) / 2
          : padding;
      
        // 設(shè)置文本對齊方式
        ctx.textAlign = horizontalCenter ? 'center' : 'left';
        ctx.textBaseline = verticalCenter ? 'middle' : 'top';
      
        // 繪制文本
        displayLines.forEach((line, index) => {
          let truncatedLine = line.trim();
          while (ctx.measureText(truncatedLine).width > drawableWidth && truncatedLine.length > 0) {
            truncatedLine = truncatedLine.slice(0, -1);
          }
      
          ctx.fillText(truncatedLine, startX, startY + index * fontSize * lineHeight);
        });
      
        queueMicrotask(() => {
          canvas.remove();
        });
      
        return canvas.toDataURL('image/png');
      
        // const blob = await canvas.convertToBlob();
        // return URL.createObjectURL(blob);
      }
      
      • 使用
      const base64 = textToImage({
        text: 'Hello, World! This is a best d
        width: 200,
        height: 200,
        backgroundColor: 'pink',
        fontSize: 24,
        lineHeight: 1.25,
        horizontalCenter: false,
        verticalCenter: false,
        padding: 10,
      });
      let img = new Image();
      img.onload = () => {
        document.body.appendChild(img);
      };
      img.src = base64;
      

      • 方式二
      <!DOCTYPE html>
      <html lang="en">
      
      <head>
      	<meta charset="UTF-8" />
      	<meta name="viewport" content="width=device-width, initial-scale=1.0" />
      	<title>Text to Image</title>
      	<style>
      		img {
      			width: 100px;
      			height: 100px;
      		}
      	</style>
      </head>
      
      <body>
      	<canvas id="canvas"></canvas>
      	<script>
      		function textToImage({
              text,
              font = '14px Arial', // 默認(rèn)字體
              width = 200, // 默認(rèn)畫布寬度
              height = 200, // 默認(rèn)畫布高度
              backgroundColor = '#FFFFFF', // 默認(rèn)背景色
              textColor = '#000000', // 默認(rèn)文字顏色
              padding = 10, // 默認(rèn)內(nèi)邊距
              align = 'left', // 默認(rèn)水平居中
              valign = 'top', // 默認(rèn)垂直居中
            }) {
              /** @type {HTMLCanvasElement} */
              const canvas = document.getElementById('canvas');
              const ctx = canvas.getContext('2d');
      
              const maxWidth = width - 2 * padding;
              const fontSize = parseInt(font.match(/\d+/)[0] ?? 14); // 字體大小
              const dpr = window.devicePixelRatio || 1; // 默認(rèn)設(shè)備像素比
      
              // 根據(jù) DPR 設(shè)置實際畫布大小
              canvas.width = width * dpr;
              canvas.height = height * dpr;
              ctx.scale(dpr, dpr); // 縮放畫布
      
              // 設(shè)置背景色
              ctx.fillStyle = backgroundColor;
              ctx.fillRect(0, 0, width, height);
      
              // 設(shè)置字體
              ctx.font = font;
              ctx.fillStyle = textColor;
              ctx.textBaseline = 'top'; // 設(shè)置文字基線
      
              // 計算最大寬度
              let lineWidth = maxWidth || width - 2 * padding;
      
              // 創(chuàng)建緩存 Map 存儲非中文的單詞寬度
              const wordCache = new Map();
      
              // 自動換行文本
              const lines = wrapText(ctx, text, lineWidth, wordCache);
      
              // 計算文本總高度
              let textHeight = lines.length * fontSize + (lines.length - 1) * 5; // 字體高度 + 行間距
              if (textHeight > height - 2 * padding) {
                // 如果文本高度超出,截斷文本
                lines.length = Math.floor((height - 2 * padding) / (fontSize + 5));
                textHeight = lines.length * fontSize + (lines.length - 1) * 5;
              }
      
              // 計算文字的起始位置,支持水平和垂直居中
              const x = align === 'center' ? (width - lineWidth) / 2 : padding;
              const y = valign === 'middle' ? (height - textHeight) / 2 : padding;
      
              // 繪制文本
              for (let i = 0; i < lines.length; i++) {
                ctx.fillText(lines[i], x, y + i * (fontSize + 5));
              }
            }
      
            function wrapText(ctx, text, maxWidth, wordCache) {
              let lines = [];
              let currentLine = '';
              let words = text.split(' ');
      
              // 遍歷每個單詞
              for (let i = 0; i < words.length; i++) {
                const word = words[i];
      
                // 判斷當(dāng)前單詞是否為中文
                const isChinese = /[\u4e00-\u9fa5]/.test(word);
      
                // 獲取單詞的寬度,優(yōu)先從緩存獲取
                let wordWidth;
                if (isChinese) {
                  // 中文字符逐個測量
                  wordWidth = ctx.measureText(word).width;
                } else {
                  // 非中文字符從緩存獲取
                  if (wordCache.has(word)) {
                    wordWidth = wordCache.get(word);
                  } else {
                    wordWidth = ctx.measureText(word).width;
                    wordCache.set(word, wordWidth); // 緩存非中文單詞的寬度
                  }
                }
      
                // 檢查當(dāng)前行加上該單詞后是否超出最大寬度
                if (ctx.measureText(currentLine).width + wordWidth > maxWidth && currentLine !== '') {
                  lines.push(currentLine); // 當(dāng)前行寬度超出,換行
                  currentLine = word; // 新的一行從當(dāng)前單詞開始
                } else {
                  currentLine += (currentLine ? ' ' : '') + word; // 當(dāng)前行繼續(xù)添加該單詞
                }
              }
      
              // 最后一行文本
              if (currentLine) {
                lines.push(currentLine);
              }
      
              return lines;
            }
      
            // 示例調(diào)用
            textToImage({
              text: 'This is a long text example that will wrap when necessary. 中文的文本也可以處理。 This is a long text example that will wrap when necessary. 中文的文本也可以處理。 This is a long text example that will wrap when necessary. 中文的文本也可以處理。 This is a long text example that will wrap when necessary. 中文的文本也可以處理。',
              font: '14px Arial',
              width: 100,
              height: 100,
              backgroundColor: '#e0e0e0',
              textColor: '#333',
              padding: 10,
              // align: 'left',
              // valign: 'top',
            });
      	</script>
      </body>
      
      </html>
      
      posted @ 2025-01-21 22:59  _clai  閱讀(1322)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产精品中文av专线| 免费无码一区二区三区蜜桃大| 久久午夜无码鲁丝片午夜精品 | 久久99久久99精品免视看国产成人| 国产欧美日韩亚洲一区二区三区| 亚洲一区二区在线无码| 久久精品不卡一区二区| 久久爱在线视频在线观看| 国产精品免费看久久久| 撕开奶罩揉吮奶头高潮av| 精品人妻系列无码天堂| 国产三级黄色片在线观看| 国产伦码精品一区二区| 临高县| 亚洲乱码一二三四区国产| 91密桃精品国产91久久| 午夜欧美日韩在线视频播放 | 亚洲成在人线AV品善网好看| 亚洲女人天堂成人av在线| 免费无码肉片在线观看| 成人免费区一区二区三区| 中文字幕色av一区二区三区| 国产高清视频一区二区三区| 免费看黄片一区二区三区| 女人张开腿无遮无挡视频| 国产av亚洲精品ai换脸电影| 国产亚洲综合欧美视频| 国产精品日韩av在线播放| 色综合人人超人人超级国碰| 福利一区二区1000| 亚洲 欧美 唯美 国产 伦 综合| WWW丫丫国产成人精品| 国产一区二区三区精品自拍| 香港日本三级亚洲三级| av中文字幕在线二区| 亚洲日本中文字幕天天更新| 4399理论片午午伦夜理片| 国产精品大全中文字幕| 国产精品户外野外| 亚洲一卡2卡3卡4卡精品| 昌平区|