画布 toDataUrl 没有在最新的 safari 上返回正确的图像

Posted

技术标签:

【中文标题】画布 toDataUrl 没有在最新的 safari 上返回正确的图像【英文标题】:Canvas toDataUrl not returning proper image on latest safari 【发布时间】:2021-12-11 02:45:37 【问题描述】:

我从Convert SVG to image (JPEG, PNG, etc.) in the browser使用了这个sn-p

它在 chrome 中运行良好,但在最新的 safari update 15 之后,生成的图像不正确。

这是 chrome 图片 https://pastebin.com/hcLAS51W

这是 safari 生成的图像 https://pastebin.com/S7tEWQsQ

const base64Image = 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjkyLjk3NzUyODA4OTg4NzY0IDEyOSAzNzQuMDQ0OTQzODIwMjI0NyAxMTAiIGNsYXNzPSJQU1BERktpdC04czFzYmM1MTN0MzRxMzg4OTViNGJoM2p2biIgZm9jdXNhYmxlPSJmYWxzZSIgZGF0YS10ZXN0aWQ9Imluay1zdmciIHN0eWxlPSJsZWZ0OiAwcHg7IHRvcDogMHB4OyB3aWR0aDogMTAwJTsgaGVpZ2h0OiAxMDAlOyBvcGFjaXR5OiAxOyBvdmVyZmxvdzogaGlkZGVuOyI+PHJlY3QgeD0iOTcuOTc3NTI4MDg5ODg3NjQiIHk9IjEzNCIgd2lkdGg9IjM2NC4wNDQ5NDM4MjAyMjQ3IiBoZWlnaHQ9IjEwMCIgY2xhc3M9IlBTUERGS2l0LTc4NzFyZmh5eGI3cGRta3MxbjN4N2F2dnRhIiBzdHlsZT0iZmlsbDogdHJhbnNwYXJlbnQ7Ii8+PGcgc3R5bGU9ImZpbGw6IHRyYW5zcGFyZW50OyI+PGc+PHBhdGggY2xhc3M9IlBTUERGS2l0LTQ3cjV6eHB0eWtoanFwenFkdWU5YWNwaHR6IFBTUERGS2l0LTQ0OG5jcjVtdWhycGM4cDh5dmFkeTUxZW1jIFBTUERGS2l0LVNtb290aC1MaW5lcyIgZD0iTSAyMTIuNzYzODUwODAyMDQ4MiwxNjYuMDQwNTk0NDE4MjY3NDYgQyAxODMuNiwxNjAuNyAxNTQuNSwxNTUuNCAxMzUuNiwxNTIuMyBDIDExNi43LDE0OS4xIDEwNy45LDE0OC4yIDEwNC4wLDE0OS45IEMgMTAwLjIsMTUxLjUgMTAxLjEsMTU1LjkgMTAzLjMsMTYwLjcgQyAxMDUuNSwxNjUuNiAxMDguOSwxNzAuOSAxMTYuNCwxNzYuMiBDIDEyMy45LDE4MS41IDEzNS42LDE4Ni44IDE0Mi45LDE4Ny4xIEMgMTUwLjIsMTg3LjMgMTUzLjEsMTgyLjUgMTU1LjUsMTc3LjYgQyAxNTcuOSwxNzIuOCAxNTkuOSwxNjguMCAxNjEuMSwxNjUuMyBDIDE2Mi4zLDE2Mi43IDE2Mi44LDE2Mi4yIDE2NS43LDE2NS44IEMgMTY4LjYsMTY5LjQgMTczLjksMTc3LjIgMTgwLjcsMTg1LjQgQyAxODcuNSwxOTMuNiAxOTUuOCwyMDIuMyAyMDIuMSwyMDcuNiBDIDIwOC40LDIxMi45IDIxMi44LDIxNC45IDIxOC4zLDIxNS42IEMgMjIzLjksMjE2LjMgMjMwLjcsMjE1LjggMjM1LjYsMjEyLjkgQyAyNDAuNCwyMTAuMCAyNDMuMywyMDQuNyAyNDYuMywxOTcuMiBDIDI0OS4yLDE4OS43IDI1Mi4xLDE4MC4xIDI1My41LDE3NS4wIEMgMjU1LjAsMTY5LjkgMjU1LjAsMTY5LjQgMjU1LjIsMTY5LjIgQyAyNTUuNSwxNjguOSAyNTYuMCwxNjguOSAyNTYuOSwxNjkuNCBDIDI1Ny45LDE2OS45IDI1OS40LDE3MC45IDI2MS41LDE3MS44IEMgMjYzLjcsMTcyLjggMjY2LjYsMTczLjggMjY5LjgsMTc0LjMgQyAyNzIuOSwxNzQuNyAyNzYuMywxNzQuNyAyNzkuMywxNzQuMCBDIDI4Mi4yLDE3My4zIDI4NC42LDE3MS44IDI4Ni41LDE2OS45IEMgMjg4LjUsMTY4LjAgMjg5LjksMTY1LjYgMjkwLjksMTYxLjIgQyAyOTEuOSwxNTYuOSAyOTIuNCwxNTAuNiAyOTAuMiwxNDYuMCBDIDI4OC4wLDE0MS40IDI4My4xLDEzOC41IDI3Ny44LDEzNy4wIEMgMjcyLjUsMTM1LjYgMjY2LjYsMTM1LjYgMjYzLjUsMTM1LjYgQyAyNjAuMywxMzUuNiAyNTkuOCwxMzUuNiAyNTkuNCwxMzYuMSBDIDI1OC45LDEzNi42IDI1OC40LDEzNy41IDI2MS4zLDE0MC45IEMgMjY0LjIsMTQ0LjMgMjcwLjUsMTUwLjEgMjgzLjksMTU2LjEgQyAyOTcuMiwxNjIuMiAzMTcuNiwxNjguNSAzMjkuNSwxNzEuNiBDIDM0MS40LDE3NC43IDM0NC44LDE3NC43IDM1MC44LDE3NC4zIEMgMzU2LjksMTczLjggMzY1LjcsMTcyLjggMzcwLjMsMTcyLjEgQyAzNzQuOSwxNzEuNCAzNzUuNCwxNzAuOSAzNzUuNiwxNzIuMyBDIDM3NS44LDE3My44IDM3NS44LDE3Ny4yIDM3NS44LDE4Mi43IEMgMzc1LjgsMTg4LjMgMzc1LjgsMTk2LjAgMzc1LjYsMjAzLjUgQyAzNzUuNCwyMTEuMCAzNzQuOSwyMTguMiAzNzQuOSwyMjMuMSBDIDM3NC45LDIyNy45IDM3NS40LDIzMC4zIDM3OS43LDIzMS41IEMgMzg0LjEsMjMyLjcgMzkyLjMsMjMyLjcgNDAwLjYsMjMyLjIgQyA0MDguOCwyMzEuOCA0MTcuMSwyMzAuOCA0MjUuNiwyMjkuNiBDIDQzNC4xLDIyOC40IDQ0Mi44LDIyNi45IDQ0OC42LDIyNi4wIEMgNDU0LjUsMjI1LjAgNDU3LjQsMjI0LjUgNDYwLjMsMjI0LjAiIGRhdGEtdGVzdGlkPSJpbmstcGF0aCIgc3R5bGU9InN0cm9rZTogcmdiKDAsIDAsIDApOyBzdHJva2Utd2lkdGg6IDRweDsgcG9pbnRlci1ldmVudHM6IG5vbmU7Ii8+PHBhdGggY2xhc3M9IlBTUERGS2l0LTQ3cjV6eHB0eWtoanFwenFkdWU5YWNwaHR6IFBTUERGS2l0LTQ0OG5jcjVtdWhycGM4cDh5dmFkeTUxZW1jIFBTUERGS2l0LVNtb290aC1MaW5lcyIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgZD0iTSAyMTIuNzYzODUwODAyMDQ4MiwxNjYuMDQwNTk0NDE4MjY3NDYgQyAxODMuNiwxNjAuNyAxNTQuNSwxNTUuNCAxMzUuNiwxNTIuMyBDIDExNi43LDE0OS4xIDEwNy45LDE0OC4yIDEwNC4wLDE0OS45IEMgMTAwLjIsMTUxLjUgMTAxLjEsMTU1LjkgMTAzLjMsMTYwLjcgQyAxMDUuNSwxNjUuNiAxMDguOSwxNzAuOSAxMTYuNCwxNzYuMiBDIDEyMy45LDE4MS41IDEzNS42LDE4Ni44IDE0Mi45LDE4Ny4xIEMgMTUwLjIsMTg3LjMgMTUzLjEsMTgyLjUgMTU1LjUsMTc3LjYgQyAxNTcuOSwxNzIuOCAxNTkuOSwxNjguMCAxNjEuMSwxNjUuMyBDIDE2Mi4zLDE2Mi43IDE2Mi44LDE2Mi4yIDE2NS43LDE2NS44IEMgMTY4LjYsMTY5LjQgMTczLjksMTc3LjIgMTgwLjcsMTg1LjQgQyAxODcuNSwxOTMuNiAxOTUuOCwyMDIuMyAyMDIuMSwyMDcuNiBDIDIwOC40LDIxMi45IDIxMi44LDIxNC45IDIxOC4zLDIxNS42IEMgMjIzLjksMjE2LjMgMjMwLjcsMjE1LjggMjM1LjYsMjEyLjkgQyAyNDAuNCwyMTAuMCAyNDMuMywyMDQuNyAyNDYuMywxOTcuMiBDIDI0OS4yLDE4OS43IDI1Mi4xLDE4MC4xIDI1My41LDE3NS4wIEMgMjU1LjAsMTY5LjkgMjU1LjAsMTY5LjQgMjU1LjIsMTY5LjIgQyAyNTUuNSwxNjguOSAyNTYuMCwxNjguOSAyNTYuOSwxNjkuNCBDIDI1Ny45LDE2OS45IDI1OS40LDE3MC45IDI2MS41LDE3MS44IEMgMjYzLjcsMTcyLjggMjY2LjYsMTczLjggMjY5LjgsMTc0LjMgQyAyNzIuOSwxNzQuNyAyNzYuMywxNzQuNyAyNzkuMywxNzQuMCBDIDI4Mi4yLDE3My4zIDI4NC42LDE3MS44IDI4Ni41LDE2OS45IEMgMjg4LjUsMTY4LjAgMjg5LjksMTY1LjYgMjkwLjksMTYxLjIgQyAyOTEuOSwxNTYuOSAyOTIuNCwxNTAuNiAyOTAuMiwxNDYuMCBDIDI4OC4wLDE0MS40IDI4My4xLDEzOC41IDI3Ny44LDEzNy4wIEMgMjcyLjUsMTM1LjYgMjY2LjYsMTM1LjYgMjYzLjUsMTM1LjYgQyAyNjAuMywxMzUuNiAyNTkuOCwxMzUuNiAyNTkuNCwxMzYuMSBDIDI1OC45LDEzNi42IDI1OC40LDEzNy41IDI2MS4zLDE0MC45IEMgMjY0LjIsMTQ0LjMgMjcwLjUsMTUwLjEgMjgzLjksMTU2LjEgQyAyOTcuMiwxNjIuMiAzMTcuNiwxNjguNSAzMjkuNSwxNzEuNiBDIDM0MS40LDE3NC43IDM0NC44LDE3NC43IDM1MC44LDE3NC4zIEMgMzU2LjksMTczLjggMzY1LjcsMTcyLjggMzcwLjMsMTcyLjEgQyAzNzQuOSwxNzEuNCAzNzUuNCwxNzAuOSAzNzUuNiwxNzIuMyBDIDM3NS44LDE3My44IDM3NS44LDE3Ny4yIDM3NS44LDE4Mi43IEMgMzc1LjgsMTg4LjMgMzc1LjgsMTk2LjAgMzc1LjYsMjAzLjUgQyAzNzUuNCwyMTEuMCAzNzQuOSwyMTguMiAzNzQuOSwyMjMuMSBDIDM3NC45LDIyNy45IDM3NS40LDIzMC4zIDM3OS43LDIzMS41IEMgMzg0LjEsMjMyLjcgMzkyLjMsMjMyLjcgNDAwLjYsMjMyLjIgQyA0MDguOCwyMzEuOCA0MTcuMSwyMzAuOCA0MjUuNiwyMjkuNiBDIDQzNC4xLDIyOC40IDQ0Mi44LDIyNi45IDQ0OC42LDIyNi4wIEMgNDU0LjUsMjI1LjAgNDU3LjQsMjI0LjUgNDYwLjMsMjI0LjAiIGRhdGEtdGVzdGlkPSJjbGlja2FibGUtcGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogNXB4OyIvPjwvZz48L2c+PC9zdmc+';

