草庐IT

canvas 导出为图片兼容ie10+,谷歌,火狐等浏览器,代码详解

阿巳交不起水电费 2023-03-28 原文

效果图:


image.png

导出效果:


image.png

如果canvas设置了背景色,导出的图片就不是透明的了,如:


image.png

代码如下,里面详细写了注释,可以快速看懂:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>
<body>
<button id="btn">导出图片</button>
<br/>
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #d3d3d3;">您的浏览器不支持 HTML5 canvas
    标签。
</canvas>
</body>
<script>

    // base64转blob
    function base64ToBlob(code) {
        // 截取base64的数据内容(去掉前面的描述信息,类似这样的一段:data:image/png;base64,)
        var parts = code.split(";base64,");
        var contentType = parts[0].split(":")[1];
        var raw = window.atob(parts[1]); // 解码为2进制数据
        var rawLength = raw.length; // 获取解码后的二进制数据的长度,用于后面创建二进制数据容器
        // 创建一个Uint8Array类型的数组以存放二进制数据
        var uInt8Array = new Uint8Array(rawLength);
        // 将二进制数据存入Uint8Array类型的数组中
        while (rawLength--) {
            uInt8Array[rawLength] = raw.charCodeAt(rawLength)
        }
        // 创建blob对象
        return new Blob([uInt8Array], {type: contentType});
    }

    // 下载图片
    function downLoad(url, name) {
        var a = document.createElement('a')
        a.href = url
        a.setAttribute('download', name)
        // a.setAttribute('target', '_blank')
        // a.click() // 在safari下不行。safari下的A标签默认是没有绑定事件的 Safari不支持非button元素的click事件
        document.body.appendChild(a); // 火狐浏览器必须追加到body里面
        var e = document.createEvent('MouseEvent');
        e.initEvent('click', false, false);
        a.dispatchEvent(e);
        a && document.body.removeChild(a)
    }

    // 下载方式一:ie浏览器使用 canvas.toDataURL("image/png") + window.navigator.msSaveOrOpenBlob 方法
    function canvas2Img() {
        var canvas = document.getElementById('myCanvas')
        var name = 'canvas 下载'
//        console.log(canvas.toDataURL())
        var base64Url = canvas.toDataURL("image/png") // 因为canvas.toDataURL()兼容ie 9+,canvas.toBlob()只兼容ie10+【其中ie还需要加前缀ms,即使用canvas.msToBlob()】  因此这里选选择canvas.toDataURL()这个方法
        if (window.navigator.msSaveOrOpenBlob) {//ie浏览器
//            var imgData = canvas.msToBlob();
//            var blobObj = new Blob([imgData]);
//            console.log(blobObj, 555)
//            window.navigator.msSaveOrOpenBlob(blobObj, name + '.png');

//            window.navigator.msSaveBlob 只能保存,而window.navigator.msSaveOrOpenBlob 有保存和打开两个选项
            window.navigator.msSaveOrOpenBlob(base64ToBlob(base64Url), name + '.png');
        } else { //谷歌火狐浏览器
            downLoad(base64Url, name);
        }
    }

    // 下载方式一:ie浏览器使用 canvas.msToBlob + window.navigator.msSaveOrOpenBlob 方法
    function canvas2Img2() {
        var canvas = document.getElementById('myCanvas')
        var name = 'canvas 下载'
//        console.log(canvas.toDataURL())
        var base64Url = canvas.toDataURL("image/png") // 因为canvas.toDataURL()兼容ie 9+,canvas.toBlob()只兼容ie10+【其中ie还需要加前缀ms,即使用canvas.msToBlob()】  因此这里选选择canvas.toDataURL()这个方法
        if (window.navigator.msSaveOrOpenBlob) {//ie浏览器
            var imgData = canvas.msToBlob();
            var blobObj = new Blob([imgData]);
//            console.log(blobObj, 555)
            window.navigator.msSaveOrOpenBlob(blobObj, name + '.png');
        } else { //谷歌火狐浏览器
            downLoad(base64Url, name);
        }
    }

    // 绑定点击
    var btn = document.querySelector('#btn');
    btn.onclick = function () {
        // canvas2Img()
        canvas2Img2()
    };

    // canvas 绘制
    var c = document.getElementById("myCanvas");
    var ctx = c.getContext("2d");
    ctx.fillStyle = "#FF0000";
    ctx.fillRect(0, 0, c.width, c.height);
    ctx.font = "30px Arial";
    ctx.strokeText("Hello World", 10, 50);
