canvas-toDataURL()将图片转为dataURL(base64)

将图片转换为Base64编码可以减少图片请求,解决路径问题。本文介绍了利用canvas-toDataURL方法将图片转为dataURL,解决跨域问题,并提供了相关解决方案和代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

将图片转为base64的好处

  • 将图片转换为Base64编码,可以让你很方便地在没有上传文件的条件下将图片插入其它的网页、编辑器中。 这对于一些小的图片是极为方便的,因为你不需要再去寻找一个保存图片的地方。

  • 将图片转换成base64编码的,在web网上一般用于小图片上,不仅可以减少图片的请求数量(集合到js、css代码中),还可以防止因为一些相对路径等问题导致图片404错误。

一个应用场景:由于某些特殊原因从服务端请求到图片路径,要求通过该路径获取对应图片的 base64 dataURL.

一个完整的 dataURI 应该是这样的:

data:[<mediatype>][;base64],<data>

其中mediatype声明了文件类型,遵循MIME规则,如“image/png”、“text/plain”;之后是编码类型,这里我们只涉及 base64;紧接着就是文件编码后的内容了。

  • 我们常常在 HTML 里看到img标签的src会这样写:
src="data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwAAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFzByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSpa/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJlZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uisF81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PHhhx4dbgYKAAA7"

这个img引用的就是以 base64 编码的 dataURL 了,只要浏览器支持,就可以被解码成 gif 图片并渲染出来。

  • 或者在CSS中使用:
    background-image:url("data:image/png;base64,iVBORw0KGgo=...");

解决办法:

FileReader对象也有类似的方法,比如.readAsDataURL(),然而它只接受file或blob类型,而这两种类型一般只能通过<input[type=file]>元素的files属性获取,或者用Blob()构造函数手工创建一个新的对象。尴尬的是我们当前只有图片路径,受制于浏览器的安全策略,<input[type=file]>的files属性是只读的,而Blob()构造函数只接受文件内容,两种方式都无法通过图片路径直接获取。上文中假设的应用场景迫使我们必先考虑如何通过路径获取到图片内容。<img>是可以的,并且可以被绘制到<canvas>中,而<canvas>正巧拥有.toDataURL()方法。

解决办法一:canvas-toDataURL()

把获取到的图片放到里再通过.toDataURL()方法转化下,就可以得到以 base64 编码的 dataURL。

canvas.toDataURL([type, encoderOptions]);

 canvas是DOM元素<canvas>对象;参数type指定图片类型,如果指定的类型不被支持则以默认值image/png替代;encoderOptions可以为image/jpeg或image/webp类型的图片设置图片质量,取值0-1,超出则以默认值0.92替代。

需要注意的是,在转换成 dataURL 前必须先确保图片成功加载到,于是.toDataURL()方法应该写在<img>的onload异步事件中。现在就来实现一个功能函数:

function getBase64(url) {
        //通过构造函数来创建的 img 实例,在赋予 src 值后就会立刻下载图片,相比 createElement() 创建 <img> 省去了 append(),也就避免了文档冗余和污染
        var Img = new Image(),
            dataURL = '';
        Img.src = url;
        Img.onload = function() { //要先确保图片完整获取到,这是个异步事件
            //创建canvas元素
            var canvas = document.createElement("canvas"), 
            width = Img.width, //确保canvas的尺寸和图片一样
            height = Img.height;
            canvas.width = width;
            canvas.height = height;
            canvas.getContext("2d").drawImage(Img, 0, 0, width, height); //将图片绘制到canvas中
            dataURL = canvas.toDataURL('image/jpeg'); //转换图片为dataURL
        };
        return dataURL;
    }

跨域访问图片遇到的问题:

报错:Uncaught SecurityError: Failed to execute ‘toDataURL’ on ‘HTMLCanvasElement’: Tainted canvases may not be exported.

canvas绘制图片,由于浏览器的安全考虑,如果在使用canvas绘图的过程中,使用到了外域的图片资源,那么在toDataURL()时会抛出安全异常

解决方案1.

如果想使用toDataURL()生成图片文件的话,在canvas绘图过程中使用的图片应该是当前域下的。

解决方案2.

①访问的服务器允许,资源跨域使用,也就是说设置了CORS跨域配置,Access-Control-Allow-Origin

②然后在客户端访问图片资源的时候

var img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.src = url;

一个完整的案例:

<!DOCTYPE html>
<html lang="en">

<head>
    <title>123</title>
    <meta http-equiv="X-UA-Compatible" content="chrome=1">
    <script>
    window.onload = function() {  
        draw();  
        var saveButton = document.getElementById("saveImageBtn");  
        bindButtonEvent(saveButton, "click", saveImageInfo);  
        var dlButton = document.getElementById("downloadImageBtn");  
        bindButtonEvent(dlButton, "click", saveAsLocalImage);  
    };  
        function draw(){  
            var canvas = document.getElementById("thecanvas");  
            var ctx = canvas.getContext("2d");  
            ctx.fillStyle = "rgba(125, 46, 138, 0.5)";  
            ctx.fillRect(25,25,100,100);   
            ctx.fillStyle = "rgba( 0, 146, 38, 0.5)";  
            ctx.fillRect(58, 74, 125, 100);  
            ctx.fillStyle = "rgba( 0, 0, 0, 1)"; // black color  
            ctx.fillText("Gloomyfish - Demo", 50, 50);  
        }  

        function bindButtonEvent(element, type, handler)  
        {  
               if(element.addEventListener) {  
                  element.addEventListener(type, handler, false);  
               } else {  
                  element.attachEvent('on'+type, handler);  
               }  
        }  

        function saveImageInfo ()   
        {  
            var mycanvas = document.getElementById("thecanvas");  
            var image    = mycanvas.toDataURL("image/png");  
            console.log(image);
            var w=window.open('about:blank','image from canvas');  
            w.document.write("<img src='"+image+"' alt='from canvas'/>");  
        }  

        function saveAsLocalImage () {  
            var myCanvas = document.getElementById("thecanvas");  
            // here is the most important part because if you dont replace you will get a DOM 18 exception.  
            var image = myCanvas.toDataURL("image/png").replace("image/png", "image/octet-stream;Content-Disposition: attachment;filename=foobar.png");  
            // var image = myCanvas.toDataURL("image/png").replace("image/png", "image/octet-stream");   
            window.location.href=image; // it will save locally  
        }
    </script>
</head>

<body bgcolor="#E6E6FA">
    <div>
        <canvas width=200 height=200 id="thecanvas"></canvas>
        <button id="saveImageBtn">Save Image</button>
        <button id="downloadImageBtn">Download Image</button>
    </div>

    </script> 
</body>

</html>

解决办法二:FileReader的readAsDataURL()

参考链接:http://www.jianshu.com/p/17d7e5ddf10a
http://blog.youkuaiyun.com/jia20003/article/details/8948005
http://imgbase64.duoshitong.com/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值