const svg = window.atob(base64Image);

svgToPng(svg,(imgData)=>
    const pngImage = document.createElement('img');
    document.body.appendChild(pngImage);
    pngImage.src=imgData;
);
 function svgToPng(svg, callback) 
    const url = getSvgUrl(svg);
    svgUrlToPng(url, (imgData) => 
        callback(imgData);
        URL.revokeObjectURL(url);
    );

function getSvgUrl(svg) 
    return  URL.createObjectURL(new Blob([svg],  type: 'image/svg+xml' ));

function svgUrlToPng(svgUrl, callback) 
    const svgImage = document.createElement('img');
    // imgPreview.style.position = 'absolute';
    // imgPreview.style.top = '-9999px';
    document.body.appendChild(svgImage);
    svgImage.onload = function () 
        const canvas = document.createElement('canvas');
        canvas.width = svgImage.clientWidth;
        canvas.height = svgImage.clientHeight;
        const canvasCtx = canvas.getContext('2d');
        canvasCtx.drawImage(svgImage, 0, 0);
        const imgData = canvas.toDataURL('image/png');
        console.log(imgData, 'imgData') // This logged here gives different image in chrome and safari
        callback(imgData);
        // document.body.removeChild(imgPreview);
    ;
    svgImage.src = svgUrl;
 

