Skip to main content
Inspiring
August 22, 2023
Answered

Simulate a "Scratch-book" effect on hover in a animate HTML5 canvas project

  • August 22, 2023
  • 1 reply
  • 750 views

Has anybody got a scratchbook style reval animation, (on hover) working in a adobe animate html canvas project?

 

Different form the example below: using x2 different images (one on top of the other), on hover,  hide the top image to reveal the image below.

 

Similar excample: https://createjs.com/demos/easeljs/alphamaskreveal

 

Any help to get started on this, much appriciated 🙂

Correct answer JoãoCésar17023019

Hi.

 

Please grab the files in the link below:

https://github.com/joao-cesar/adobe/tree/master/animate%20cc/html5_canvas/scratch

 

Then replace all the code in the main timeline by this one:

var root = this;
var minProgressToReveal = 0.9; // minimum mask area that needs to be cleared to reveal what is behind
var cursorType = "default";
var strokeTickness = 48;
var strokeCaps = "round";
var strokeJoints = "round";
var strokeColor = "rgba(0,0,0,1)"; // change the 4th argument for the stroke density
var mkContainer = root.scratchable; // mask container instance
var cursor = root.cursor; // cursor instance
var friction = 0.8; // cursor friction
var scratchable, mkBounds, grid, oldPt, oldMidPt, maskFilter;

root.start = function()
{
	var stageX, stageY;
	
	createjs.Touch.enable(stage);
	stage.enableMouseOver();
	stage.mouseMoveOutside = true;
	document.body.style.backgroundColor = "black";
	grid = {};
	scratchable = mkContainer.children[0];
	mkBounds = root.scratchable.nominalBounds;
	scratchable.cache(-mkBounds.width * 0.5, -mkBounds.height * 0.5, mkBounds.width, mkBounds.height);
	maskFilter = new createjs.AlphaMaskFilter(scratchable.cacheCanvas);
	scratchable.cursor = cursorType;
	stageX = ((stage.mouseX / stage.scaleX) - mkBounds.width * 0.5);
	stageY = ((stage.mouseY / stage.scaleY) - mkBounds.height * 0.5);
	oldPt = new createjs.Point(stageX, stageY);
	oldMidPt = oldPt;
	root.stop();
	root.tick = createjs.Ticker.on("tick", root.tickHandler);
}

root.tickHandler = function(event)
{
	var stageX = stage.mouseX / stage.scaleX;
	var stageY = stage.mouseY / stage.scaleY;
	var midPoint;
	
	cursor.rotation = root.rotateToCursor(stageY - cursor.y, stageX - cursor.x);
	cursor.x = root.lerp(cursor.x, stageX, friction);
	cursor.y = root.lerp(cursor.y, stageY, friction);
	
	stageX -= mkBounds.width * 0.5;
	stageY -= mkBounds.height * 0.5;	
	midPoint = new createjs.Point(oldPt.x + stageX >> 1, oldPt.y + stageY >> 1);
	root.trackProgress(midPoint);

	scratchable.graphics.clear()
		.setStrokeStyle(strokeTickness, strokeCaps, strokeJoints)
		.beginStroke(strokeColor)
		.moveTo(midPoint.x, midPoint.y)
		.curveTo(oldPt.x, oldPt.y, oldMidPt.x, oldMidPt.y);
	
	oldPt.x = stageX;
	oldPt.y = stageY;

	oldMidPt.x = midPoint.x;
	oldMidPt.y = midPoint.y;

	scratchable.updateCache("destination-out");
}

root.trackProgress = function(point)
{
	var columns = Math.round(mkBounds.width / strokeTickness) + 1;
	var rows = Math.round(mkBounds.height / strokeTickness) + 1;
	var total = columns * rows;
	var gridX = Math.round((point.x + mkBounds.width * 0.5) / strokeTickness);
	var gridY = Math.round((point.y + mkBounds.height * 0.5) / strokeTickness);
	
	grid[gridX + "_" + gridY] = true;
	
	if (Object.keys(grid).length >= Math.round(total * minProgressToReveal))
		root.revealCallback();	
}

root.revealCallback = function()
{	
	createjs.Tween.get(scratchable).to({ alpha: 0 }, 500).call(function()
	{
		scratchable.visible = false;
	});
	
	createjs.Tween.get(cursor).to({ alpha: 0 }, 500).call(function()
	{
		cursor.visible = false;
	});	
	
	createjs.Ticker.off("tick", root.tick);
}

root.lerp = function(v1, v2, f)
{
	 return f * v1 + (1 - f) * v2;
};