</script>
</html>

下面有几个api需要注意下:

canvas.toDataURL()

image.png

可以看到此api兼容ie9+

canvas.toBlob()

image.png

注意此api兼容的是ie10+,而且注意看兼容ie10的时候还有个标记,这个标记的意思是在ie10中需要加ms前缀,因此代码里面是这样调用的 var imgData = canvas.msToBlob();【注意这里msToBlob不是用的callback方式,而是直接赋值的】
image.png

window.navigator.msSaveBlob 与 window.navigator.msSaveOrOpenBlob 的区别

两个其实差不多,只是window.navigator.msSaveBlob 只能保存,而window.navigator.msSaveOrOpenBlob 有保存和打开两个选项

我在代码中提供了两种下载方式,两个方法主要针对ie浏览器的处理方式不同,canvas2Img需要结合base64ToBlob方法,而canvas2Img2不用。若能解决ie 9下载base64图片的问题,那么推荐使用canvas2Img,不能解决或者没必要兼容ie9的,那么推荐使用canvas2Img2

若对你有帮助,请点个赞吧,谢谢支持!

本文地址:https://www.jianshu.com/p/9b3ad5bc131c,转载请注明出处,谢谢。

参考:
https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/toDataURL
https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/toBlob
https://www.yisu.com/zixun/658160.html
https://www.jianshu.com/p/9b3ad5bc131c