【问题讨论】:

您是否尝试在屏幕上显示画布以查看它是否正确?您有一堆步骤正在进行,最终结果不正确,但您无法确定哪一步正在中断。弄清楚这一点将大大有助于解决您的问题。 是的,画布在两个浏览器中都正确显示,即使您在 sn-p 上运行时也可以看到 哈,Safari,新的 Internet Explorer 您可以报告webkit错误here 【参考方案1】:

drawImage() 使用没有固有宽度或高度的 SVG 图像是互操作的噩梦。 目前,规范文本确实遵循 Chrome 在此处的行为,但鉴于它们是唯一实现它的人,因此很难将其称为“标准”。

这里的一个问题是您正在根据<img> 元素的clientWidthclientHeight 属性设置画布大小。 这个<img> 元素嵌入了一个没有自己固有宽度和高度的SVG 图像。默认的width 因此被解释为100%。 因此,您的 <img> 元素将占据容器 (<body>) 的任何大小,并且您将画布大小设置为该主体的大小。

但是,这个大小应该只影响<img> 元素,当它的图像绘制在画布上时,这个<img> 元素应该(大部分)无关紧要。

在这种没有固有宽度或高度的图像的特殊情况下,重要的是输出画布的大小。在这种情况下,the current specs texts 要求使用CSS default sizing algorithm 来确定图像的大小,这基本上表示如果定义了使用固有宽度和高度,或者如果图像具有定义的固有纵横比(例如 viewBox),则乘以此比率的可用值,如果两者都不存在,则使用默认大小。 而这个默认大小是由输出画布大小决定的。

