Skip to content
Snippets Groups Projects
SkribblCanvasContainer.js 9.26 KiB
Newer Older
import SkribblClient from "../logic/SkribblClient.js";
import LatexJS from "../util/Latex.js";
import Util, {CustomElement} from "../util/Util.js";
import SkribblCanvas from "./SkribblCanvas.js";

/**
 * Custom element `<skribbl-canvas-container>` that manages the canvas and its overlays.
 */
export default class SkribblCanvasContainer extends CustomElement {
	/**
	 * @param {SkribblClient} client 
	 */
	constructor(client){
		super();
		this.attachShadow({mode:"open"});
		this.shadowRoot.innerHTML = `
			<style>
				:host {
					display: block;
					position: relative;
				}
				svg {
					display: block;
					width: 100%;
				}
				#container {
					position: absolute;
					left: 0;
					top: 0;
					width: 100%;
					height: 100%;
					overflow: hidden;
					background: #ffffff;
					border-radius: 5px;
				}
				#controls {
					position: absolute;
					top: 100%;
					margin-top: 10px;
				}
				#controls.hidden {
					display: none;
				}
				.button {
					margin: auto;
					text-align: center;
					display:inline-block;
					border: 3px solid transparent;
					height:40px;
					width:40px;
					cursor: pointer;
				}
				.colorButton{
					height: 20px;
					width: 20px;	
					}
				.widthButton{
					height:40px;
					width: 40px;
				}
				.drawButton{
					height: 40px;
					width: 100px;
				}
			</style>
			<!-- invisible svg to maintain an aspect ratio of 960:720, aka 4:3 -->
			<svg viewBox="0 0 960 720"></svg>
			<div id="container">
				<slot name="overlay"></slot>
			</div>
			<div id="controls">
				<div id = "widthS" class = "button widthButton" style="background: white"> dünn </div>
				<div id = "widthM" class = "button widthButton" style="background: white"> mittel </div>
				<div id = "widthL" class = "button widthButton" style="background: white">  dick </div>
				<div id = "widthXL" class = "button widthButton" style="background: white"> sehr dick  </div>
				<div id = "pen" class = "button drawButton" style="background:white"> malen  </div>
				<div id = "erasor" class = "button drawButton" style="background: white"> radieren </div>
				<div id = "changeBackgroundColor" class = "button drawButton" style="background: white"> Hintergrund färben </div>
				
//@todo: vierter Button für Fill
		this.colors =["darkred",  "DarkRed",
			"red", "Firebrick",
			"orange", "orange",
			"yellow", "yellow",
			"lightgreen", "YellowGreen",
			"green", "ForestGreen",
			"lightblue", "SkyBlue",
			"blue",  "SlateBlue",
			"purple", "BlueViolet",
			"pink", "pink",
			"lightbrown", "SandyBrown",
			"darkbrown", "SaddleBrown",
			"black", "black",
			"darkgrey", "DarkGrey",
			"lightgrey","LightGrey",
			"white","white"];	
		let buttonString = "";
		for (let i = 0;i<this.colors.length; i+=2){
			buttonString += "<div id = \""+this.colors[i]+"\" class = \"button colorButton\" style=\"background: "+this.colors[i+1]+"\"> </div>";
			console.log(buttonString);
		}
			
			
			
		this._canvas = new SkribblCanvas(client);
		this._container = this.shadowRoot.getElementById("container");
		this._container.insertBefore(this._canvas,this._container.firstChild);
		this._controls = this.shadowRoot.getElementById("controls");
		this._controls.insertAdjacentHTML("afterbegin", buttonString);


		client.state.onChange(state=>{
			/** whether the player should currently be allowed to draw on the canvas */
			let allowToDraw = state.hasGameStarted&&state.drawingPlayer==state.playerIndex&&typeof state.word=="string";
			this._canvas.drawable = allowToDraw;
			this._controls.classList.toggle("hidden",!allowToDraw);
		},{onlyWhen:this.connected});
		// TODO implement color settings and set the correspondig properties of `this._canvas` whenever they change here. 
		//Logik fuer die Buttons zur Farbauswahl
		for(let i = 0;i<this.colors.length;i+=2){
			this._coolButton = this.shadowRoot.querySelector("#"+this.colors[i]);
			this._coolButton.addEventListener("click",e=>{
				this._canvas.color = this.colors[i+1];	
				this.allColorButtonsBorderTransparent();
				this.shadowRoot.getElementById(this.colors[i]).style.borderColor = Farbe;
			});
		}
			//Logik fuer Buttons zur Auswahl der Stiftdicke
		//@todo: Stiftdicke bestimmen
		this.penDrawButtons = ["widthS",
							"widthM",
							"widthL",
							"widthXL"];
		let penDrawButtonsSize = [5,10,30,50];
		for(let i = 0;i<this.penDrawButtons.length;i+=1){
			this._widthSDrawButton = this.shadowRoot.querySelector("#"+this.penDrawButtons[i]);
			this._widthSDrawButton.addEventListener("click",e=>{
				this._canvas.radius = penDrawButtonsSize[i];
				this.allWidthButtonsBorderTransparent();	
				this.shadowRoot.getElementById(this.penDrawButtons[i]).style.borderColor = Farbe;
		});
		}
			//Logik fuer Buttons (Radieren und Malen)
		this._penButton = this.shadowRoot.querySelector("#pen");
		this._penButton.addEventListener("click",e=>{
			this._canvas.penActive = true;		
			this.allDrawButtonsBorderTransparent();	
			this.shadowRoot.getElementById("pen").style.borderColor = Farbe;
		});
		this._erasorButton = this.shadowRoot.querySelector("#erasor");
		this._erasorButton.addEventListener("click",e=>{
			this._canvas.erasorActive = true;		
			this.allDrawButtonsBorderTransparent();	
			this.shadowRoot.getElementById("erasor").style.borderColor = Farbe;
		this._changeBackgroundColorButton = this.shadowRoot.querySelector("#changeBackgroundColor");
		this._changeBackgroundColorButton.addEventListener ("click", e=>{
			this._canvas.changeBackgroundActive = true;
			this.allDrawButtonsBorderTransparent();	
			this.shadowRoot.getElementById("changeBackgroundColor").style.borderColor = Farbe;
		})
	/**
	 * changes bordercolor of all Colorbuttons to transparent
	 */
	
	 allColorButtonsBorderTransparent() {
		for(let i = 0; i<this.colors.length;i+=2){
			this.shadowRoot.getElementById(this.colors[i]).style.borderColor = "transparent";
		}
	}

	/**
	 * changes bordercolor of all Widthbuttons to transparent
	 */
	allWidthButtonsBorderTransparent() {
		for(let i = 0; i<this.penDrawButtons.length;i+=1){
			this.shadowRoot.getElementById(this.penDrawButtons[i]).style.borderColor = "transparent";
		}
	}

	/**
	 * changes bordercolor of all Drawbuttons to transparent
	 */
	allDrawButtonsBorderTransparent() {
		this.shadowRoot.getElementById("pen").style.borderColor = "transparent";
		this.shadowRoot.getElementById("erasor").style.borderColor = "transparent";
		this.shadowRoot.getElementById("changeBackgroundColor").style.borderColor = "transparent";
		//this.shadowRoot.getElementById("widthXL").style.borderColor = "transparent";
	}


	set overlay(overlay){
		if (this._overlay){
			this._overlay.remove();
		}
		this._overlay = overlay;
		if (overlay){
			overlay.slot = "overlay";
			this.appendChild(overlay);
		}
	}
	/**
	 * @type {SkribblCanvasOverlay}
	 */
	get overlay(){
		return this._overlay;
	}
}
/**
 * Custom element `<skribbl-canvas-overlay>` for overlays on the `<skribbl-canvas>`-element.
 */
export class SkribblCanvasOverlay extends HTMLElement {
	/**
	 * Constructs a new SkribblCanvasOverlay and appends the given nodes or strings to it.
	 * @param {(string|Node)[]|import("../logic/SkribblClient.js").WordReveal} data the nodes or data to display
	 * @param {SkribblClient} client
	 */
	constructor(data=[],client=null){
		super();
		this.attachShadow({mode:"open"});
		this.shadowRoot.innerHTML = `
			<style>
				:host {
					display: block;
					position: absolute;
					top: 0;
					right: 0;
					bottom: 0;
					left: 0;
					background: #000000bf;
					color: #ffffff;
				}
					position: absolute;
					left: 50%;
					top: 50%;
					width: 100%;
					height: 100%;
				}
				#contents {
					position: absolute;
					max-width: 80%;
					transform: translate(-50%,-50%);
					text-align: center;
				}
				::slotted(button) {
					padding: 3px 5px;
					margin: 3px;
					border: none;
					border-radius: 3px;
					background: #dfdfdf;
					color: #000000;
					font-size: 1em;
				}
				::slotted(button:hover) {
					cursor: pointer;
				}
				table {
					display: inline-block;
					font-size: 1.1em;
				}
				td {
					padding: 1px 8px;
				}
				td:first-child {
					text-align: left;
				}
				td:last-child {
					text-align: right;
				}
				h2+latex-js.description {
					display: block;
					margin-top: -1em;
					margin-bottom: 1em;
				}
			</style>
			<div id="outer">
				<div id="contents">
					<slot></slot>
				</div>
		this._contents = this.shadowRoot.querySelector("#contents");
		if (Array.isArray(data)){
			this.append(...data);
		}else{
			let points = data.points.map((points,index)=>({name:client.players.value[index].name,points}));
			points.sort((a,b)=>b.points-a.points);
			this._contents.innerHTML = `
				<h2>The word was: ${Util.htmlEscape(data.word)}</h2>
				<table>
					${points.map(({name,points})=>`
						<tr>
							<td>${Util.htmlEscape(name)}:</td>
							<td style="color:${points>0?"#00bf00":"#bf0000"}">+${Util.htmlEscape(points.toString())}</td>
						</tr>
					`).join("")}
			if (data.description){
				let latex = new LatexJS(data.description,{macros:data.macros});
				latex.className = "description";
				this._contents.insertBefore(latex,this._contents.children[1]);
			}
		}
	}
customElements.define("skribbl-canvas-container",SkribblCanvasContainer);
customElements.define("skribbl-canvas-overlay",SkribblCanvasOverlay);