当包含 base64 数据作为 href 的 HTML 链接元素 (<a/>) 准备好时,是不是会触发事件?

Posted

技术标签:

【中文标题】当包含 base64 数据作为 href 的 HTML 链接元素 (<a/>) 准备好时,是不是会触发事件?【英文标题】:Is an event triggered when an HTML link element (<a/>) containing base64 data as href is ready?当包含 base64 数据作为 href 的 HTML 链接元素 (<a/>) 准备好时,是否会触发事件? 【发布时间】:2016-03-12 12:19:46 【问题描述】:

我创建了一个 webpage,它基本上并排显示 2 个图像。

它有一个“下载”按钮,该按钮触发一个普通的 javascript 函数,该函数创建一个&lt;canvas&gt; html 元素并将其中的两个图像连接起来。然后它会创建一个带有 base64 编码结果图像的链接 href 并点击它:

&lt;a download="image.png" id="dllink" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABQAAAAMnCAYAAABhnf9DAAAgAElEQVR4nOzdR48kD3rn96j03pfv6qo21dVd3qT3JryP9Jll281..."&gt;&lt;/a&gt;

我正在使用的函数如下所示:

/**
 * 创建画布,在其中绘制两个图像,创建一个带有结果的链接
 * "href" 字段中 base64 格式的图像,将链接附加到文档中,
 * 并点击它
 */
函数保存图像()

    // 获取左图
    var imgLeft = 新图像();
    imgLeft.setAttribute('crossOrigin', '匿名');
    imgLeft.src = "imgleft/" + idxImageShownLeft + ".jpg";
    imgLeft.onload = 函数() 

        // 左图准备好后,获取右图
        var imgRight = 新图像()
        imgRight.setAttribute('crossOrigin', '匿名');
        imgRight.src = "imgright/" + idxImageShownRight + ".jpg";
        imgRight.onload = 函数() 

            // 准备好正确的图像后,创建画布
            var canv = document.createElement("canvas");
            var widthLeft = parseInt(imgLeft.width);
            var widthRight = parseInt(imgRight.width);
            变量宽度 = widthLeft + widthRight;
            变量高度 = imgLeft.height;

            canv.setAttribute("宽度", 宽度);
            canv.setAttribute("高度", 高度);
            canv.setAttribute("id", "myCanvas");
            canv.setAttribute('crossOrigin', '匿名');
            var ctx = canv.getContext("2d");

            // 在画布中绘制两个图像
            ctx.drawImage(imgLeft, 0, 0);
            ctx.drawImage(imgRight, widthLeft, 0);

            // 从画布中创建 PNG 图像
            var img = canv.toDataURL("image/png");

            // 创建链接元素
            var aHref = document.createElement('a');
            aHref.href = img;
            aHref.setAttribute("id", "dlllink");
            aHref.download = "image.png";

            // 将链​​接附加到文档
            var renderDiv = document.getElementById("render");
            renderDiv.replaceChild(aHref, document.getElementById("dlllink"));

            // 点击链接
            aHref.click();
        
    

我的问题是这在 Firefox 上运行良好,但在 Chrome 上却不行。

经过一番调查,我意识到通过在 Chrome 中的 aHref.click(); 行之前设置断点,它可以正常工作。我认为这意味着aHref.click(); 被调用之前 &lt;a href="data:image/png;base64,...&gt;&lt;/a&gt; 准备好被点击,但我不确定。

我找不到此主题的副本。我应该使用哪些关键字才能 100% 确定? 我的调查方向是否正确? 有没有我可以依赖的事件,以便仅在它准备好时调用aHref.click();

【问题讨论】:

它适用于我,我在 ubuntu 上使用 chrome 46.0.2490.86(64 位)。有什么问题?? renderDiv.replaceChild(aHref, document.getElementById("dllink")); 的目的是什么? aHref , #dlink 是同一个元素吗? @Alessandro.Vegna:问题是当我点击“下载”按钮时,有时结果图像会在我的图像编辑器中打开,有时什么也没有发生。 @guest271314:我正在做的是将之前的#dllink 元素替换为新元素 (aHref)。 与您的问题无关,但画布没有 crossorigin 属性。对于您的问题,您确定触发了图像onload 事件吗?我个人总是更喜欢在声明 onload 处理程序后设置 src。另外,我认为在某些 UA 上,链接必须是可见的,这样click() 才能工作。 【参考方案1】:

您可以将它包装在一个 init 函数中,该函数在窗口完成加载时被调用。

function init() 
  aHref.click();

window.onload = init; 

它类似于 jQuery 的 .ready() 方法。

【讨论】:

不幸的是,我在my code 中已经有一个window.onload 函数...有没有办法绕过这个? 你总是可以把它放在一个超时函数中,让 SVG 在点击它之前有机会加载。将其设置为 1 秒。不理想,但可以解决。 感谢您的建议,它帮助我解决了这个问题。显然,使用这样的东西没有帮助:setTimeout(function() aHref.click(); , 3000);。但是,由于某种原因,这效果更好:setTimeout(function() alert("About to click..."); aHref.click(); , 3);。奇怪...【参考方案2】:

aHrefdocument.getElementById("dllink") 似乎是同一个元素?虽然"dllink" 在调用.replaceChild 时尚未附加到document

尝试替换

renderDiv.appendChild(aHref);

renderDiv.replaceChild(aHref, document.getElementById("dllink"));

【讨论】:

是的,document.getElementById("dllink") 是之前使用的元素,aHref 是新创建的元素。我使用.replaceChild 将旧的替换为新的。在此之前,我一直在追加,因此每次单击时都会在我的文档中创建一个新元素。不幸的是,上述问题在当时也存在。 @AlfredDupont 为了避免文档中可能出现重复的ids,是否可以在添加新的#dllink 之前删除现有的#dllink?可以创建 stacksn-ps blog.***.com/2014/09/… , jsfiddle jsfiddle.net 来演示问题吗?见***.com/help/mcve 我已经在使用repaceChild 而不是appendChild,因此在任何给定时间,只有一个ID 为dllink 的元素。我试过制作jsfiddle,但由于某种原因我没有成功......对不起。明天我将阅读如何制作一个最小、完整和可验证的示例,然后再试一次。

以上是关于当包含 base64 数据作为 href 的 HTML 链接元素 (<a/>) 准备好时,是不是会触发事件?的主要内容,如果未能解决你的问题,请参考以下文章

BASE64

四十三 常用内建模块 base64

python 常用内建模块 base64

python 常用的模块(base64)转

像图像或 PDF 文件这样的 MIME 类型不需要 base64 或以其他方式编码吗?

php解密 base64