这里,<svg> 既没有 width 也没有 height,但它确实有一个内在比率 (110/374.0449438202247),所以 width 将设置为画布宽度和高度将设置为此宽度 x 比率。

因此,drawImage 使用的正确计算的图像大小应该取决于画布大小,因此取决于用户的屏幕大小,我个人觉得这很令人不安。这就是 Chrome 所做的。 另一方面,Safari 使用代表widthheightviewBox 中的值。这种做法是有道理的,但在各种实践中存在问题(例如,使用 0 0 1 1 的 viewBox 来更轻松地在 SVG 中进行绝对定位是很常见的)。

在这种情况下,Firefox 根本不会绘制您的图像。

您可以通过不附加<img>、根据<img>.naturalWidth.naturalHeight 设置画布宽度和高度以及设置根<svg> 元素的widthheight 为绝对值(即不是 %)。 这将为您提供最好的跨浏览器体验和最可预测的体验(由于 Chrome 的行为,您的所有用户都将拥有不同大小的图像)。

const svg = `<svg
    $/* We force width absolute width and height */""
  xmlns="http://www.w3.org/2000/svg" viewBox="92.97752808988764 129 374.0449438202247 110" class="PSPDFKit-8s1sbc513t34q38895b4bh3jvn" focusable="false" data-testid="ink-svg" style="left: 0px; top: 0px; width: 100%; height: 100%; opacity: 1; overflow: hidden;">
  <rect x="97.97752808988764" y="134"   class="PSPDFKit-7871rfhyxb7pdmks1n3x7avvta" style="fill: transparent;"/>
  <g style="fill: transparent;">
    <g>
      <path class="PSPDFKit-47r5zxptykhjqpzqdue9acphtz PSPDFKit-448ncr5muhrpc8p8yvady51emc PSPDFKit-Smooth-Lines"
        d="M 212.7638508020482,166.04059441826746 C 183.6,160.7 154.5,155.4 135.6,152.3 C 116.7,149.1 107.9,148.2 104.0,149.9 C 100.2,151.5 101.1,155.9 103.3,160.7 C 105.5,165.6 108.9,170.9 116.4,176.2 C 123.9,181.5 135.6,186.8 142.9,187.1 C 150.2,187.3 153.1,182.5 155.5,177.6 C 157.9,172.8 159.9,168.0 161.1,165.3 C 162.3,162.7 162.8,162.2 165.7,165.8 C 168.6,169.4 173.9,177.2 180.7,185.4 C 187.5,193.6 195.8,202.3 202.1,207.6 C 208.4,212.9 212.8,214.9 218.3,215.6 C 223.9,216.3 230.7,215.8 235.6,212.9 C 240.4,210.0 243.3,204.7 246.3,197.2 C 249.2,189.7 252.1,180.1 253.5,175.0 C 255.0,169.9 255.0,169.4 255.2,169.2 C 255.5,168.9 256.0,168.9 256.9,169.4 C 257.9,169.9 259.4,170.9 261.5,171.8 C 263.7,172.8 266.6,173.8 269.8,174.3 C 272.9,174.7 276.3,174.7 279.3,174.0 C 282.2,173.3 284.6,171.8 286.5,169.9 C 288.5,168.0 289.9,165.6 290.9,161.2 C 291.9,156.9 292.4,150.6 290.2,146.0 C 288.0,141.4 283.1,138.5 277.8,137.0 C 272.5,135.6 266.6,135.6 263.5,135.6 C 260.3,135.6 259.8,135.6 259.4,136.1 C 258.9,136.6 258.4,137.5 261.3,140.9 C 264.2,144.3 270.5,150.1 283.9,156.1 C 297.2,162.2 317.6,168.5 329.5,171.6 C 341.4,174.7 344.8,174.7 350.8,174.3 C 356.9,173.8 365.7,172.8 370.3,172.1 C 374.9,171.4 375.4,170.9 375.6,172.3 C 375.8,173.8 375.8,177.2 375.8,182.7 C 375.8,188.3 375.8,196.0 375.6,203.5 C 375.4,211.0 374.9,218.2 374.9,223.1 C 374.9,227.9 375.4,230.3 379.7,231.5 C 384.1,232.7 392.3,232.7 400.6,232.2 C 408.8,231.8 417.1,230.8 425.6,229.6 C 434.1,228.4 442.8,226.9 448.6,226.0 C 454.5,225.0 457.4,224.5 460.3,224.0"
        data-testid="ink-path" style="stroke: rgb(0, 0, 0); stroke-width: 4px; pointer-events: none;"/>
      <path class="PSPDFKit-47r5zxptykhjqpzqdue9acphtz PSPDFKit-448ncr5muhrpc8p8yvady51emc PSPDFKit-Smooth-Lines" stroke="transparent"
        d="M 212.7638508020482,166.04059441826746 C 183.6,160.7 154.5,155.4 135.6,152.3 C 116.7,149.1 107.9,148.2 104.0,149.9 C 100.2,151.5 101.1,155.9 103.3,160.7 C 105.5,165.6 108.9,170.9 116.4,176.2 C 123.9,181.5 135.6,186.8 142.9,187.1 C 150.2,187.3 153.1,182.5 155.5,177.6 C 157.9,172.8 159.9,168.0 161.1,165.3 C 162.3,162.7 162.8,162.2 165.7,165.8 C 168.6,169.4 173.9,177.2 180.7,185.4 C 187.5,193.6 195.8,202.3 202.1,207.6 C 208.4,212.9 212.8,214.9 218.3,215.6 C 223.9,216.3 230.7,215.8 235.6,212.9 C 240.4,210.0 243.3,204.7 246.3,197.2 C 249.2,189.7 252.1,180.1 253.5,175.0 C 255.0,169.9 255.0,169.4 255.2,169.2 C 255.5,168.9 256.0,168.9 256.9,169.4 C 257.9,169.9 259.4,170.9 261.5,171.8 C 263.7,172.8 266.6,173.8 269.8,174.3 C 272.9,174.7 276.3,174.7 279.3,174.0 C 282.2,173.3 284.6,171.8 286.5,169.9 C 288.5,168.0 289.9,165.6 290.9,161.2 C 291.9,156.9 292.4,150.6 290.2,146.0 C 288.0,141.4 283.1,138.5 277.8,137.0 C 272.5,135.6 266.6,135.6 263.5,135.6 C 260.3,135.6 259.8,135.6 259.4,136.1 C 258.9,136.6 258.4,137.5 261.3,140.9 C 264.2,144.3 270.5,150.1 283.9,156.1 C 297.2,162.2 317.6,168.5 329.5,171.6 C 341.4,174.7 344.8,174.7 350.8,174.3 C 356.9,173.8 365.7,172.8 370.3,172.1 C 374.9,171.4 375.4,170.9 375.6,172.3 C 375.8,173.8 375.8,177.2 375.8,182.7 C 375.8,188.3 375.8,196.0 375.6,203.5 C 375.4,211.0 374.9,218.2 374.9,223.1 C 374.9,227.9 375.4,230.3 379.7,231.5 C 384.1,232.7 392.3,232.7 400.6,232.2 C 408.8,231.8 417.1,230.8 425.6,229.6 C 434.1,228.4 442.8,226.9 448.6,226.0 C 454.5,225.0 457.4,224.5 460.3,224.0"
        data-testid="clickable-path" style="stroke-width: 5px;"/>
    </g>
  </g>
</svg>`;

