mirror of
https://github.com/konvajs/konva.git
synced 2025-04-05 20:48:28 +08:00
new drawHitFromCache Shape method replaces Image createImageHitRegion
This commit is contained in:
parent
fae1c538f3
commit
4d323c7b57
@ -264,10 +264,7 @@
|
||||
|
||||
if (this.shouldDrawHit()) {
|
||||
if (cachedHitCanvas) {
|
||||
context.save();
|
||||
context._applyTransform(this);
|
||||
context.drawImage(cachedHitCanvas._canvas, 0, 0);
|
||||
context.restore();
|
||||
this._drawCachedHitCanvas(context);
|
||||
}
|
||||
else {
|
||||
this._drawChildren(canvas, 'drawHit');
|
||||
|
45
src/Node.js
45
src/Node.js
@ -104,9 +104,8 @@
|
||||
delete this._cache.canvas;
|
||||
},
|
||||
/**
|
||||
* cache node to improve drawing performance.
|
||||
* NOTE: if you have filters applied to your node, your shape is already cached.
|
||||
* explicitly calling cache() will override your filters.
|
||||
* cache node to improve drawing performance, apply filters, or create more accurate
|
||||
* hit regions
|
||||
* @method
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @returns {Kinetic.Node}
|
||||
@ -119,17 +118,17 @@
|
||||
y = box.y || 0,
|
||||
width = box.width || this.width(),
|
||||
height = box.height || this.height(),
|
||||
sceneCanvasCache = new Kinetic.SceneCanvas({
|
||||
cachedSceneCanvas = new Kinetic.SceneCanvas({
|
||||
pixelRatio: 1,
|
||||
width: width,
|
||||
height: height
|
||||
}),
|
||||
filterCanvasCache = new Kinetic.SceneCanvas({
|
||||
cachedFilterCanvas = new Kinetic.SceneCanvas({
|
||||
pixelRatio: 1,
|
||||
width: width,
|
||||
height: height
|
||||
}),
|
||||
hitCanvasCache = new Kinetic.HitCanvas({
|
||||
cachedHitCanvas = new Kinetic.HitCanvas({
|
||||
width: width,
|
||||
height: height
|
||||
}),
|
||||
@ -141,24 +140,28 @@
|
||||
this.x(x * -1);
|
||||
this.y(y * -1);
|
||||
|
||||
this.drawScene(sceneCanvasCache);
|
||||
this.drawHit(hitCanvasCache);
|
||||
this.drawScene(cachedSceneCanvas);
|
||||
this.drawHit(cachedHitCanvas);
|
||||
|
||||
this.x(origX);
|
||||
this.y(origY);
|
||||
this.transformsEnabled(origTransEnabled);
|
||||
|
||||
this._cache.canvas = {
|
||||
scene: sceneCanvasCache,
|
||||
filter: filterCanvasCache,
|
||||
hit: hitCanvasCache,
|
||||
x: x,
|
||||
y: y
|
||||
scene: cachedSceneCanvas,
|
||||
filter: cachedFilterCanvas,
|
||||
hit: cachedHitCanvas
|
||||
};
|
||||
|
||||
return this;
|
||||
},
|
||||
_drawCachedSceneCanvas: function(context) {
|
||||
context.save();
|
||||
context._applyTransform(this);
|
||||
context.drawImage(this._getCachedSceneCanvas()._canvas, 0, 0);
|
||||
context.restore();
|
||||
},
|
||||
_getCachedSceneCanvas: function() {
|
||||
var filters = this.filters(),
|
||||
cachedCanvas = this._cache.canvas,
|
||||
sceneCanvas = cachedCanvas.scene,
|
||||
@ -166,9 +169,6 @@
|
||||
filterContext = filterCanvas.getContext(),
|
||||
len, imageData, n, filter;
|
||||
|
||||
context.save();
|
||||
context._applyTransform(this);
|
||||
|
||||
if (filters) {
|
||||
if (!this._filterUpToDate) {
|
||||
try {
|
||||
@ -192,13 +192,20 @@
|
||||
this._filterUpToDate = true;
|
||||
}
|
||||
|
||||
context.drawImage(filterCanvas._canvas, 0, 0);
|
||||
return filterCanvas;
|
||||
}
|
||||
else {
|
||||
context.drawImage(sceneCanvas._canvas, 0, 0);
|
||||
return sceneCanvas;
|
||||
}
|
||||
},
|
||||
_drawCachedHitCanvas: function(context) {
|
||||
var cachedCanvas = this._cache.canvas,
|
||||
hitCanvas = cachedCanvas.hit;
|
||||
|
||||
context.restore();
|
||||
context.save();
|
||||
context._applyTransform(this);
|
||||
context.drawImage(hitCanvas._canvas, 0, 0);
|
||||
context.restore();
|
||||
},
|
||||
/*
|
||||
* the default isDraggable method returns false.
|
||||
|
55
src/Shape.js
55
src/Shape.js
@ -300,10 +300,7 @@
|
||||
if(this.shouldDrawHit()) {
|
||||
|
||||
if (cachedHitCanvas) {
|
||||
context.save();
|
||||
context._applyTransform(this);
|
||||
context.drawImage(cachedHitCanvas._canvas, 0, 0);
|
||||
context.restore();
|
||||
this._drawCachedHitCanvas(context);
|
||||
}
|
||||
else if (drawFunc) {
|
||||
context.save();
|
||||
@ -317,7 +314,55 @@
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* draw hit graph using the cached scene canvas
|
||||
* @method
|
||||
* @memberof Kinetic.Shape.prototype
|
||||
* @returns {Kinetic.Shape}
|
||||
* @example
|
||||
* shape.cache();
|
||||
* shape.drawHitFromCache();
|
||||
*/
|
||||
drawHitFromCache: function() {
|
||||
var cachedCanvas = this._cache.canvas,
|
||||
sceneCanvas = cachedCanvas.scene,
|
||||
sceneContext = sceneCanvas.getContext(),
|
||||
hitCanvas = cachedCanvas.hit,
|
||||
hitContext = hitCanvas.getContext(),
|
||||
width = sceneCanvas.getWidth(),
|
||||
height = sceneCanvas.getHeight(),
|
||||
sceneImageData, sceneData, hitImageData, hitData, len, rgbColorKey, i, alpha;
|
||||
|
||||
hitContext.clear();
|
||||
|
||||
//try {
|
||||
sceneImageData = sceneContext.getImageData(0, 0, width, height);
|
||||
sceneData = sceneImageData.data;
|
||||
hitImageData = hitContext.getImageData(0, 0, width, height);
|
||||
hitData = hitImageData.data;
|
||||
len = sceneData.length;
|
||||
rgbColorKey = Kinetic.Util._hexToRgb(this.colorKey);
|
||||
|
||||
// replace non transparent pixels with color key
|
||||
for(i = 0; i < len; i += 4) {
|
||||
alpha = sceneData[i + 3];
|
||||
if (alpha > 0) {
|
||||
hitData[i] = rgbColorKey.r;
|
||||
hitData[i + 1] = rgbColorKey.g;
|
||||
hitData[i + 2] = rgbColorKey.b;
|
||||
hitData[i + 3] = alpha;
|
||||
}
|
||||
}
|
||||
|
||||
hitContext.putImageData(hitImageData, 0, 0);
|
||||
// }
|
||||
// catch(e) {
|
||||
// Kinetic.Util.warn('Unable to draw hit graph from cached scene canvas. ' + e.message);
|
||||
// }
|
||||
|
||||
return this;
|
||||
},
|
||||
});
|
||||
Kinetic.Util.extend(Kinetic.Shape, Kinetic.Node);
|
||||
|
||||
|
@ -71,83 +71,12 @@
|
||||
},
|
||||
_hitFunc: function(context) {
|
||||
var width = this.getWidth(),
|
||||
height = this.getHeight(),
|
||||
imageHitRegion = this.imageHitRegion;
|
||||
height = this.getHeight();
|
||||
|
||||
if(imageHitRegion) {
|
||||
context.drawImage(imageHitRegion, 0, 0);
|
||||
context.beginPath();
|
||||
context.rect(0, 0, width, height);
|
||||
context.closePath();
|
||||
context.strokeShape(this);
|
||||
}
|
||||
else {
|
||||
context.beginPath();
|
||||
context.rect(0, 0, width, height);
|
||||
context.closePath();
|
||||
context.fillStrokeShape(this);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* create image hit region which enables more accurate hit detection mapping of the image
|
||||
* by avoiding event detections for transparent pixels
|
||||
* @method
|
||||
* @memberof Kinetic.Image.prototype
|
||||
* @param {Function} [callback] callback function to be called once
|
||||
* the image hit region has been created
|
||||
* @example
|
||||
* image.createImageHitRegion(function() {<br>
|
||||
* layer.drawHit();<br>
|
||||
* });
|
||||
*/
|
||||
createImageHitRegion: function(callback) {
|
||||
var that = this,
|
||||
width = this.getWidth(),
|
||||
height = this.getHeight(),
|
||||
canvas = new Kinetic.SceneCanvas({
|
||||
width: width,
|
||||
height: height,
|
||||
pixelRatio: 1
|
||||
}),
|
||||
_context = canvas.getContext()._context,
|
||||
image = this.getImage(),
|
||||
imageData, data, rgbColorKey, i, len;
|
||||
|
||||
_context.drawImage(image, 0, 0);
|
||||
|
||||
try {
|
||||
imageData = _context.getImageData(0, 0, width, height);
|
||||
data = imageData.data;
|
||||
len = data.length;
|
||||
rgbColorKey = Kinetic.Util._hexToRgb(this.colorKey);
|
||||
|
||||
// replace non transparent pixels with color key
|
||||
for(i = 0; i < len; i += 4) {
|
||||
if (data[i + 3] > 0) {
|
||||
data[i] = rgbColorKey.r;
|
||||
data[i + 1] = rgbColorKey.g;
|
||||
data[i + 2] = rgbColorKey.b;
|
||||
}
|
||||
}
|
||||
|
||||
Kinetic.Util._getImage(imageData, function(imageObj) {
|
||||
that.imageHitRegion = imageObj;
|
||||
if(callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
catch(e) {
|
||||
Kinetic.Util.warn('Unable to create image hit region. ' + e.message);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* clear image hit region
|
||||
* @method
|
||||
* @memberof Kinetic.Image.prototype
|
||||
*/
|
||||
clearImageHitRegion: function() {
|
||||
delete this.imageHitRegion;
|
||||
context.beginPath();
|
||||
context.rect(0, 0, width, height);
|
||||
context.closePath();
|
||||
context.fillStrokeShape(this);
|
||||
},
|
||||
getWidth: function() {
|
||||
var image = this.getImage();
|
||||
|
@ -2929,11 +2929,7 @@ suite('Node', function() {
|
||||
|
||||
assert.notEqual(circle._cache.canvas.scene, undefined);
|
||||
assert.notEqual(circle._cache.canvas.hit, undefined);
|
||||
assert.equal(circle._cache.canvas.x, -74);
|
||||
assert.equal(circle._cache.canvas.y, -74);
|
||||
|
||||
|
||||
|
||||
layer.draw();
|
||||
|
||||
|
||||
|
@ -544,4 +544,56 @@ suite('Shape', function() {
|
||||
|
||||
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
test('create image hit region', function(done) {
|
||||
var imageObj = new Image();
|
||||
|
||||
var stage = addStage();
|
||||
var layer = new Kinetic.Layer();
|
||||
|
||||
imageObj.onload = function() {
|
||||
|
||||
var lion = new Kinetic.Image({
|
||||
x: 200,
|
||||
y: 40,
|
||||
image: imageObj,
|
||||
draggable: true,
|
||||
shadowColor: 'black',
|
||||
shadowBlur: 10,
|
||||
shadowOffset: 20,
|
||||
shadowOpacity: 0.2
|
||||
});
|
||||
|
||||
// override color key with black
|
||||
lion.colorKey = '#000000';
|
||||
Kinetic.shapes['#000000'] = lion;
|
||||
|
||||
layer.add(lion);
|
||||
|
||||
stage.add(layer);
|
||||
|
||||
lion.cache();
|
||||
|
||||
|
||||
//document.body.appendChild(lion._cache.canvas.hit._canvas);
|
||||
|
||||
|
||||
lion.drawHitFromCache();
|
||||
|
||||
|
||||
layer.draw();
|
||||
|
||||
|
||||
done();
|
||||
|
||||
|
||||
};
|
||||
imageObj.src = 'assets/lion.png';
|
||||
|
||||
showHit(layer);
|
||||
|
||||
layer.hitCanvas._canvas.style.border='2px solid black';
|
||||
});
|
||||
|
||||
});
|
@ -105,14 +105,14 @@ suite('Blur', function() {
|
||||
|
||||
layer.draw();
|
||||
|
||||
//document.body.appendChild(group._cache.canvas.scene._canvas);
|
||||
//document.body.appendChild(group._cache.canvas.hit._canvas);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
showHit(layer);
|
||||
//showHit(layer);
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
|
@ -173,55 +173,6 @@ suite('Image', function(){
|
||||
imageObj.src = 'assets/darth-vader.jpg';
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
test('create image hit region', function(done) {
|
||||
var imageObj = new Image();
|
||||
|
||||
var stage = addStage();
|
||||
var layer = new Kinetic.Layer();
|
||||
|
||||
imageObj.onload = function() {
|
||||
|
||||
var lion = new Kinetic.Image({
|
||||
x: 200,
|
||||
y: 40,
|
||||
image: imageObj,
|
||||
draggable: true,
|
||||
shadowColor: 'black',
|
||||
shadowBlur: 10,
|
||||
shadowOffset: 20,
|
||||
shadowOpacity: 0.2
|
||||
});
|
||||
|
||||
// override color key with black
|
||||
lion.colorKey = '#000000';
|
||||
Kinetic.shapes['#000000'] = lion;
|
||||
|
||||
layer.add(lion);
|
||||
|
||||
lion.createImageHitRegion(function() {
|
||||
stage.add(layer);
|
||||
layer.drawHit();
|
||||
|
||||
var trace = layer.hitCanvas.getContext().getTrace();
|
||||
//console.log(trace);
|
||||
//assert.equal(trace, 'clearRect(0,0,578,200);save();transform(1,0,0,1,200,40);drawImage([object HTMLImageElement],0,0,144,139);beginPath();rect(0,0,144,139);closePath();restore();clearRect(0,0,578,200);save();transform(1,0,0,1,200,40);drawImage([object HTMLImageElement],0,0,144,139);beginPath();rect(0,0,144,139);closePath();restore();');
|
||||
|
||||
var hitTrace = layer.hitCanvas.getContext().getTrace();
|
||||
//console.log(hitTrace);
|
||||
//assert.equal(hitTrace, 'clearRect(0,0,578,200);save();transform(1,0,0,1,200,40);drawImage([object HTMLImageElement],0,0,144,139);beginPath();rect(0,0,144,139);closePath();restore();clearRect(0,0,578,200);save();transform(1,0,0,1,200,40);drawImage([object HTMLImageElement],0,0,144,139);beginPath();rect(0,0,144,139);closePath();restore();');
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
};
|
||||
imageObj.src = 'assets/lion.png';
|
||||
|
||||
showHit(layer);
|
||||
|
||||
layer.hitCanvas._canvas.style.border='2px solid black';
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
test('image with svg source', function(done) {
|
||||
var imageObj = new Image();
|
||||
|
Loading…
Reference in New Issue
Block a user