如何将'screen'混合模式添加到canvas元素?

时间:2018-05-22 23:09:05

标签: css animation canvas adobe mix-blend-mode

我有一个使用两个图像的html5动画。第一个是一个女人的jpg。第二个是一个渐变的jpg,它位于女人的上方,并在她身上动画。

我希望渐变图像的透明度为50%,并将CSS mix-blend-mode属性设置为“screen”。

版本A1 <使用Google Web Designer创建 。见版本A1 Java allows

版本B1 <使用Adobe Animate CC创建 。渐变为50%不透明度,但没有“屏幕”混合模式,因为Animate CC的gui不支持“屏幕”混合模式。见版本B1 here

我希望版本B1看起来像版本A1。我无法调整代码来实现这一目标。有人有想法吗?

在此处下载html和图片文件:here

<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 :(得分:0)

Animate使用EaselJS,它支持HTML Canvas globalCompositeOperation,它既有像素复合操作,也有典型的混合模式,包括&#34; screen&#34;。

由于IDE中目前没有Animate支持(但我们希望将来支持),您必须确定库中哪个剪辑要具有该混合模式,并自行设置。

例如,如果是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);

或者,如果您想在主时间轴(您的舞台/ exportRoot)上的整个PHOTO剪辑上进行设置,您可以定位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";

希望有所帮助!