Skip to content
Snippets Groups Projects
Select Git revision
  • 07a873702a303d8ccfd028e8279df5bd3b993580
  • master default protected
2 results

bottom-slogan-gradient-vertical-logo.js

Blame
  • bottom-slogan-gradient-vertical-logo.js 19.33 KiB
    class BottomSloganGradientVerticalLogo extends Template {
    	description = "Určeno pro sociální sítě. <span style=\"color:red\">Pozor, některé koalice nemají vertikální logo!</span>";
    	
    	changeableAttributes = [
    		"verticalLogoImage",
    		"primaryImage",
    		"primaryImagePosition",
    		"primaryColorScheme",
    		"primaryText",
    		"nameText"
    	];
    
    	primaryColorSchemes = [
    		"black-on-white",
    		"white-on-black"
    	];
    
    	// Colors
    	changeableColors = [
    		"backgroundGradientColor1",
    		"foregroundColor",
    		"primaryTextColor",
    		"nameBackgroundColor",
    		"nameTextColor"
    	];
    	
    	lightLogoDefaultSource = "static/images/vertical-logos/default-light.png";
    	darkLogoDefaultSource = "static/images/vertical-logos/default-dark.png";
    	
    	// Canvas
    	async redrawCanvas() {
    		if (this.redrawing) {
    			return;
    		}
    		
    		this.redrawing = true;
    		
    		// Background rectangle
    		let backgroundRectangleHeight = Math.ceil(this.canvas.height * 0.35);
    		
    		// Foreground rectangle
    		const foregroundRectangleOffsetSides = Math.ceil(this.canvas.width * 0.1);
    		const foregroundRectanglePaddingSides = Math.ceil(this.canvas.width * 0.04);
    		const foregroundRectangleAngle = Math.ceil(this.canvas.height * 0.01);
    		const foregroundRectangleOffsetBottom = Math.ceil(this.canvas.height * 0.1);
    		const foregroundRectanglePaddingTop = Math.ceil(this.canvas.height * 0.02);
    		const foregroundRectanglePaddingTopWithNameOrDiacritics = Math.ceil(this.canvas.height * 0.02);
    		const foregroundRectanglePaddingBottom = Math.ceil(this.canvas.height * 0.05);
    		
    		// Primary text
    		let primaryTextFontSize = Math.ceil(this.canvas.height * 0.09);
    		let primaryTextMaxLines = 3;
    		
    		// Name text
    		let nameTextFontSize = Math.ceil(this.canvas.height * 0.03);
    		const nameTextMaxWidth = Math.ceil(this.canvas.width * 0.35);
    		
    		// Name rectangle
    		const nameRectangleOffsetSide = Math.ceil(this.canvas.width * 0.025);
    		const nameRectangleOffsetTop = Math.ceil(this.canvas.height * 0.03);
    		const nameRectanglePaddingSides = Math.ceil(this.canvas.width * 0.025);
    		const nameRectanglePaddingTop = Math.ceil(this.canvas.height * 0.01);
    		const nameRectanglePaddingBottom = Math.ceil(this.canvas.height * 0.0175);
    		
    		// Logo
    		let logoWidth = Math.ceil(this.canvas.width * 0.12) * this.logoImageZoom;
    		const logoOffsetSide = Math.ceil(this.canvas.width * 0.04);
    		const logoMaxHeightArea = 0.8;
    		
    		// Clear the canvas
    		this.context.clearRect(
    			0, 0,
    			this.canvas.width, this.canvas.height
    		);
    		
    		// Set image
    		if (this.primaryImage !== null) {
    			// https://github.com/DonkeyDushan/piratilol/blob/main/src/js/index.js
    			// Thanks to DonkeyDushan, the guy who made the joke 2021 campaign generator :D
    			
    			const imageScaleX = this.canvas.width / this.primaryImage.width;
    			const imageScaleY = this.canvas.height / this.primaryImage.height;
    			
    			const imageScale = Math.max(imageScaleX, imageScaleY) * this.primaryImageZoom;
    			
    			// https://stackoverflow.com/a/8529655
    			// Thanks to alex!
    			this.context.setTransform(
    				imageScale,
    				0, 0,
    				imageScale,
    				(this.canvas.width - this.primaryImage.width * imageScale) / 2 + this.primaryImageX * this.primaryImageZoom,
    				(this.canvas.height - this.primaryImage.height * imageScale) / 2 + this.primaryImageY * this.primaryImageZoom,
    			);
    			this.context.drawImage(
    				this.primaryImage,
    				0, 0
    			);
    			this.context.setTransform(); // Reset transformation
    		}
    		
    		// Create primary text
    		const primaryTextMaxWidth = (
    			this.canvas.width
    			- foregroundRectangleOffsetSides * 2
    			- foregroundRectanglePaddingSides * 2
    			- logoWidth
    			- logoOffsetSide
    		);
    		
    		let primaryTextLines = null;
    		const originalPrimaryTextFontSize = primaryTextFontSize;
    		
    		do {
    			this.context.font = `${this.primaryFontStyle} ${primaryTextFontSize}px ${this.primaryFont}`;
    			
    			primaryTextLines = splitStringIntoLines(
    				this.context,
    				this.primaryText,
    				primaryTextMaxWidth,
    				primaryTextMaxLines,
    				true
    			);
    			
    			if (
    				primaryTextLines.length > primaryTextMaxLines
    				&& (
    					primaryTextLines.length * primaryTextFontSize
    					> primaryTextMaxLines * originalPrimaryTextFontSize
    				)
    			) {
    				primaryTextFontSize -= 2;
    			}
    		} while (
    			primaryTextLines.length > primaryTextMaxLines
    			&& (
    				primaryTextLines.length * primaryTextFontSize
    				> primaryTextMaxLines * originalPrimaryTextFontSize
    			)
    		);
    		
    		const firstPrimaryLine = primaryTextLines[0].toString();
    		let foregroundRectangleHeight = 0;
    		
    		// Create background rectangle
    		if (primaryTextLines.length === 1) {
    			backgroundRectangleHeight = Math.ceil(backgroundRectangleHeight / 1.3);
    		}
    		
    		// Helper canvas
    		const backgroundCanvas = document.createElement("canvas");
    		backgroundCanvas.width = this.canvas.width;
    		backgroundCanvas.height = backgroundRectangleHeight;
    		
    		const backgroundCanvasContext = backgroundCanvas.getContext("2d");
    		
    		const backgroundGradient = backgroundCanvasContext.createLinearGradient(
    			0, backgroundCanvas.height,
    			backgroundCanvas.width * 2, 0
    		);
    		backgroundGradient.addColorStop(0, this.backgroundGradientColor1);
    		backgroundGradient.addColorStop(1, "rgba(0, 0, 0, 0)");
    		
    		backgroundCanvasContext.fillStyle = backgroundGradient;
    		backgroundCanvasContext.fillRect(
    			0, 0,
    			backgroundCanvas.width, backgroundCanvas.height
    		);
    		
    		const backgroundTransparencyGradient = backgroundCanvasContext.createLinearGradient(
    			backgroundCanvas.width / 2, 0,
    			backgroundCanvas.width / 2, backgroundCanvas.height
    		);
    		backgroundTransparencyGradient.addColorStop(0, "rgba(0, 0, 0, 1)");
    		backgroundTransparencyGradient.addColorStop(1, "rgba(0, 0, 0, 0)");
    		
    		backgroundCanvasContext.fillStyle = backgroundTransparencyGradient;
    		backgroundCanvasContext.globalCompositeOperation = "xor";
    		backgroundCanvasContext.fillRect(
    			0, 0,
    			backgroundCanvas.width, backgroundCanvas.height
    		);
    		
    		this.context.drawImage(
    			backgroundCanvas,
    			0, this.canvas.height - backgroundCanvas.height,
    		);
    		
    		// Create foreground rectangle
    		if (this.primaryText !== "") {
    			foregroundRectangleHeight = (
    				foregroundRectanglePaddingBottom
    				+ primaryTextLines.length * primaryTextFontSize
    				+ foregroundRectanglePaddingTop
    				+ (
    					(
    						this.nameText !== ""
    						|| (
    							firstPrimaryLine.replace(/[a-zA-Z0-9À-ž]+/g, "").length
    							!== firstPrimaryLine.replace(/[a-zA-Z0-9]+/g, "").length
    						)
    					) ?
    					foregroundRectanglePaddingTopWithNameOrDiacritics : 0
    				)
    			);
    			
    			this.context.fillStyle = this.foregroundColor;
    			
    			this.context.beginPath();
    			this.context.moveTo(
    				foregroundRectangleOffsetSides,
    				this.canvas.height - foregroundRectangleOffsetBottom
    			);
    			this.context.lineTo(
    				this.canvas.width - foregroundRectangleOffsetSides,
    				this.canvas.height - foregroundRectangleOffsetBottom - foregroundRectangleAngle
    			);
    			this.context.lineTo(
    				this.canvas.width - foregroundRectangleOffsetSides,
    				this.canvas.height - foregroundRectangleOffsetBottom - foregroundRectangleHeight - foregroundRectangleAngle
    			);
    			this.context.lineTo(
    				foregroundRectangleOffsetSides,
    				this.canvas.height - foregroundRectangleOffsetBottom - foregroundRectangleHeight
    			);
    			this.context.closePath();
    			
    			this.context.fill();
    			
    			this.context.font = `${this.primaryFontStyle} ${primaryTextFontSize}px ${this.primaryFont}`;
    			
    			let currentPrimaryLineY = (
    				this.canvas.height
    				- foregroundRectangleOffsetBottom
    				- foregroundRectanglePaddingBottom
    			);
    			this.context.fillStyle = this.primaryTextColor;
    			
    			for (const line of primaryTextLines.reverse()) {
    				this.context.fillText(
    					line.join(" "),
    					(
    						foregroundRectangleOffsetSides
    						+ foregroundRectanglePaddingSides
    					),
    					currentPrimaryLineY
    				);
    				
    				currentPrimaryLineY -= primaryTextFontSize;
    			}
    			
    			// Create name text
    			if (this.nameText !== "") {
    				do {
    					this.context.font = `${nameTextFontSize}px 'Roboto Condensed'`;
    					
    					if (
    						this.context.measureText(this.nameText).width
    						> nameTextMaxWidth
    					) {
    						nameTextFontSize -= 2;
    					}
    				} while (this.context.measureText(this.nameText).width > nameTextMaxWidth);
    				
    				this.context.fillStyle = this.nameBackgroundColor;
    				this.context.fillRect(
    					(
    						foregroundRectangleOffsetSides
    						+ nameRectangleOffsetSide
    					), (
    						this.canvas.height
    						- foregroundRectangleHeight
    						- foregroundRectangleOffsetBottom
    						- nameRectanglePaddingBottom
    						- nameRectanglePaddingTop
    						- nameTextFontSize
    						+ nameRectangleOffsetTop
    					),
    					(
    						nameRectanglePaddingSides * 2
    						+ this.context.measureText(this.nameText).width
    					),
    					(
    						nameRectanglePaddingBottom
    						+ nameRectanglePaddingTop
    						+ nameTextFontSize
    					)
    				);
    				
    				this.context.fillStyle = this.nameTextColor;
    				
    				this.context.fillText(
    					this.nameText,
    					(
    						foregroundRectangleOffsetSides
    						+ nameRectangleOffsetSide
    						+ nameRectanglePaddingSides
    					),
    					(
    						this.canvas.height
    						- foregroundRectangleHeight
    						- foregroundRectangleOffsetBottom
    						- nameRectanglePaddingBottom
    						+ nameRectangleOffsetTop
    					)
    				);
    			}
    		}
    		
    		const classRef = this;
    		
    		// Create logo image
    		function drawLogoImage(image) {
    			let logoHeight = image.height * (logoWidth / image.width);
    			
    			if (logoHeight > foregroundRectangleHeight * logoMaxHeightArea) {
    				logoHeight = foregroundRectangleHeight * logoMaxHeightArea;
    				logoWidth = image.width * (logoHeight / image.height);
    			}
    			
    			classRef.context.drawImage(
    				image,
    				(
    					classRef.canvas.width
    					- foregroundRectangleOffsetSides
    					- foregroundRectanglePaddingSides
    					- logoWidth
    				),
    				(
    					classRef.canvas.height
    					- foregroundRectangleOffsetBottom
    					- foregroundRectanglePaddingBottom
    					- primaryTextLines.length * primaryTextFontSize
    					- foregroundRectanglePaddingTop
    					- (
    						(
    							classRef.nameText !== ""
    							|| (
    								firstPrimaryLine.replace(/[a-zA-Z0-9À-ž]+/g, "").length
    								!== firstPrimaryLine.replace(/[a-zA-Z0-9]+/g, "").length
    							)
    						) ?
    						foregroundRectanglePaddingTopWithNameOrDiacritics : 0
    					)
    					- foregroundRectangleAngle
    				),
    				logoWidth, logoHeight
    			);
    		}
    		
    		if (this.logoImage === null) {
    			const logoImageLoadPromise = new Promise(
    				resolve => {
    					let logoImage = new Image();
    					
    					logoImage.onload = function() {
    						drawLogoImage(this);
    						
    						resolve();
    					}
    					
    					const foregroundRGB = hexToRgb(this.foregroundColor);
    					
    					const foregroundLightness = (
    						0.2126 * foregroundRGB.r
    						+ 0.7152 * foregroundRGB.g
    						+ 0.0722 * foregroundRGB.b
    					);
    					
    					const useLightLogo = (foregroundLightness < 207);
    					
    					if (useLightLogo) {
    						logoImage.src = classRef.lightLogoDefaultSource;
    					} else {
    						logoImage.src = classRef.darkLogoDefaultSource;
    					}
    				}
    			);
    			
    			await logoImageLoadPromise;
    		} else {
    			drawLogoImage(this.logoImage);
    		}
    		
    		if (this.requesterText !== "") {
    			// https://newspaint.wordpress.com/2014/05/22/writing-rotated-text-on-a-javascript-canvas/
    			// Thanks to newspaint!
    			
    			this.context.save();
    
    			this.context.translate(this.canvas.width - 1, 0);
    
    			this.context.rotate(3 * Math.PI / 2);
    
    			let requesterFontSize = Math.ceil(this.canvas.width * 0.015);
    			
    			do {
    				this.context.font = `${this.primaryFontStyle} ${requesterFontSize}px ${this.primaryFont}`;
    				
    				if (
    					this.context.measureText(this.requesterText).width
    					> this.canvas.height * 0.97
    				) {
    					requesterFontSize -= 2;
    					this.context.font = `${this.primaryFontStyle} ${requesterFontSize}px ${this.primaryFont}`;
    				}
    			} while (
    				this.context.measureText(this.requesterText).width
    				> this.canvas.height * 0.97
    			);
    			
    			this.context.fillStyle = this.requesterTextColor;
    
    			this.context.textAlign = "left";
    
    			this.context.globalAlpha = 0.6;
    			this.context.fillText(
    				this.requesterText,
    				-this.canvas.height * 0.985, -this.canvas.width * 0.985 + requesterFontSize
    			);
    			this.context.globalAlpha = 1;
    			
    			this.context.restore();
    		}
    		this.finalDrawHook();
    		this.stickerDrawHook();
    		
    		this.redrawing = false;
    	}
    	
    	// Color schemes
    	async setPrimaryColorScheme(scheme, skipRedraw = false) {
    		switch (scheme) {
    			case "black-on-white":
    				this.foregroundColor = "#ffffff";
    				this.primaryTextColor = "#000000";
    				this.backgroundGradientColor1 = "#000000";
    				
    				this.nameBackgroundColor = "#000000";
    				this.nameTextColor = "#ffffff";
    				
    				break;
    			case "white-on-black":
    				this.foregroundColor = "#000000";
    				this.primaryTextColor = "#ffffff";
    				this.backgroundGradientColor1 = "#ffffff";
    				
    				this.nameBackgroundColor = "#ffffff";
    				this.nameTextColor = "#000000";
    				
    				break;
    			case "forum-black-on-white":
    				this.foregroundColor = "#ffffff";
    				this.primaryTextColor = "#000000";
    				this.backgroundGradientColor1 = "#962a51";
    				
    				this.nameBackgroundColor = "#ffffff";
    				this.nameTextColor = "#000000";
    				
    				break;
    			case "forum-white-on-purple":
    				this.foregroundColor = "#000000";
    				this.primaryTextColor = "#ffffff";
    				this.backgroundGradientColor1 = "#962a51";
    				
    				this.nameBackgroundColor = "#ffffff";
    				this.nameTextColor = "#000000";
    				
    				break;
    			case "zeleni-volary-bystrc-most-black-on-white":
    				this.foregroundColor = "#ffffff";
    				this.primaryTextColor = "#000000";
    				this.backgroundGradientColor1 = "#00ad43";
    				
    				this.nameBackgroundColor = "#000000";
    				this.nameTextColor = "#ffffff";
    				
    				break;
    			case "zeleni-volary-bystrc-most-white-on-green":
    				this.foregroundColor = "#000000";
    				this.primaryTextColor = "#ffffff";
    				this.backgroundGradientColor1 = "#00ad43";
    				
    				this.nameBackgroundColor = "#ffffff";
    				this.nameTextColor = "#000000";
    				
    				break;
    			case "spolecne-s-piraty-black-on-white":
    				this.foregroundColor = "#ffffff";
    				this.primaryTextColor = "#000000";
    				this.backgroundGradientColor1 = "#21274e";
    				
    				this.nameBackgroundColor = "#9796ca";
    				this.nameTextColor = "#000000";
    				
    				break;
    			case "spolecne-s-piraty-white-on-blue":
    				this.foregroundColor = "#21274e";
    				this.primaryTextColor = "#ffffff";
    				this.backgroundGradientColor1 = "#ffffff";
    				
    				this.nameBackgroundColor = "#9796ca";
    				this.nameTextColor = "#000000";
    				
    				break;
    			case "louny-spolecne-black-on-white":
    				this.foregroundColor = "#ffffff";
    				this.primaryTextColor = "#3e2a5b";
    				this.backgroundGradientColor1 = "#e2d7a9";
    				
    				this.nameBackgroundColor = "#3e2a5b";
    				this.nameTextColor = "#ffffff";
    				
    				break;
    			case "louny-spolecne-white-on-purple":
    				this.foregroundColor = "#3e2a5b";
    				this.primaryTextColor = "#ffffff";
    				this.backgroundGradientColor1 = "#e2d7a9";
    				
    				this.nameBackgroundColor = "#ffffff";
    				this.nameTextColor = "#000000";
    				
    				break;
    			case "litomerice-blue-on-white":
    				this.foregroundColor = "#ffffff";
    				this.primaryTextColor = "#123172";
    				this.backgroundGradientColor1 = "#123172";
    				
    				this.nameBackgroundColor = "#cccccc";
    				this.nameTextColor = "#123172";
    				
    				break;
    			case "litomerice-white-on-blue":
    				this.foregroundColor = "#123172";
    				this.primaryTextColor = "#ffffff";
    				this.backgroundGradientColor1 = "#ffffff";
    				
    				this.nameBackgroundColor = "#cccccc";
    				this.nameTextColor = "#123172";
    				
    				break;
    			case "stranane-gray-on-yellow":
    				this.foregroundColor = "#ffd500";
    				this.primaryTextColor = "#4d4d4d";
    				this.backgroundGradientColor1 = "#ffffff";
    				
    				this.nameBackgroundColor = "#4d4d4d";
    				this.nameTextColor = "#ffffff";
    				
    				break;
    			case "stranane-yellow-on-white":
    				this.foregroundColor = "#ffffff";
    				this.primaryTextColor = "#4d4d4d";
    				this.backgroundGradientColor1 = "#ffd500";
    				
    				this.nameBackgroundColor = "#4d4d4d";
    				this.nameTextColor = "#ffffff";
    				
    				break;
    			case "stranane-white-on-yellow":
    				this.foregroundColor = "#4d4d4d";
    				this.primaryTextColor = "#ffffff";
    				this.backgroundGradientColor1 = "#ffd500";
    				
    				this.nameBackgroundColor = "#ffffff";
    				this.nameTextColor = "#4d4d4d";
    				
    				break;
    			case "prusanky-black-on-yellow":
    				this.foregroundColor = "#ffd500";
    				this.primaryTextColor = "#000000";
    				this.backgroundGradientColor1 = "#000000";
    				
    				this.nameBackgroundColor = "#000000";
    				this.nameTextColor = "#ffffff";
    				
    				break;
    			case "prusanky-yellow-on-white":
    				this.foregroundColor = "#ffffff";
    				this.primaryTextColor = "#000000";
    				this.backgroundGradientColor1 = "#ffd500";
    				
    				this.nameBackgroundColor = "#000000";
    				this.nameTextColor = "#ffffff";
    				
    				break;
    			case "prusanky-white-on-yellow":
    				this.foregroundColor = "#000000";
    				this.primaryTextColor = "#ffffff";
    				this.backgroundGradientColor1 = "#ffd500";
    				
    				this.nameBackgroundColor = "#ffffff";
    				this.nameTextColor = "#000000";
    				
    				break;
    			case "ujezd-green-on-white":
    				this.foregroundColor = "#ffffff";
    				this.primaryTextColor = "#000000";
    				this.backgroundGradientColor1 = "#8ed4a3";
    				
    				this.nameBackgroundColor = "#ffdd55";
    				this.nameTextColor = "#000000";
    				
    				break;
    			case "ujezd-white-on-green":
    				this.foregroundColor = "#8ed4a3";
    				this.primaryTextColor = "#000000";
    				this.backgroundGradientColor1 = "#000000";
    				
    				this.nameBackgroundColor = "#ffdd55";
    				this.nameTextColor = "#000000";
    				
    				break;
    			case "cssd-red-on-black":
    				this.foregroundColor = "#000000";
    				this.primaryTextColor = "#ffffff";
    				this.backgroundGradientColor1 = "#e63812";
    				
    				this.nameBackgroundColor = "#ffffff";
    				this.nameTextColor = "#000000";
    				
    				break;
    			case "cssd-black-on-red":
    				this.foregroundColor = "#ffffff";
    				this.primaryTextColor = "#000000";
    				this.backgroundGradientColor1 = "#000000";
    				
    				this.nameBackgroundColor = "#ffffff";
    				this.nameTextColor = "#000000";
    				
    				break;
    			case "jilemnice-purple-on-black":
    				this.foregroundColor = "#ffffff";
    				this.primaryTextColor = "#000000";
    				this.backgroundGradientColor1 = "#6e1646";
    				
    				this.nameBackgroundColor = "#000000";
    				this.nameTextColor = "#ffffff";
    				
    				break;
    			case "jilemnice-black-on-purple":
    				this.foregroundColor = "#6e1646";
    				this.primaryTextColor = "#ffffff";
    				this.backgroundGradientColor1 = "#000000";
    				
    				this.nameBackgroundColor = "#ffffff";
    				this.nameTextColor = "#000000";
    				
    				break;
    			case "novarole-white-on-green":
    				this.foregroundColor = "#ffffff";
    				this.primaryTextColor = "#000000";
    				this.backgroundGradientColor1 = "#a9ce2d";
    				
    				this.nameBackgroundColor = "#a9ce2d";
    				this.nameTextColor = "#000000";
    				
    				break;
    			case "novarole-green-on-white":
    				this.foregroundColor = "#000000";
    				this.primaryTextColor = "#ffffff";
    				this.backgroundGradientColor1 = "#a9ce2d";
    				
    				this.nameBackgroundColor = "#ffffff";
    				this.nameTextColor = "#000000";
    				
    				break;
    			case "novarole-green-on-black":
    				this.foregroundColor = "#a9ce2d";
    				this.primaryTextColor = "#000000";
    				this.backgroundGradientColor1 = "#000000";
    				
    				this.nameBackgroundColor = "#ffffff";
    				this.nameTextColor = "#000000";
    				
    				break;
    			case "zeleni-melnik-yellow-name-rect":
    				await this.setPrimaryColorScheme("white-on-black", true);
    				
    				this.nameBackgroundColor = "#fde119";
    				this.nameTextColor = "#000000";
    				
    				break;
    			default:
    				throw new Error("This scheme does not exist.");
    				break;
    		}
    		
    		this.requesterTextColor = this.primaryTextColor;
    		
    		if (!skipRedraw) {
    			await this.redrawCanvas();
    		}
    	}
    }