Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Прозрачность слоёв canvas (https://javascript.ru/forum/dom-window/82761-prozrachnost-slojov-canvas.html)

Янковиц 29.06.2021 14:51

Прозрачность слоёв canvas
 
Использую небольшую библиотечку для задания слоёв в canvas. Привожу полный код.
<html>
<head>
	<title>layeredCanvas Example</title>
</head>
<body>
	<canvas id="theCanvas" width="512" height="512"></canvas>

	<script>
	/*
	layeredCanvas v0.1

	by Federico Jacobi
	federicojacobi.com

	Abstraction layer on canvas to mimic the use of layers
	*/

	layeredCanvas = function ( id ) {
		this.layers = [];
		
		var extend = function ( defaults, options ) {
			var extended = {} , prop;
			for (prop in defaults) {
				if (Object.prototype.hasOwnProperty.call(defaults, prop))
					extended[prop] = defaults[prop];
			}
			for (prop in options) {
				if (Object.prototype.hasOwnProperty.call(options, prop))
					extended[prop] = options[prop];
			}
			return extended;
		};

		this.addLayer = function( obj ) {

			layer = extend( {
				id: Math.random().toString(36).substr(2, 5),
				show: true,
				render: function( canvas, ctx ) {}
			}, obj );

			if ( this.getLayer( layer.id ) !== false ) {
				console.log( 'Layer already exists' );
				console.log( obj );
				return false;
			}
			
			this.layers.push( layer );
			return this;
		};
		
		this.getLayer = function( id ) {
			var length = this.layers.length;
			for ( var i = 0; i < length; i++ ) {
				if ( this.layers[i].id === id )
					return this.layers[i];
			}
			return false;
		};
		
		this.removeLayer = function( id ) {
			var length = this.layers.length;
			for ( var i = 0; i < length; i++ ) {
				if ( this.layers[i].id === id ) {
					removed = this.layers[i];
					this.layers.splice( i, 1 );
					return removed;
				}
			}
			return false;
		};
		
		this.render = function() {
			var canvas = this.canvas;
			var ctx = this.ctx2d;
			this.layers.forEach( function( item, index, array ) {
				if ( item.show )
					item.render( canvas, ctx );
			});
		};
		
		this.canvas = document.getElementById( id );
		this.ctx2d = this.canvas.getContext( '2d' );
	};
	
	window.addEventListener( 'load', function() {
		var myCanvas = new layeredCanvas( "theCanvas" );

		myCanvas.addLayer( {
			id: 'background',
			render: function( canvas, ctx ) {
				ctx.fillStyle = "black";
				ctx.fillRect( 0, 0, canvas.width, canvas.height );
			}
		})
		.addLayer( {
			id: 'squares',
			render: function( canvas, ctx ) {
				ctx.globalAlpha = opacity;

				ctx.fillStyle = "#E5E059";
				ctx.fillRect( 50, 50, 150, 150 );

				ctx.fillStyle = "#BDD358";
				ctx.fillRect( 350, 75, 150, 150 );

				ctx.fillStyle = "#E5625E";
				ctx.fillRect( 50, 250, 100, 250 );
			}
		});

		var opacity = 1;
		var fadeEffect = setInterval( function () {
			if ( opacity > 0 ) {
				opacity -= 0.0125;
			} else {
				clearInterval( fadeEffect );
				opacity = 0;
			}
			console.log(opacity)
			myCanvas.render();
		}, 10 );
	});
	</script>
</body>
</html>


Проблема в том, что хотя параметр ctx.globalAlpha достигает 0 в функции setInterval, полной прозрачности добиться не получается, второй слой полупрозрачный. Но если, ctx.globalAlpha задать не через переменную, а напрямую, то слой получает полную прозрачность. Подскажите, как решить эту проблему?

Строки 18-84 - функция работы со слоями
строки 112-122 - плавное изменение прозрачности

Янковиц 29.06.2021 16:34

В общем решил так:
добавил ещё один слой и стало работать:
.addLayer( {
				id: 'fullopacity',
				render: function( canvas, ctx ) {
					ctx.globalAlpha = 1;
				}
			} )

Rise 29.06.2021 17:48

Янковиц, у тебя 'background' тоже прозрачный, альфа то общая, поэтому все прошлые отрисовки просвечивают, а еще в интервале opacity в минус уходит.

myCanvas.addLayer({
    id: 'background',
    render: function(canvas, ctx) {
        ctx.globalAlpha = 1;
        ctx.fillStyle = 'black';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
    }
})

var opacity = 1;
var fadeEffect = setInterval(function () {
    opacity = Math.max(0, opacity - 0.0125);
    if (opacity == 0) clearInterval(fadeEffect);
    console.log(opacity);
    myCanvas.render();
}, 10);


Часовой пояс GMT +3, время: 10:12.