如何判断图片为透明图片 getImageData rgba

本文探讨了如何使用HTML5 Canvas处理跨域图片,包括检测图片透明度、保存图片到DOM存储,以及解决由CORS引起的canvas污染问题。介绍了如何设置服务器响应头以允许跨域请求,并提供了代码示例。

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

            let _img = new Image(),
                    _canvas = window.document.createElement("canvas"),
                    _context = _canvas.getContext("2d");
            _img.onload = function () {
                let originWidth = _img.width,
                    originHeight = _img.height;
                _canvas.width = originWidth;
                _canvas.height = originHeight;
                _context.clearRect(0, 0, originWidth, originHeight);
                _context.drawImage(_img, 0, 0);
                let imageData = _context.getImageData(0, 0, originWidth, originHeight).data;
                // 检测是否是透明图片 Uint8ClampedArray 描述了一个一维数组,包含以 RGBA 顺序的数据,数据使用  0 至 255(包含)的整数表示。
                isTransparent = true;
                for (let index = 3; index < imageData.length; index += 4) {
                    if (imageData[index] !== 0) {
                        isTransparent = false;
                        break;
                    }
                }
               
            };
            _img.onerror = function () {
       
            };
            _img.url = _url;

注意:

HTML 规范文档为 images 引入了 crossorigin属性, 通过设置适当的头信息 CORS, 可以从其他站点加载 img图片, 并用在 canvas 中,就像从当前站点(current origin)直接下载的一样.

crossorigin属性的使用细节, 请参考 CORS settings attributes.

什么是 “被污染的(tainted)” canvas?

尽管没有CORS授权也可以在 canvas 中使用图像, 但这样做就会污染(taints)画布。 只要 canvas 被污染, 就不能再从画布中提取数据, 也就是说不能再调用 toBlob()toDataURL()和 getImageData()等方法, 否则会抛出安全错误(security error).

这实际上是为了保护用户的个人信息,避免未经许可就从远程web站点加载用户的图像信息,造成隐私泄漏。

(译者注: 如果用户登陆过QQ等社交网站, 假若不做保护,则可能打开某个网站后,该网站利用 canvas 将用户的图片信息获取,上传,进而引发泄露.)

示例: 从其他站点保存图片

首先, 图片服务器必须设置相应的 Access-Control-Allow-Origin响应头。添加 img 元素的 crossOrigin 属性来请求头。比如Apache服务器,可以拷贝 HTML5 Boilerplate Apache server configs中的配置信息, 来进行回应:

<IfModule mod_setenvif.c>
    <IfModule mod_headers.c>
    <FilesMatch "\.(cur|gif|ico|jpe?g|png|svgz?|webp)$">
        SetEnvIf Origin ":" IS_CORS
        Header set Access-Control-Allow-Origin "*" env=IS_CORS
    </FilesMatch>
    </IfModule>
</IfModule> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

这些设置生效之后, 就可以像本站的资源一样, 保存其他站点的图片到 DOM存储之中(或者其他地方)。

var img = new Image,
    canvas = document.createElement("canvas"),
    ctx = canvas.getContext("2d"),
    src = "http://example.com/image"; // 具体的图片地址

img.crossOrigin = "Anonymous";

