Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to apply a clipping artefact to a specific image artefact only? (Question) #22

Closed
Sjoerd82 opened this issue May 13, 2022 · 2 comments

Comments

@Sjoerd82
Copy link

The demo's do sometimes a bit too much, which makes it a little more difficult to disect the information you're trying to learn form them. However, after working with it for a few hours and reading through the tutorials I came very close to my goals, and must say that it's a very capable library, although I have no experience with other similar ones, I am absolutely very happy choosing this one for my little project.

There is however one thing that I have so far not been able to figure out, and that is how to apply clipping to only certain artefacts (and probably by extension, grouping, as I have a feeling it might be accomplished through groups). This screenshot shows the issue, there are two images, a background (the person in the suit) and a foreground (the ring which is a transparent png, with some shading on the inside of the ring. Then there is a third artefact, a wheel-clip, which I want to ONLY apply to the background image.

image

I have been playing around with order and groups, but have been so far unsuccesful.

At the end of the 'struggle', this was the code producing the screenshot above (as you may notice there are is a variable scale and postioning, which I took from the Pan&Zoom example ;-) ):

            this.canvas = scrawl.getCanvas('#mycanvas')
            let base = this.canvas.base,
                baseGroup = scrawl.library.group[base.name];

            let naturalWidth = document.getElementById("subjectImg").naturalWidth
            let naturalHeight = document.getElementById("subjectImg").naturalHeight
            let maxScale = (naturalHeight / this.frameDimension)
            if (!this.currentScale) {
                this.currentScale = maxScale
            }
            let minScale = 1
            let fromLeft = 0
            let fromTop = 0

            this.canvas.set({
                width: this.frameDimension,
                height: this.frameDimension,
                checkForResize: true,               // ?
                baseMatchesCanvasDimensions: true,  // ?
                isComponent: true,                  // ??
            }).setAsCurrentCanvas();

            // Ring
            this.tokenRing = scrawl.makePicture({
                name: `token-image`,
                imageSource: `/../img/ring.png`,
                width: '100%',
                height: '100%',
                copyWidth: '100%',
                copyHeight: '100%',
                order:2,
            });

            // Subject
            let tokenSubject = scrawl.makePicture({
                name: 'token-subject',
                imageSource: `/../img/background.png`,
                width: '100%',
                height: '100%',
                copyWidth: this.currentScale * this.frameDimension,
                copyHeight: this.currentScale * this.frameDimension,
                copyStartX: fromLeft,
                copyStartY: fromTop,
                filter: 'drop-shadow(2px 2px 2px #000000)',
                order: 1,
            });

            scrawl.makeWheel({
                name: 'wheel-clip',
                //radius: 257,
                radius: 270,
                startAngle: 0,
                endAngle: 360,
                includeCenter: true,
                startX: 279,
                startY: 279,
                handle: ['center', 'center'],
                method: 'clip',
                order: 3,
            })

            scrawl.makeRender({
                name: "demo-animation",
                target: this.canvas,
            });
@KaliedaRik
Copy link
Owner

There's a few of ways you can do this. The simplest is probably to use the globalCompositeOperation attribute.

(Note that you don't need to include default values when defining the entitys)

scrawl.makeWheel({
    name: 'wheel-clip',
    radius: 270,
    startX: 279,
    startY: 279,
    handle: ['center', 'center'],
    order: 0,
})

let tokenSubject = scrawl.makePicture({
    name: 'token-subject',
    imageSource: `/../img/background.png`,
    width: '100%',
    height: '100%',
    copyWidth: this.currentScale * this.frameDimension,
    copyHeight: this.currentScale * this.frameDimension,
    copyStartX: fromLeft,
    copyStartY: fromTop,
    filter: 'drop-shadow(2px 2px 2px #000000)',
    order: 1,
    globalCompositeOperation: 'source-in', // or possibly 'source-atop'[1]
});

this.tokenRing = scrawl.makePicture({
    name: `token-image`,
    imageSource: `/../img/ring.png`,
    width: '100%',
    height: '100%',
    copyWidth: '100%',
    copyHeight: '100%',
    order:2,
});

[1] - you can get an idea of GCO effects in demo canvas028 - https://scrawl-v8.rikweb.org.uk/demo/canvas-028.html

An alternative is to use a group to do the clipping for you - see demo canvas-042 for examples - https://scrawl-v8.rikweb.org.uk/demo/canvas-042.html

The group approach works by putting all the entitys into the same group. The wheel-clip entity should be applied first (with method: 'clip' attribute), followed by the other entitys.

@Sjoerd82
Copy link
Author

Struggled until I saw that the wheel is not a clip! Thanks, this works great. For those reading this and having a similar problem, I can add to this topic that the difference between globalCompositeOperation: 'source-in' and globalCompositeOperation: 'source-atop' is:

image

In this scenario there is only a difference if the image has transparency. In that case effectively, when using source-in, the transparancy "overwrites" the fill color of the wheel. Using 'source-atop', the transparancy is actually transparent, revealing the fill color of the underlying wheel.

            scrawl.makeWheel({
                name: 'wheel-clip',
                radius: 270,
                includeCenter: true,
                startX: 279,
                startY: 279,
                handle: ['center', 'center'],
                fillStyle: "yellow",
                order: 0,
            })

            let tokenSubject = scrawl.makePicture({
                name: 'token-subject',
                imageSource: 'image.png',
                width: '100%',
                height: '100%',
                filter: 'drop-shadow(2px 2px 2px #000000)',
                order: 1,
                globalCompositeOperation: 'source-in', // 'source-atop' (choose your poison)
            });

This solves this problem, closing the "issue".

Repository owner locked and limited conversation to collaborators May 14, 2022
@KaliedaRik KaliedaRik converted this issue into discussion #24 May 14, 2022

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants