Как добавить режим смешивания 'screen' к элементу canvas? - PullRequest
0 голосов
/ 23 мая 2018

У меня есть анимация html5, которая использует два изображения.Во-первых, JPG женщины.Второй - это градиент jpg, который расположен над женщиной и анимируется над ней.

Я хочу, чтобы изображение градиента было с непрозрачностью 50% и иметь свойство CSS mix-blend-mode как «screen».

Это прекрасно работает в Версия A1 (созданная с помощью Google Web Designer).См. Версию A1 здесь .

Это не работает в Версия B1 (созданная с помощью Adobe Animate CC).Градиент имеет непрозрачность 50%, но не имеет режима наложения «экран», потому что графический интерфейс Animate CC не поддерживает режим наложения «экран».См. Версию B1 здесь .

Я хочу, чтобы версия B1 была похожа на версию A1.Я не смог настроить код для достижения этой цели.У кого-нибудь есть идея?

Загрузите html и файлы изображений здесь: Скачать .

<html>
<head>
<meta charset="UTF-8">
<meta name="authoring-tool" content="Adobe_Animate_CC">
<title>index</title>
<!-- write your code here -->
<script src="https://code.createjs.com/createjs-2015.11.26.min.js"></script>
<script>
(function (cjs, an) {
var p; // shortcut to reference prototypes
var lib={};var ss={};var img={};
lib.ssMetadata = [];
// symbols:
(lib.gradient = function() {
    this.initialize(img.gradient);
}).prototype = p = new cjs.Bitmap();
p.nominalBounds = new cjs.Rectangle(0,0,1070,1339);
(lib.photo = function() {
    this.initialize(img.photo);
}).prototype = p = new cjs.Bitmap();
p.nominalBounds = new cjs.Rectangle(0,0,300,600);// helper functions:
function mc_symbol_clone() {
    var clone = this._cloneProps(new this.constructor(this.mode, this.startPosition, this.loop));
    clone.gotoAndStop(this.currentFrame);
    clone.paused = this.paused;
    clone.framerate = this.framerate;
    return clone;
}
function getMCSymbolPrototype(symbol, nominalBounds, frameBounds) {
    var prototype = cjs.extend(symbol, cjs.MovieClip);
    prototype.clone = mc_symbol_clone;
    prototype.nominalBounds = nominalBounds;
    prototype.frameBounds = frameBounds;
    return prototype;
    }
(lib.PHOTO = function(mode,startPosition,loop) {
    this.initialize(mode,startPosition,loop,{});
    // Layer_1
    this.instance = new lib.photo();
    this.instance.parent = this;
    this.timeline.addTween(cjs.Tween.get(this.instance).wait(1));
}).prototype = getMCSymbolPrototype(lib.PHOTO, new cjs.Rectangle(0,0,300,600), null);
(lib.hotspot = function(mode,startPosition,loop) {
    this.initialize(mode,startPosition,loop,{});
    // Layer 1
    this.shape = new cjs.Shape();
    this.shape.graphics.f("rgba(65,65,65,0.008)").s().p("EgXbAu4MAAAhdvMAu3AAAMAAABdvg");
    this.shape.setTransform(150,300);
    this.timeline.addTween(cjs.Tween.get(this.shape).wait(4));
}).prototype = p = new cjs.MovieClip();
p.nominalBounds = new cjs.Rectangle(0,0,300,600);
(lib.GRADIENT = function(mode,startPosition,loop) {
    this.initialize(mode,startPosition,loop,{});
    // Layer_1
    this.instance = new lib.gradient();
    this.instance.parent = this;
    this.timeline.addTween(cjs.Tween.get(this.instance).wait(1));
}).prototype = getMCSymbolPrototype(lib.GRADIENT, new cjs.Rectangle(0,0,1070,1339), null);
// stage content:
(lib.index = function(mode,startPosition,loop) {
    this.initialize(mode,startPosition,loop,{});
    // timeline functions:
    this.frame_0 = function() {
        this.hotspot.addEventListener("click", fl_MouseClickHandler.bind(this));
        function fl_MouseClickHandler()
        {
            //Start your custom code here for when the ad is clicked.
            window.open(window.clickTag);
        }
    }
    this.frame_92 = function() {
        this.stop();
    }
    // actions tween:
    this.timeline.addTween(cjs.Tween.get(this).call(this.frame_0).wait(92).call(this.frame_92).wait(1));
    // hotspot
    this.hotspot = new lib.hotspot();
    this.hotspot.name = "hotspot";
    this.hotspot.parent = this;
    this.hotspot.setTransform(150,125,1,1,0,0,0,150,125);
    new cjs.ButtonHelper(this.hotspot, 0, 1, 2, false, new lib.hotspot(), 3);
    this.timeline.addTween(cjs.Tween.get(this.hotspot).wait(93));
    // GRADIENT
    this.instance = new lib.GRADIENT();
    this.instance.parent = this;
    this.instance.setTransform(535,669.5,1,1,0,0,0,535,669.5);
    this.instance.alpha = 0.5;
    this.timeline.addTween(cjs.Tween.get(this.instance).to({x:-235,y:-69.5},89,cjs.Ease.quartInOut).wait(4));
    // PHOTO
    this.instance_1 = new lib.PHOTO();
    this.instance_1.parent = this;
    this.instance_1.setTransform(150,300,1,1,0,0,0,150,300);
    this.timeline.addTween(cjs.Tween.get(this.instance_1).wait(93));
}).prototype = p = new cjs.MovieClip();
p.nominalBounds = new cjs.Rectangle(150,300,1070,1339);
// library properties:
lib.properties = {
    id: '81B93427D538447FB1884A97C84A1343',
    width: 300,
    height: 600,
    fps: 30,
    color: "#FFFFFF",
    opacity: 1.00,
    manifest: [
        {src:"images/gradient.jpg", id:"gradient"},
        {src:"images/photo.jpg", id:"photo"}
    ],
    preloads: []
};
// bootstrap callback support:
(lib.Stage = function(canvas) {
    createjs.Stage.call(this, canvas);
}).prototype = p = new createjs.Stage();
p.setAutoPlay = function(autoPlay) {
    this.tickEnabled = autoPlay;
}
p.play = function() { this.tickEnabled = true; this.getChildAt(0).gotoAndPlay(this.getTimelinePosition()) }
p.stop = function(ms) { if(ms) this.seek(ms); this.tickEnabled = false; }
p.seek = function(ms) { this.tickEnabled = true; this.getChildAt(0).gotoAndStop(lib.properties.fps * ms / 1000); }
p.getDuration = function() { return this.getChildAt(0).totalFrames / lib.properties.fps * 1000; }
p.getTimelinePosition = function() { return this.getChildAt(0).currentFrame / lib.properties.fps * 1000; }
an.bootcompsLoaded = an.bootcompsLoaded || [];
if(!an.bootstrapListeners) {
    an.bootstrapListeners=[];
}
an.bootstrapCallback=function(fnCallback) {
    an.bootstrapListeners.push(fnCallback);
    if(an.bootcompsLoaded.length > 0) {
        for(var i=0; i<an.bootcompsLoaded.length; ++i) {
            fnCallback(an.bootcompsLoaded[i]);
        }
    }
};
an.compositions = an.compositions || {};
an.compositions['81B93427D538447FB1884A97C84A1343'] = {
    getStage: function() { return exportRoot.getStage(); },
    getLibrary: function() { return lib; },
    getSpriteSheet: function() { return ss; },
    getImages: function() { return img; }
};
an.compositionLoaded = function(id) {
    an.bootcompsLoaded.push(id);
    for(var j=0; j<an.bootstrapListeners.length; j++) {
        an.bootstrapListeners[j](id);
    }
}
an.getComposition = function(id) {
    return an.compositions[id];
}
})(createjs = createjs||{}, AdobeAn = AdobeAn||{});
var createjs, AdobeAn;
</script>
<script>
var canvas, stage, exportRoot, anim_container, dom_overlay_container, fnStartAnimation;
function init() {
    canvas = document.getElementById("canvas");
    anim_container = document.getElementById("animation_container");
    dom_overlay_container = document.getElementById("dom_overlay_container");
    var comp=AdobeAn.getComposition("81B93427D538447FB1884A97C84A1343");
    var lib=comp.getLibrary();
    var loader = new createjs.LoadQueue(false);
    loader.addEventListener("fileload", function(evt){handleFileLoad(evt,comp)});
    loader.addEventListener("complete", function(evt){handleComplete(evt,comp)});
    var lib=comp.getLibrary();
    loader.loadManifest(lib.properties.manifest);
}
function handleFileLoad(evt, comp) {
    var images=comp.getImages();    
    if (evt && (evt.item.type == "image")) { images[evt.item.id] = evt.result; }    
}
function handleComplete(evt,comp) {
    //This function is always called, irrespective of the content. You can use the variable "stage" after it is created in token create_stage.
    var lib=comp.getLibrary();
    var ss=comp.getSpriteSheet();
    var queue = evt.target;
    var ssMetadata = lib.ssMetadata;
    for(i=0; i<ssMetadata.length; i++) {
        ss[ssMetadata[i].name] = new createjs.SpriteSheet( {"images": [queue.getResult(ssMetadata[i].name)], "frames": ssMetadata[i].frames} )
    }
    exportRoot = new lib.index();
    stage = new lib.Stage(canvas);
    stage.enableMouseOver();    
    //Registers the "tick" event listener.
    fnStartAnimation = function() {
        stage.addChild(exportRoot);
        createjs.Ticker.setFPS(lib.properties.fps);
        createjs.Ticker.addEventListener("tick", stage);
    }       
    //Code to support hidpi screens and responsive scaling.
    function makeResponsive(isResp, respDim, isScale, scaleType) {      
        var lastW, lastH, lastS=1;      
        window.addEventListener('resize', resizeCanvas);        
        resizeCanvas();     
        function resizeCanvas() {           
            var w = lib.properties.width, h = lib.properties.height;            
            var iw = window.innerWidth, ih=window.innerHeight;          
            var pRatio = window.devicePixelRatio || 1, xRatio=iw/w, yRatio=ih/h, sRatio=1;          
            if(isResp) {                
                if((respDim=='width'&&lastW==iw) || (respDim=='height'&&lastH==ih)) {                    
                    sRatio = lastS;                
                }               
                else if(!isScale) {                 
                    if(iw<w || ih<h)                        
                        sRatio = Math.min(xRatio, yRatio);              
                }               
                else if(scaleType==1) {                 
                    sRatio = Math.min(xRatio, yRatio);              
                }               
                else if(scaleType==2) {                 
                    sRatio = Math.max(xRatio, yRatio);              
                }           
            }           
            canvas.width = w*pRatio*sRatio;         
            canvas.height = h*pRatio*sRatio;
            canvas.style.width = dom_overlay_container.style.width = anim_container.style.width =  w*sRatio+'px';               
            canvas.style.height = anim_container.style.height = dom_overlay_container.style.height = h*sRatio+'px';
            stage.scaleX = pRatio*sRatio;           
            stage.scaleY = pRatio*sRatio;           
            lastW = iw; lastH = ih; lastS = sRatio;            
            stage.tickOnUpdate = false;            
            stage.update();            
            stage.tickOnUpdate = true;      
        }
    }
    makeResponsive(false,'both',false,1);   
    AdobeAn.compositionLoaded(lib.properties.id);
    fnStartAnimation();
}
</script>
<!-- write your code here -->
</head>
<body onload="init();" style="margin:0px;">
    <div id="animation_container" style="background-color:rgba(255, 255, 255, 1.00); width:300px; height:600px">
        <canvas id="canvas" width="300" height="600" style="position: absolute; display: block; background-color:rgba(255, 255, 255, 1.00);"></canvas>
        <div id="dom_overlay_container" style="pointer-events:none; overflow:hidden; width:300px; height:600px; position: absolute; left: 0px; top: 0px; display: block;">
        </div>
    </div>