img.onload = function() {
    canvas.width = img.width;
    canvas.height = img.height;
    ctx.drawImage( img, 0, 0 );
    localStorage.setItem( "savedImageData", canvas.toDataURL("image/png") );
}
img.src = src;
//  确保缓存的图片也触发 load 事件
if ( img.complete || img.complete === undefined ) {
    img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
    img.src = src;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

浏览器兼容性

Desktop

FeatureChromeFirefox (Gecko)Internet ExplorerOperaSafari
Basic support138No supportNo support?

Mobile

FeatureAndroidFirefox Mobile (Gecko)IE MobileOpera MobileSafari Mobile
Basic support?????
--------------------- 本文来自 铁锚 的优快云 博客 ,全文地址请点击:https://blog.youkuaiyun.com/renfufei/article/details/51675148?utm_source=copy 

 

 

参考链接:

https://developer.mozilla.org/zh-CN/docs/Web/API/ImageData

https://www.zhangxinxu.com/wordpress/2018/05/canvas-png-transparent-background-detect/

https://www.zhangxinxu.com/wordpress/2017/12/canvas-getimagedata-letter-shape-animation/

https://blog.youkuaiyun.com/renfufei/article/details/51675148

 

<think>好的,我需要帮助用户创建一个带有刮刮乐效果的HTML页面,要求包括自定义奖品列表、随机排序奖品、显示图片和添加音效,同时页面设计要美观。让我一步步思考如何实现。 首先,用户的需求是制作一个刮刮乐网页,主要功能包括:奖品列表随机排序、刮开显示图片、播放音效,以及吸引人的设计。我需要结合HTML、CSS和JavaScript来实现这些功能。 根据引用[2]和[3],刮刮乐通常有两层:底层的奖品和覆盖层。使用HTML5的Canvas可以实现刮刮效果,覆盖层通过绘制半透明的颜色层,用户用鼠标或触摸刮开时,清除该层的部分区域,露出底层内容。 奖品列表需要自定义,并且每次加载时随机排序。JavaScript中可以用数组存储奖品,然后使用sort方法结合随机数进行打乱顺序。例如,将奖品数组shufflePrizes = prizes.sort(() => Math.random() - 0.5)。 显示奖品图片的部分,用户刮开后需要展示对应的图片。可能需要在底层Canvas中绘制图片,或者当刮开区域达到一定比例时,显示对应的图片元素。考虑到Canvas的绘制,可能需要预加载图片,根据刮开的区域触发显示。 音效方面,当用户开始刮或刮开完成时播放声音。使用HTML5的Audio元素,在JavaScript中控制播放。比如,在mousedown事件中开始播放刮擦声,在mouseup或刮开完成时停止或播放中奖音效。 页面美观设计需要用到CSS,比如背景渐变、阴影效果、圆角边框等。引用[2]提到创建基本结构,可能需要一个容器div,内部包含Canvas元素。覆盖层上的“请刮开”字样可以用CSS绝对定位在Canvas上方。 接下来,具体实现步骤: 1. HTML结构:创建容器,包含Canvas元素、隐藏的图片元素和音效元素。 2. CSS样式:设计页面背景、Canvas的样式,设置覆盖层的文字样式。 3. JavaScript逻辑: - 初始化Canvas,绘制覆盖层。 - 处理鼠标或触摸事件,记录刮擦路径,清除覆盖层像素。 - 检测刮开面积比例,触发显示奖品图片和播放音效。 - 奖品数组随机排序,确保每次加载顺序不同。 - 预加载奖品图片,根据刮开结果显示对应图片。 - 音效控制,绑定事件播放声音。 需要考虑的问题包括:Canvas的绘制性能、触摸事件的支持、图片预加载、音效的加载和播放时机,以及如何准确检测刮开区域的比例。 例如,引用[4]提到Android中刮刮乐效果使用PorterDuff混合模式,但在Web中,可以通过设置globalCompositeOperation为'destination-out'来擦除覆盖层,实现刮开效果。同时,需要处理不同设备的鼠标和触摸事件,使用clientX和clientY获取正确坐标。 关于随机排序奖品,JavaScript数组的sort方法结合Math.random()可以实现,但需要注意这种方法的随机性是否足够。可能存在偏差,但对于简单需求可能足够。 音效部分,可能需要两个音频文件:刮擦时的声音和中奖时的音效。使用new Audio()创建对象,在适当的事件触发play()。 最后,页面美观方面,可以使用CSS渐变背景、阴影效果,以及动态效果如悬停放大奖品图片,增强吸引力。 测试过程中需要注意不同浏览器的兼容性,尤其是Canvas和音频的支持情况。可能需要提供多种音频格式或使用兼容性处理。 总结步骤后,就可以编写代码,并确保各部分功能正常协作。同时,参考引用中的教程,确保刮刮乐的基本结构正确,并加入用户所需的定制功能。</think>根据需求,我们将分步骤实现一个包含随机奖品、刮卡特效、图片展示和音效的刮刮乐页面。以下是完整实现方案: ```html <!DOCTYPE html> <html> <head> <style> body { background: linear-gradient(135deg, #ff6b6b, #4ecdc4); display: flex; flex-direction: column; align-items: center; height: 100vh; margin: 0; font-family: 'Arial Rounded MT Bold', sans-serif; } #container { position: relative; margin-top: 50px; box-shadow: 0 10px 20px rgba(0,0,0,0.3); border-radius: 15px; overflow: hidden; } #scratchCanvas { background: #fff; } .prize-img { position: absolute; width: 200px; height: 200px; object-fit: cover; display: none; border-radius: 15px; box-shadow: 0 5px 15px rgba(0,0,0,0.3); } .instruction { color: white; font-size: 24px; text-shadow: 2px 2px 4px rgba(0,0,0,0.5); margin-top: 20px; } </style> </head> <body> <div class="instruction">刮开查看奖品!</div> <div id="container"> <canvas id="scratchCanvas" width="400" height="400"></canvas> <img id="prizeImage" class="prize-img"> </div> <audio id="scratchSound" src="https://actions.google.com/sounds/v1/cartoon/clang.ogg"></audio> <audio id="winSound" src="https://actions.google.com/sounds/v1/cartoon/cartoon_boing.ogg"></audio> <script> const prizes = [ { name: '很遗憾,你没中奖', image: 'https://example.com/sad.png' }, { name: '夜宵券', image: 'https://example.com/food.png' }, { name: '卷子一张', image: 'https://example.com/test.png' }, { name: '再来一次', image: 'https://example.com/again.png' } ]; // 随机打乱奖品顺序 const shuffledPrizes = [...prizes].sort(() => Math.random() - 0.5); let currentPrize = shuffledPrizes[0]; const canvas = document.getElementById('scratchCanvas'); const ctx = canvas.getContext('2d'); let isDrawing = false; // 初始化覆盖层 function initCanvas() { ctx.fillStyle = '#95a5a6'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#34495e'; ctx.font = '30px Arial'; ctx.textAlign = 'center'; ctx.fillText('刮开有奖', canvas.width/2, canvas.height/2); } // 刮卡特效实现 canvas.addEventListener('mousedown', () => { isDrawing = true; document.getElementById('scratchSound').play(); }); canvas.addEventListener('mouseup', () => { isDrawing = false; checkScratchedArea(); }); canvas.addEventListener('mousemove', (e) => { if (!isDrawing) return; const rect = canvas.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; ctx.globalCompositeOperation = 'destination-out'; ctx.beginPath(); ctx.arc(x, y, 20, 0, Math.PI * 2); ctx.fill(); }); // 检测刮开面积 function checkScratchedArea() { const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); let transparentPixels = 0; for (let i = 3; i < imageData.data.length; i += 4) { if (imageData.data[i] === 0) transparentPixels++; } if (transparentPixels / (canvas.width * canvas.height) > 0.6) { showPrize(); } } // 显示奖品 function showPrize() { const img = document.getElementById('prizeImage'); img.src = currentPrize.image; img.style.display = 'block'; document.getElementById('winSound').play(); } initCanvas(); </script> </body> </html> ``` ### 核心实现原理: 1. **页面结构**: - 使用`<canvas>`作为刮卡区域 - 隐藏的`<img>`元素用于显示奖品图片 - 两个`<audio>`元素分别存储刮擦音效和中奖音效 2. **随机奖品生成**: - 使用`sort(() => Math.random() - 0.5)`实现数组随机排序[^5] - 奖品对象包含名称和对应图片URL 3. **刮卡特效**: - 通过设置`globalCompositeOperation = 'destination-out'`实现擦除效果[^4] - 使用圆弧路径模拟刮擦笔触 - 实时检测透明像素比例判断是否完成刮卡 4. **交互增强**: - 添加渐变背景和阴影提升视觉效果 - 音效触发时机: - 刮擦开始时播放刮擦音效 - 完全刮开后播放中奖音效 5. **响应式设计**: - 使用CSS Flex布局实现居中显示 - 动态计算鼠标位置确保准确擦除 §§相关优化建议§§ 1. 如何提升刮擦检测的准确性? - 可以采用更精确的像素检测算法,通过四叉树分割优化检测效率 2. 如何增加多语言支持? - 将奖品文本和界面提示提取为多语言资源文件 3. 怎样实现移动端适配? - 添加`touchstart`/`touchmove`事件监听 - 使用`meta viewport`标签优化移动端显示 4. 如何添加加载动画? - 在图片预加载阶段显示loading动画 - 使用CSS动画实现刮卡完成后的粒子特效 [^1]: 刮刮乐实现需要分层处理覆盖层与内容层 [^2]: Canvas是实现刮擦效果的核心技术 [^3]: 随机排序算法保证奖品的公平性 : 混合模式设置是实现擦除效果的关键 : 数组随机排序需要注意算法公平性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值