使用canvas标签,将图片与文案合并方案存在的情况

文章介绍了如何在Vue3项目中通过Canvas合并图片并添加文本,但遇到跨域问题。提出了确保资源同一源、设置CORS头、使用代理服务器和服务器端处理等解决方案。
摘要由CSDN通过智能技术生成

一、功能背景:后端返回一张二维码url和姓名,分开的两个字段。前端拿到两个字段后,要实现拼接姓名在二维码图片正下方,合并成新的图片,并点击保存下来,如下图:。


二、项目技术栈:vue3+vant3+vite

三、计划实现方式:
       后端:
拼接姓名再返回新的url返回给前端保存。
       前端:使用canvas标签,将图片与文案放在canvas标签合并生成新的图片再保存

四:存在问题:
     
如果前端在处理时,先看以下代码:


html:

<template>
    <div class="canvas-container">  
        <canvas id="myCanvas"></canvas>  
    </div> 
    <van-button @click="saveImg">保存合并的图片</van-button>
</template>

js:

<script setup lang="ts">
import { onMounted } from "vue";

 // 初始化时设置canvas的大小以适应父元素  
 function resizeCanvas() {  
    let canvas:any = document.getElementById('myCanvas');
    // 获取父元素的宽度  
    const containerWidth = canvas.parentElement.clientWidth;  
    // 设置canvas的宽度为父元素的宽度  
    canvas.width = containerWidth;  
    // 根据需要设置canvas的高度,这里假设我们想要保持一个固定的纵横比  
    const aspectRatio = 1 / 1; // 例如1:1的纵横比  
    canvas.height = containerWidth * aspectRatio;  
  } 

function init() {
    let canvas:any = document.getElementById('myCanvas');
    var ctx = canvas.getContext('2d');
    // 创建一个新的Image对象  
    const img = new Image();  
    
    // 设置图片源(这里使用了一个占位符URL,你需要替换为实际的图片URL)  
    img.src = "https://img.yzcdn.cn/vant/cat.jpeg";//第三方资源图片
    // img.src = "http://10.0.16.78:6688/worker/mb/v1/withdrawal_del.png";//我本地图片(项                                                                        
    // 目public下的图片)
        
    // 当图片加载完成后,绘制图片和文本  
    img.onload = function() {  
        // 绘制图片  
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);  
        
        // 设置文本内容、字体和位置  
        const text = '这是合并的文案';  
        const fontSize = 24;  
        const x = 100;  
        const y = canvas.height - 10 - fontSize;  
        
        // 设置字体样式  
        ctx.font = `${fontSize}px Arial`;  
        
        // 设置文本颜色  
        ctx.fillStyle = 'black';  
        
        // 绘制文本  
        ctx.fillText(text, x, y);  
    }

}

// 保存图片使用canvas的toDataURL方法将其内容转换为PNG格式的DataURL  
function saveImg(){
    let canvas:any = document.getElementById('myCanvas');
    const link = document.createElement('a');
    link.href = canvas.toDataURL('image/png');
    link.download = 'merged_image.png';
    link.click();
}
onMounted(() => {
    resizeCanvas()
    init() 
})

</script>

css:

<style lang="less" scoped>
 /* 设置canvas的宽度为100%,这样它会填满其父元素的宽度 */  
 canvas {  
    width: 100%;  
    /* 如果你希望canvas的高度自动缩放以保持图片的纵横比,  
       可以设置一个相对高度,或者通过JavaScript计算并设置 */  
    height: auto;  
  }  
  /* 你可以设置一个包含canvas的父元素,并给这个父元素设置宽度 */  
  .canvas-container {  
    width: 100%; /* 或者其他你想要的宽度 */  
    /* 可以设置max-width来限制canvas的最大宽度 */  
    max-width: 1000px; /* 例如 */  
    margin: 0 auto; /* 水平居中 */  
  } 
</style>

以上代码看完后,合并展示效果是没有问题的,但是最终你在点击保存时,会报错无法保存,是因为跨域

详细原因是:

      当canvas的内容来自不同的源(即不同的域名、端口或协议)时,浏览器会出于安全考虑限制对其内容的访问。如果你尝试从这样的canvas中导出图片,会抛出一个安全错误。

  link.href = canvas.toDataURL('image/png');: 使用canvastoDataURL方法将其内容转换为PNG格式的DataURL,并将这个DataURL赋值给link元素的href属性。DataURL是一个可以直接嵌入到HTML中的数据编码形式,包含了一个MIME类型(这里是image/png)和编码后的数据。

五、解决方案

  1. 确保所有资源都来自同一源:这是最简单的方法,但可能不是总可行的,尤其是当你依赖于第三方资源时。
  2. 设置CORS头:如果你可以控制canvas内容的源服务器,确保它返回正确的CORS头。这允许跨源请求,并允许canvas操作这些资源。
  3. 使用代理服务器:设置一个代理服务器来从其他源获取资源,并将它们作为同一源的资源返回给你的应用。
  4. 使用服务器端处理:在服务器端处理图像合并或操作,然后直接提供结果图片。

对于大多数web应用来说,最实际的方法可能第4种。确保你的服务器端资源配置正确,允许跨源请求,或者将图像处理逻辑移到服务器端。

其实,以上如果由前端处理,那方案本身就存在些问题的,一是图片是动态返回的,不是写死的资源,二是就算将图片转base64后合并导出图片,那也得考虑性能问题,图片资源大的情况也不可行。这是个人见解,如果有错误地方或更优的办法欢迎提出来!

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值