有关canvas 导出为图片兼容ie10+,谷歌,火狐等浏览器,代码详解的更多相关文章

  1. ruby-on-rails - Ruby on Rails - 为文本区域和图片生成列 - 2

    我是Rails的新手,所以请原谅简单的问题。我正在为一家公司创建一个网站。那家公司想在网站上展示它的客户。我想让客户自己管理这个。我正在为“客户”生成一个表格,我想要的三列是:公司名称、公司描述和Logo。对于名称,我使用的是name:string但不确定如何在脚本/生成脚手架终端命令中最好地创建描述列(因为我打算将其设置为文本区域)和图片。我怀疑描述(我想成为一个文本区域)应该仍然是描述:字符串,然后以实际形式进行调整。不确定如何处理图片字段。那么……说来话长:我在脚手架命令中输入什么来生成描述和图片列? 最佳答案 对于“文本”数

  2. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  3. 由于 libgmp.10.dylib 的问题,Ruby 2.2.0 无法运行 - 2

    我刚刚安装了带有RVM的Ruby2.2.0,并尝试使用它得到了这个:$rvmuse2.2.0--defaultUsing/Users/brandon/.rvm/gems/ruby-2.2.0dyld:Librarynotloaded:/usr/local/lib/libgmp.10.dylibReferencedfrom:/Users/brandon/.rvm/rubies/ruby-2.2.0/bin/rubyReason:Incompatiblelibraryversion:rubyrequiresversion13.0.0orlater,butlibgmp.10.dylibpro

  4. ruby - ri 有空文件 – Ubuntu 11.10, Ruby 1.9 - 2

    我正在运行Ubuntu11.10并像这样安装Ruby1.9:$sudoapt-getinstallruby1.9rubygems一切都运行良好,但ri似乎有空文档。ri告诉我文档是空的,我必须安装它们。我执行此操作是因为我读到它会有所帮助:$rdoc--all--ri现在,当我尝试打开任何文档时:$riArrayNothingknownaboutArray我搜索的其他所有内容都是一样的。 最佳答案 这个呢?apt-getinstallri1.8编辑或者试试这个:(非rvm)geminstallrdocrdoc-datardoc-da

  5. ruby-on-rails - 不兼容的库版本 : nokogiri. bundle 需要 8.0.0 或更高版本,但 libiconv.2.dylib 提供 7.0.0 版本 - 2

    为了在我的mac上为一个rails项目安装mysql,我遵循了安装Homebrew软件和删除mac端口的在线建议。这是问题开始的地方。rails项目不会构建,我得到这个:[rake--prereqs]rakeaborted!dlopen(/Users/Parker/.rvm/gems/ruby-1.9.3-p448/gems/nokogiri-1.6.0/lib/nokogiri/nokogiri.bundle,9):Librarynotloaded:/opt/local/lib/libiconv.2.dylibReferencedfrom:/Users/Parker/.rvm/gem

  6. ruby-on-rails - gem install rmagick -v 2.13.1 错误 Failed to build gem native extension on Mac OS 10.9.1 - 2

    我已经通过提供MagickWand.h的路径尝试了一切,我安装了命令工具。谁能帮帮我?$geminstallrmagick-v2.13.1Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingrmagick:ERROR:Failedtobuildgemnativeextension./Users/ghazanfarali/.rvm/rubies/ruby-1.8.7-p357/bin/rubyextconf.rbcheckingforRubyversion>=1.8.5...yescheckingfor/

  7. ruby - 强制浏览器下载文件而不是打开文件 - 2

    我要下载http://foobar.com/song.mp3作为song.mp3,而不是让Chrome在其native中打开它浏览器中的播放器。我怎样才能做到这一点? 最佳答案 您只需要确保发送这些header:Content-Disposition:attachment;filename=song.mp3;Content-Type:application/octet-streamContent-Transfer-Encoding:binarysend_file方法为您完成:get'/:file'do|file|file=File.

  8. ruby-on-rails - Rails 3,在RAILS_ROOT上方显示来自本地文件系统的jpg图片 - 2

    我正在尝试找出一种方法来显示来自不在RAILS_ROOT下(在RedHat或Ubuntu环境中)的已安装文件系统的图像。我不想使用符号链接(symboliclink),因为这个应用程序实际上是通过Tomcat部署的,而当我关闭Tomcat时,Tomcat会尝试跟随符号链接(symboliclink)并删除挂载中的所有图像。由于这些文件的数量和大小,将图像放在public/images下也不是一种选择。我查看了send_file,但它只会显示一张图片。我需要在一个格式良好的页面中显示6个请求的图像。由于膨胀,我宁愿不使用Base64编码,但我不知道如何将图像数据与呈现的页面一起传递下去。

  9. ruby - 404 未找到,但可以从网络浏览器正常访问 - 2

    我在这方面尝试了很多URL,在我遇到这个特定的之前,它们似乎都很好:require'rubygems'require'nokogiri'require'open-uri'doc=Nokogiri::HTML(open("http://www.moxyst.com/fashion/men-clothing/underwear.html"))putsdoc这是结果:/Users/macbookair/.rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/open-uri.rb:353:in`open_http':404NotFound(OpenURI::HT

  10. ruby - 如何在 watir 测试套件结束时关闭浏览器? - 2

    使用ruby​​的watir测试网络应用程序时,浏览器最后会保持打开状态。网上的一些建议是,要进行真正的单元测试,您应该在每次测试时(在拆卸调用中)打开和关闭浏览器,但这很慢而且毫无意义。或者他们做这样的事情:defself.suites=superdefs.afterClass#Closebrowserenddefs.run(*args)superafterClassendsend但这会导致摘要输出不再显示(诸如“100次测试、100次断言、0次失败、0次错误”之类的内容仍应显示)。我怎样才能让ruby​​或watir在我的测试结束时关闭浏览器? 最佳答案

随机推荐