</body>
</html>

1 Ответ

0 голосов
/ 23 мая 2018

Animate использует EaselJS, который поддерживает HTML Canvas globalCompositeOperation, который имеет как пиксельные составные операции, так и типичные режимы наложения, включая «экран».

Поскольку в настоящее время нетПоддержка анимации в IDE (пока мы надеемся на поддержку в будущем), вам нужно будет определить, какой клип в вашей библиотеке вы хотите использовать в этом режиме наложения, и установить его самостоятельно.

Например, если это экземпляр PHOTO (который содержит растровое изображение photo), вы можете установить режим наложения на instance:

(lib.PHOTO = function(mode,startPosition,loop) {
    this.initialize(mode,startPosition,loop,{});
    // Layer_1
    this.instance = new lib.photo();
    this.instance.compositeOperation = "screen"; // <------------------- there
    this.instance.parent = this;
    this.timeline.addTween(cjs.Tween.get(this.instance).wait(1));
}).prototype = getMCSymbolPrototype(lib.PHOTO, new cjs.Rectangle(0,0,300,600), null);

Или, если вы хотитеустановить его на весь клип PHOTO на главной временной шкале (это ваша сцена / exportRoot), вы можете настроить таргетинг на instance_1:

// PHOTO
this.instance_1 = new lib.PHOTO();
this.instance_1.compositeOperation = "screen";

Надеюсь, вы поняли идею.К сожалению, он будет перезаписан при повторном экспорте.Вы можете отключить обновление html в настройках и установить его вручную в HTML-коде:

// Find this:
exportRoot = new lib.index();
// And dig in yourself:
exportRoot.instance_1.compositeOperation = "screen";

Надеюсь, это поможет!

...