let _textureIdMapDataContainer = {}
cc.Class({
extends: cc.Component,
properties: {
},
// LIFE-CYCLE CALLBACKS:
onLoad() {
let spriteComp = this.node.getComponent(cc.Sprite)
if (spriteComp.type !== cc.Sprite.Type.SIMPLE || spriteComp.sizeMode !== cc.Sprite.SizeMode.RAW){
throw "目前仅支持sprite SizeMode 为RAW, type 为SIMPLE的方式"
}
this.node._hitTest = this.hitTest.bind(this)
},
start() {
},
hitTest(location) {
let spriteFrame = this.node.getComponent(cc.Sprite).spriteFrame
if (spriteFrame == null) {
return false
}
let posInNode = this.node.convertToNodeSpaceAR(location)
let rect = spriteFrame.getRect()
let offset = spriteFrame.getOffset()
//var type = this.node.getComponent("DecorateItemPrefab").m_type
// cc.log(type + "--", "xxxxxxxxxxxxxx", type)
// cc.log(type + "--", "posInNode", posInNode)
// cc.log(type + "--", "rect", rect)
// cc.log(type + "--", "offset", offset)
if ((posInNode.x < offset.x - rect.width / 2) || (posInNode.y < offset.y - rect.height / 2)
|| (posInNode.x > (offset.x + rect.width / 2)) || (posInNode.y > (offset.y + rect.height / 2))) {
return false
}
else {
let posInRect = cc.v2(parseInt(posInNode.x - offset.x + rect.width / 2), parseInt(posInNode.y - offset.y + rect.height / 2))
// cc.log(type + "--", "posInRect", posInRect)
// cc.log(type + "--", "isRotated", spriteFrame.isRotated())
let tex = spriteFrame.getTexture()
let data
if (tex instanceof cc.RenderTexture) { // 细图(width <= 512 && height <= 512) 被引擎自动打包了
if (cc.sys.platform === cc.sys.QQ_PLAY) { // 玩一玩平台
throw "在玩一玩平台,请确保你的SpriteFrame 的宽高至少有一个大于512, 这样不会被Atlas, 不然被引擎自动Atlas之后,因为玩一玩不支持gl.readPixels 或 getImageData这样的接口,像素就读不出来了"
}
// data就是这个texture的rgba值数组
if (spriteFrame.isRotated()) {
data = rt.readPixels(null, rect.x + posInRect.y, rect.y + posInRect.x, 1, 1)
//cc.log(type + "--", "data", data, rect.x + posInRect.y, rect.y + posInRect.x)
}
else {
data = rt.readPixels(null, rect.x + posInRect.x, rect.y + rect.height - posInRect.y, 1, 1)
//cc.log(type + "--", "data", data, rect.x + posInRect.x, rect.y + rect.height - posInRect.y)
}
}
else {
var dataContainer = _textureIdMapDataContainer[tex.getId()]
if (cc.sys.platform === cc.sys.QQ_PLAY) { // 针对玩一玩的特殊方式
if (!dataContainer) {
tex.getHtmlElementObj().bkImage || tex.getHtmlElementObj()._generateBKImage()
dataContainer = tex.getHtmlElementObj().bkImage
_textureIdMapDataContainer[tex.getId()] = dataContainer
}
var buffer = dataContainer.buffer
buffer.rewind()
if (spriteFrame.isRotated()) {
buffer.jumpBytes(((rect.x + posInRect.y) + (rect.y + posInRect.x) * tex.width) * 4)
//cc.log(type + "--", "data", data, rect.x + posInRect.y, rect.y + posInRect.x)
} else {
buffer.jumpBytes(((rect.x + posInRect.x) + (rect.y + rect.height - posInRect.y) * tex.width) * 4)
//cc.log(type + "--", "data", data, rect.x + posInRect.x, rect.y + rect.height - posInRect.y)
}
data = [buffer.readUint8Buffer(), buffer.readUint8Buffer(), buffer.readUint8Buffer(), buffer.readUint8Buffer()]
}
else {
//Canvas 方式
var scale = 8
var cvs = dataContainer
if (!cvs) {
cvs = document.createElement("canvas")
var ctx = cvs.getContext('2d')
cvs.width = tex.width
cvs.height = tex.height
ctx.drawImage(tex.getHtmlElementObj(), 0, 0, tex.width, tex.height, 0, 0, tex.width / scale, tex.height / scale)
_textureIdMapDataContainer[tex.getId()] = cvs
}
var ctx = cvs.getContext('2d')
if (spriteFrame.isRotated()) {
data = ctx.getImageData((rect.x + posInRect.y) / scale, (rect.y + posInRect.x) / scale, 1, 1).data
//cc.log(type + "--", "data", data, rect.x + posInRect.y, rect.y + posInRect.x)
}
else {
data = ctx.getImageData((rect.x + posInRect.x) / scale, (rect.y + rect.height - posInRect.y) / scale, 1, 1).data
//cc.log(type + "--", "data", data, rect.x + posInRect.x, rect.y + rect.height - posInRect.y)
}
/*
//RenderTexture 方式
var rt = dataContainer
if (!rt){
rt = new cc.RenderTexture()
rt.initWithSize(tex.width, tex.height)
rt.drawTextureAt(tex, 0, 0)
_textureIdMapDataContainer[tex.getId()] = rt
}
// data就是这个texture的rgba值数组
if (spriteFrame.isRotated()) {
data = rt.readPixels(null, rect.x + posInRect.y, rect.y + posInRect.x, 1, 1)
//cc.log(type + "--", "data", data, rect.x + posInRect.y, rect.y + posInRect.x)
}
else {
data = rt.readPixels(null, rect.x + posInRect.x, rect.y + rect.height - posInRect.y, 1, 1)
//cc.log(type + "--", "data", data, rect.x + posInRect.x, rect.y + rect.height - posInRect.y)
}
*/
}
}
if (data[3] <= 0) {
return false
}
else {
return true
}
}
},
onDisable() {
cc.log("DecorateHitTest onDisable")
let spriteFrame = this.node.getComponent(cc.Sprite).spriteFrame
if (spriteFrame == null) {
return false
}
var tex = spriteFrame.getTexture()
if (cc.sys.platform === cc.sys.QQ_PLAY) { // 针对玩一玩的特殊方式
var img = _textureIdMapDataContainer[tex.getId()]
if (img) {
cc.log("DecorateHitTest onDisable QQ bkImage")
img.dispose()
_textureIdMapDataContainer[tex.getId()] = null
}
}
else {
var dataContainer = _textureIdMapDataContainer[tex.getId()]
if (dataContainer) {
if (dataContainer instanceof cc.RenderTexture) { // RenderTexture 方式
cc.log("DecorateHitTest onDisable renderTexture")
dataContainer.destroy()
}
else { // Canvas 方式
cc.log("DecorateHitTest onDisable canvas")
// 暂时不知道如何释放这个引用的Canvas
}
}
_textureIdMapDataContainer[tex.getId()] = null
}
}
// update (dt) {},
});
完善版代码, 玩一玩微信web都可以了
1,微信打包后把 game.js 里面cc.macro.CLEANUP_IMAGE_CACHE = false;不然tex.getHtmlElementObj() 拿到的image 是已经销毁了的, 微信的Image 如何通过Texture拿到? @wangzhe 哲大大可以拉个人过来指导下吗? 这样这个透明点击的问题就算有了个初步的解决方案啦。。
2,QQ玩一玩,使用的SpriteFrame需要width 和 height 有一个大于512, 不然引擎自动atlas 之后,就无法获取到texture对应的Image。。也就无法使用玩一玩Brick引擎自身接口读取像素数据了
Update:
微信里面如果需要透明点击的在特定场景,可以在loading这个场景前cc.macro.CLEANUP_IMAGE_CACHE = false;设置这个,切换其他场景再设置为true,这样,只有这个场景的资源会保留Image 导致多消耗内存