root.rotateToCursor = function(distY, distX)
{
	return Math.atan2(distY, distX) * 180 / Math.PI;
};

root.start();

 

I hope this helps.

 

Regards,

JC

1 reply

JoãoCésar17023019
JoãoCésar17023019Correct answer
Community Expert
August 22, 2023

Hi.

 

Please grab the files in the link below:

https://github.com/joao-cesar/adobe/tree/master/animate%20cc/html5_canvas/scratch

 

Then replace all the code in the main timeline by this one:

var root = this;
var minProgressToReveal = 0.9; // minimum mask area that needs to be cleared to reveal what is behind
var cursorType = "default";
var strokeTickness = 48;
var strokeCaps = "round";
var strokeJoints = "round";
var strokeColor = "rgba(0,0,0,1)"; // change the 4th argument for the stroke density
var mkContainer = root.scratchable; // mask container instance
var cursor = root.cursor; // cursor instance
var friction = 0.8; // cursor friction
var scratchable, mkBounds, grid, oldPt, oldMidPt, maskFilter;

root.start = function()
{
	var stageX, stageY;
	
	createjs.Touch.enable(stage);
	stage.enableMouseOver();
	stage.mouseMoveOutside = true;
	document.body.style.backgroundColor = "black";
	grid = {};
	scratchable = mkContainer.children[0];
	mkBounds = root.scratchable.nominalBounds;
	scratchable.cache(-mkBounds.width * 0.5, -mkBounds.height * 0.5, mkBounds.width, mkBounds.height);
	maskFilter = new createjs.AlphaMaskFilter(scratchable.cacheCanvas);
	scratchable.cursor = cursorType;
	stageX = ((stage.mouseX / stage.scaleX) - mkBounds.width * 0.5);
	stageY = ((stage.mouseY / stage.scaleY) - mkBounds.height * 0.5);
	oldPt = new createjs.Point(stageX, stageY);
	oldMidPt = oldPt;
	root.stop();
	root.tick = createjs.Ticker.on("tick", root.tickHandler);
}

root.tickHandler = function(event)
{
	var stageX = stage.mouseX / stage.scaleX;
	var stageY = stage.mouseY / stage.scaleY;
	var midPoint;
	
	cursor.rotation = root.rotateToCursor(stageY - cursor.y, stageX - cursor.x);
	cursor.x = root.lerp(cursor.x, stageX, friction);
	cursor.y = root.lerp(cursor.y, stageY, friction);
	
	stageX -= mkBounds.width * 0.5;
	stageY -= mkBounds.height * 0.5;	
	midPoint = new createjs.Point(oldPt.x + stageX >> 1, oldPt.y + stageY >> 1);
	root.trackProgress(midPoint);

	scratchable.graphics.clear()
		.setStrokeStyle(strokeTickness, strokeCaps, strokeJoints)
		.beginStroke(strokeColor)
		.moveTo(midPoint.x, midPoint.y)
		.curveTo(oldPt.x, oldPt.y, oldMidPt.x, oldMidPt.y);
	
	oldPt.x = stageX;
	oldPt.y = stageY;

	oldMidPt.x = midPoint.x;
	oldMidPt.y = midPoint.y;

	scratchable.updateCache("destination-out");
}

root.trackProgress = function(point)
{
	var columns = Math.round(mkBounds.width / strokeTickness) + 1;
	var rows = Math.round(mkBounds.height / strokeTickness) + 1;
	var total = columns * rows;
	var gridX = Math.round((point.x + mkBounds.width * 0.5) / strokeTickness);
	var gridY = Math.round((point.y + mkBounds.height * 0.5) / strokeTickness);
	
	grid[gridX + "_" + gridY] = true;
	
	if (Object.keys(grid).length >= Math.round(total * minProgressToReveal))
		root.revealCallback();	
}

root.revealCallback = function()
{	
	createjs.Tween.get(scratchable).to({ alpha: 0 }, 500).call(function()
	{
		scratchable.visible = false;
	});
	
	createjs.Tween.get(cursor).to({ alpha: 0 }, 500).call(function()
	{
		cursor.visible = false;
	});	
	
	createjs.Ticker.off("tick", root.tick);
}

root.lerp = function(v1, v2, f)
{
	 return f * v1 + (1 - f) * v2;
};

root.rotateToCursor = function(distY, distX)
{
	return Math.atan2(distY, distX) * 180 / Math.PI;
};

root.start();

 

I hope this helps.

 

Regards,

JC

Inspiring
August 22, 2023

Thanks amazing! just what i was after.

JoãoCésar17023019
Community Expert
August 22, 2023

Great! You're welcome!