svgToPng(svg, (imgData) => 
  const pngImage = document.createElement('img');
  pngImage.src = imgData;
);

function svgToPng(svg, callback) 
  const url = getSvgUrl(svg);
  svgUrlToPng(url, (imgData) => 
    callback(imgData);
    URL.revokeObjectURL(url);
  );


function getSvgUrl(svg) 
  return URL.createObjectURL(new Blob([svg], 
    type: 'image/svg+xml'
  ));


function svgUrlToPng(svgUrl, callback) 
  const svgImage = document.createElement('img');
  // do not append the <img>
  svgImage.onload = function() 
    const canvas = document.createElement('canvas');
    canvas.width = svgImage.naturalWidth;
    canvas.height = svgImage.naturalHeight;
    const canvasCtx = canvas.getContext('2d');
    canvasCtx.drawImage(svgImage, 0, 0);
    // show the <canvas> to debug
    document.body.append(canvas);
    const imgData = canvas.toDataURL('image/png');
    callback(imgData);
  ;
  svgImage.src = svgUrl;
canvas 
  background: chocolate;

【讨论】:

谢谢。这有帮助,但生成的图像质量低。我们如何放大图像?或图像尺寸 通过将宽度和高度属性设置为您想要的值。 同样的问题会发生,如果我增加画布的高度和宽度,在 chrome 中它可以工作,但在 safari 中图像出现在左上角,其余空间被空白占据 请再读一遍这个答案。您需要更改的不是画布的大小,而是您正在绘制的根&lt;svg&gt;widthheight 属性。

以上是关于画布 toDataUrl 没有在最新的 safari 上返回正确的图像的主要内容,如果未能解决你的问题,请参考以下文章

canvas.toDataURL() 用于大画布

从画布获取 img (toDataURL) --> 可能无法导出受污染的画布

画布 todataURL 图像 Png 质量不起作用

toDataURL() 无法在 Blazor Webassembly 中使用 JS 互操作保存 HTML5 画布的内容?

toDataURL() 小屏幕,小保存图片

Konva stage.toDataUrl()是不是渲染我在画布中看到的图像?