Copy link to clipboard
Copied
Hi,
I'm trying to recreate a page-turn in the HTML-5 canvas. This involves dragging the corner of a page across the canvas and revealing the page beneath. In order to this I have some javascript code
However! I don't seem to be able to make the lineSymbol movieclip into a mask?
I also have an issue with the dragger not aligning to the lineSymbol. However, this feels like an issue I can fix.
The main thing is making the lineSymbol a mask. If I mask it in Animate CC, the javascript can't find it????
Any help much appreciated, I've scoured the internet but not found anything as yet....
var pageWidth = this.bookPage.nominalBounds.width;
var pageLeft = this.bookPage.x;
var pageRight = this.bookPage.x + pageWidth;
var pageHeight = this.bookPage.nominalBounds.height;
var pageTop = this.bookPage.y;
var pageBottom = this.bookPage.y + pageHeight;
var lineSymbol = this.line
var dragger = this.dragger
dragger.on("pressmove", function (evt) {
//this means that the mouse position is responsive to the size of the canvas which scales according to the size of the browser window or if viewed on iPad/iPhone
var mousePosition = stage.globalToLocal(evt.stageX, evt.stageY);
evt.currentTarget.x = mousePosition.x
evt.currentTarget.y = mousePosition.y
//this makes x-coord of the line equal to that of the mouse
lineSymbol.x=evt.currentTarget.x
//this says if the line is dragged beyond the page edge, it stays at the page edge and if the line is dragged beyond the page spine, it stays at the page spine
if (lineSymbol.x > pageRight) {
lineSymbol.x = pageRight;
} else if (lineSymbol.x < pageLeft) {
lineSymbol.x = pageLeft;
}
//this says if the line is dragged above the page top, it stays at the top edge and if the line is dragged below the page bottom, it stays at the bottom
if (evt.currentTarget.y > pageBottom) {
evt.currentTarget.y = pageBottom;
} else if (evt.currentTarget.y < pageTop) {
evt.currentTarget.y = pageTop;
}
lineSymbol.x=evt.currentTarget.x
lineSymbol.rotation = 45 * ((lineSymbol.x - pageLeft) / pageWidth);
stage.update(); //much smoother because it refreshes the screen on pixel movement not frame
})
Thanks,
Rob
Okay had a breakthrough on this in case anyone either encounters same problem or is interested!
As previously mentioned I just want to be able to call a mask from the stage to the javascript I have in the actions panel.
However, annoyingly when I masked on the timeline, the javascript could no longer call the symbol (in my case a movieClip but button or graphic did the same).
The breakthrough today. I managed to work that Animate was outputting the mask in the javascript it exported on publish.
...Copy link to clipboard
Copied
there's a bug in animate. to resolve use code to assign the mask and remove the mask assignment on the timeline:
pageLeft.mask=lineSimbol;
Copy link to clipboard
Copied
Hi,
Thanks for the quick response and suggestion but couldn't get this to work. I tried it in flash and this worked fine but doesn't seem to want to turn my movieclip into a mask when it's a HTML5 Canvas? Not sure if it's actionscript specific?
Regards,
Rob
Copy link to clipboard
Copied
i had no problem using html5/canvas and assigning a mask using createjs as shown in message 1.
Copy link to clipboard
Copied
Masks in HTML5 Canvas can't be a symbol with changing frames in it. If you copy the frames from the mask symbol and paste them into the layer that the symbols was in (in other words, one level up from where they are now), then the mask should work.
Copy link to clipboard
Copied
kglad wrote
there's a bug in animate. to resolve use code to assign the mask and remove the mask assignment on the timeline:
It's not a bug, it's a deliberate—albeit unfortunate—optimization. As I just discovered, symbol masks get flattened into a sequence of graphic objects. For example, a spinning square mask becomes this in the published output:
(lib.maskname = function(mode,startPosition,loop) {
this.initialize(mode,startPosition,loop,{});
// mask (mask)
var mask = new cjs.Shape();
mask._off = true;
var mask_graphics_0 = new cjs.Graphics().p("A4XD/MAhRgicIbwazMghRAicg");
var mask_graphics_1 = new cjs.Graphics().p("A4OhJMAm0gbVIWBfQMgm0AbWg");
var mask_graphics_2 = new cjs.Graphics().p("A2dlmMAq5gTXMAPmAijMgq5ATXg");
var mask_graphics_3 = new cjs.Graphics().p("AzKpOMAtXgK2MAIuAkjMgtXAK1g");
var mask_graphics_4 = new cjs.Graphics().p("Aufr6MAuLgCFMABrAlNMguLACEg");
var mask_graphics_5 = new cjs.Graphics().p("AwlTpMAFUgkgMAtVAGmMgFUAkhg");
var mask_graphics_6 = new cjs.Graphics().p("AzwM8MAMAgiiMAq4AO4MgMAAijg");
var mask_graphics_7 = new cjs.Graphics().p("A1ZGdISH/YMAm9AWgIyIfXg");
...
The original symbol is entirely discarded.
Copy link to clipboard
Copied
i'm not sure what kind of optimization is realized by losing an object reference when any object (animate or not) is used as a timeline/ide-created mask. eg, if you use a timeline movieclip as a mask, that movieclip cannot be referenced in the actions panel.
Copy link to clipboard
Copied
Hi,
I think I understand what you're saying in that the mask can be assigned using pageLeft.mask=lineSymbol; (it's actually bookPage I want to assign mask to but for this purpose that makes sense).
However every time I publish it will not mask for me! Is it that it's a movieclip and I need to stop it being a movieclip or a symbol. But if that's the case how do I call the shape from the stage
Sorry if I'm being a bit stupid here, all this help is much appreciated.
Rob
Copy link to clipboard
Copied
you can use a movieclip as a mask. but if there's more than one keyframe in the mask layer, that could be a problem but there shouldn't be a need for that with a page-turn application.
Copy link to clipboard
Copied
Yep I don't have a keyframe in there.
I've done a really simple execution. Actions contains the script
var image = this.image;
var masker = this.maskObject;
image.mask=masker
mask layer is the pink circle and is just the movieclip maskObject
image layer is the landscape image which is a movieclip called image
And still when i publish it doesn't do any masking!
Can not for life of me figure out why it's still not masking.
Thanks,
Rob
Copy link to clipboard
Copied
either one of those references is incorrect, or you need to use
this.image.mask=this.maskObject;
Copy link to clipboard
Copied
Yep still no joy unfortunately. I had been playing around with image.mask=this.maskObject;
Could it be the version of Animate CC. I'm on 2015.2?
Really odd (and frustrating!)
Copy link to clipboard
Copied
Don't know if this will be a possible solution, but in CreateJS you do masks that have alpha channels in them, which you may not need, but perhaps the same code will do a better job:
EaselJS v0.8.2 API Documentation : AlphaMaskFilter
BTW, make sure your movieclip isn't doing cacheasbitmap, or have any filters applied.
Copy link to clipboard
Copied
now, i can't get it to work, and i'm not sure what did before but i know it was working and i know i had to be testing canvas because using test movie opened in my default browser and that only occurs when i'm testing canvas apps.
Copy link to clipboard
Copied
Add this to your code:
console.log(image);
console.log(masker);
Copy link to clipboard
Copied
Yep tried console.log to no avail. I did previously look at AlphaMaskFilter as a solution but I want to call an object from the stage (as a movieclip or otherwise) and never found a way to make that work.....
Copy link to clipboard
Copied
I have no idea how to interpret what "to no avail" means happened.
Copy link to clipboard
Copied
Sorry I mean it still hit the same problem. Code is updated as below but still hitting the same problem of it refusing to mask the image when I publish.
Code as it stands is:
var image = this.image;
var masker = lib.maskObject;
console.log(this.image);
console.log(this.masker);
image.mask=masker;
Copy link to clipboard
Copied
SIGH.
You're supposed to open the browser dev console and tell us what the console.log output is.
Copy link to clipboard
Copied
Sorry, was a javascript virgin about a month ago.....and thank you all for the help on this.
So the console is now outputting the below for the image but more intriguingly (and I suspect this may be where the problem is) it says undefined for the mask.
lib.image masking_problem.html:62
undefined masking_problem.html:63
Line 62 on the html is console.log(this.image);
Line 63 on the html is console.log(this.masker);
For the record lib.image opens up as follows but I suspect the problem is definitely with masker.
Copy link to clipboard
Copied
Wait sorry just realised why it's not defining this.masker. Masker is a variable, the stage object is MaskObject.
Here's the log for the image
And for the mask
Copy link to clipboard
Copied
Hi,
I've been trying to decode these logs. Still not found a solution.
However, I noticed that when the movieclip is masked properly (i.e. when I mask it on the timeline and publish) the mask for the movieclip is defined as 'a' which appears to be a rendering of my mask into a shape.
When I try to use javascript to call the mask, the movieclip assigns maskObject as the mask (seemingly correctly), this then contains an instance of 'a' - which is the rendering of the shape. Could it be that the mask won't work because the actual shape is nested within????
Again much help appreciated. Currently been stuck on this for 10 days and really can't for life of me figure out why this part is so difficult?
Rob
Copy link to clipboard
Copied
Hi,
Just checking the console logs were as expected?
Thanks,
Rob
Copy link to clipboard
Copied
kglad wrote
i'm not sure what kind of optimization is realized by losing an object reference when any object (animate or not) is used as a timeline/ide-created mask.
Speed optimization, obviously. Decomposing a potentially deeply nested object into the vector outline required for an HTML5 canvas clipping mask is probably an expensive operation.
Again, it's not "losing" an object reference, it's discarding the entire object.
Copy link to clipboard
Copied
Okay had a breakthrough on this in case anyone either encounters same problem or is interested!
As previously mentioned I just want to be able to call a mask from the stage to the javascript I have in the actions panel.
However, annoyingly when I masked on the timeline, the javascript could no longer call the symbol (in my case a movieClip but button or graphic did the same).
The breakthrough today. I managed to work that Animate was outputting the mask in the javascript it exported on publish. However it was using it's own variable instead of using the symbol name. And it was creating a variable called 'mask' to do this.
Example here:
// maskturn (mask)
var mask = new cjs.Shape();
mask._off = true;
mask.graphics.p("AjjF8QgtgcgognQiBiCAAi3QAAgoAHgmQAWiFBkhlQCCiBC2AAQC3AACBCBQBlBlAWCFQAHAmAAAoQAAC3iCCCQgoAngtAcQhlA+h+AAQh9AAhmg+g");
mask.setTransform(375.9,218.1);
So for every instant of the symbol I wanted to call in my JS code in actions I needed to call 'mask' not the name I had defined for it. For the record in the above code 'maskturn' was the name of the layer containing 'lineSymbol' which was the mask.
Anyway long story short, the following code fixed it. And if you need more than on mask on the timeline, Animate CC defines the first one it encounters (higher on timeline) as mask, and then mask_1, mask_2, etc.
var pageWidth = this.bookPage.nominalBounds.width;
var pageLeft = this.bookPage.x;
var pageRight = this.bookPage.x + pageWidth;
var pageHeight = this.bookPage.nominalBounds.height;
var pageTop = this.bookPage.y;
var pageBottom = this.bookPage.y + pageHeight;
//no longer needed var lineSymbol = this.line
var dragger = this.dragger
var bookPage = this.bookPage
var bookPage2 = this.bookPage2
dragger.on("pressmove", function (evt) {
//this means that the mouse position is responsive to the size of the canvas which scales according to the size of the browser window or if viewed on iPad/iPhone
var mousePosition = stage.globalToLocal(evt.stageX, evt.stageY);
evt.currentTarget.x = mousePosition.x
evt.currentTarget.y = mousePosition.y
//this makes x-coord of the line equal to that of the mouse
mask.x=evt.currentTarget.x
//this says if the line is dragged beyond the page edge, it stays at the page edge and if the line is dragged beyond the page spine, it stays at the page spine
if (mask.x > pageRight) {
mask.x = pageRight;
} else if (mask.x < pageLeft) {
mask.x = pageLeft;
}
//this says if the line is dragged above the page top, it stays at the top edge and if the line is dragged below the page bottom, it stays at the bottom
if (evt.currentTarget.y > pageBottom) {
evt.currentTarget.y = pageBottom;
} else if (evt.currentTarget.y < pageTop) {
evt.currentTarget.y = pageTop;
}
mask.x=evt.currentTarget.x
mask.rotation = 45 * ((mask.x - pageLeft) / pageWidth);
stage.update(); //much smoother because it refreshes the screen on pixel movement not frame
})