Core JavaScript

Composite Design Pattern

This Javascript program demonstrates a composite design pattern.

Composite.html

<!DOCTYPE html>
<html>
  <head>
    <title>XoaX.net's Javascript</title>
    <script type="text/javascript" src="Composite.js"></script>
  </head>
  <body onload="Initialize()">
     <canvas id="idCanvas" width="640" height ="480" style="background-color: #F0F0F0;"></canvas>
  </body>
</html>

Composite.js

class CAGraphic {
	constructor() {}
	Draw(qContext, qT = CTransformation.GetIdentity()) {}
}

class CDisk extends CAGraphic {
	#mdR;
	#msColor;
	constructor(dR, sColor) {
		super();
		this.#mdR = dR;
		this.#msColor = sColor;
	}
	Draw(qContext, qT = CTransformation.GetIdentity()) {
		qT.SetTransform(qContext);
		qContext.fillStyle = this.#msColor;
		qContext.beginPath();
		qContext.arc(0, 0, this.#mdR, 0, 2 * Math.PI);
		qContext.fill();
	}
}

class CRectangle extends CAGraphic {
	#mdW;
	#mdH;
	#msColor;
	constructor(dW, dH, sColor) {
		super();
		this.#mdW = dW;
		this.#mdH = dH;
		this.#msColor = sColor;
	}
	Draw(qContext, qT = CTransformation.GetIdentity()) {
		qT.SetTransform(qContext);
		qContext.fillStyle = this.#msColor;
		qContext.fillRect(0, 0, this.#mdW, this.#mdH);
	}
}

class CComposite extends CAGraphic {
	// Transformation array
	#mdaT = new Array();
	#mdaG = new Array();
	constructor() {
		super();
	}
	Add(qTransformation, qGraphic) {
		this.#mdaT.push(qTransformation);
		this.#mdaG.push(qGraphic);
	}
	Draw(qContext, qT = CTransformation.GetIdentity()) {
		var qCurr = qT;
		for (var i = 0; i < this.#mdaT.length; ++i) {
			qCurr = CTransformation.Multiply(qCurr, this.#mdaT[i]);
			this.#mdaG[i].Draw(qContext, qCurr);
		}
	}
}


class CTransformation {
	// [ A[0], A[2], A[4] ]
	// [ A[1], A[3], A[5] ]
	// [    0,    0,    1 ]
	#mdaA;
	constructor(dA0, dA1, dA2, dA3, dA4, dA5) {
		this.#mdaA = new Array(dA0, dA1, dA2, dA3, dA4, dA5);
	}
	Apply(dX, dY) {
		return [this.#mdaA[0]*dX + this.#mdaA[2]*dY + this.#mdaA[4],
						this.#mdaA[1]*dX + this.#mdaA[3]*dY + this.#mdaA[5]];
	}
	SetTransform(qContext) {
		qContext.setTransform(
		this.#mdaA[0], this.#mdaA[1], this.#mdaA[2],
		this.#mdaA[3], this.#mdaA[4], this.#mdaA[5]);
	}
	static GetIdentity(){
		return new CTransformation(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
	}
	static GetRotation(dAngle){
		return new CTransformation(Math.cos(dAngle), Math.sin(dAngle), -Math.sin(dAngle), Math.cos(dAngle), 0.0, 0.0);
	}
	static GetTranslation(dDx, dDy){
		return new CTransformation(1.0, 0.0, 0.0, 1.0, dDx, dDy);
	}
	static GetScaling(dS){
		return new CTransformation(dS, 0.0, 0.0, dS, 0.0, 0.0);
	}
	static Multiply(qT1, qT2) {
		return new CTransformation(
			qT1.#mdaA[0]*qT2.#mdaA[0]+qT1.#mdaA[2]*qT2.#mdaA[1],
			qT1.#mdaA[1]*qT2.#mdaA[0]+qT1.#mdaA[3]*qT2.#mdaA[1],
			qT1.#mdaA[0]*qT2.#mdaA[2]+qT1.#mdaA[2]*qT2.#mdaA[3],
			qT1.#mdaA[1]*qT2.#mdaA[2]+qT1.#mdaA[3]*qT2.#mdaA[3],
			qT1.#mdaA[0]*qT2.#mdaA[4]+qT1.#mdaA[2]*qT2.#mdaA[5] + qT1.#mdaA[4],
			qT1.#mdaA[1]*qT2.#mdaA[4]+qT1.#mdaA[3]*qT2.#mdaA[5] + qT1.#mdaA[5]);
	}
}

function Initialize() {
	var qCanvas = document.getElementById("idCanvas");
	var qContext = qCanvas.getContext("2d");
	
	var qBackground = new CComposite();
	var qSky = new CRectangle(640, 300, "darkblue");
	var qGround = new CRectangle(640, 180, "green");
	var qMoon = new CDisk(40, "white");
	qBackground.Add(CTransformation.GetTranslation(0, 0), qSky);
	qBackground.Add(CTransformation.GetTranslation(0, 300), qGround);
	qBackground.Add(CTransformation.GetTranslation(500, -200), qMoon);
	qBackground.Draw(qContext);
	
	// The wheels are composite objects
	var qWheel = new CComposite();
	var qTire = new CDisk(50, "black");
	var qRim = new CDisk(30, "gray");
	qWheel.Add(CTransformation.GetIdentity(), qTire);
	qWheel.Add(CTransformation.GetIdentity(), qRim);
	
	// Construct the car with two rectangles and two wheels
	var qCar = new CComposite();
	var qCab = new CRectangle(200, 80, "orange");
	var qBody = new CRectangle(500, 100, "orange");
	qCar.Add(CTransformation.GetTranslation(220, 150), qCab);
	qCar.Add(CTransformation.GetTranslation(-150, 80), qBody);
	qCar.Add(CTransformation.GetTranslation(80, 100), qWheel);
	qCar.Add(CTransformation.GetTranslation(340, 0), qWheel);
	qCar.Draw(qContext);
}
 

Output

 
 

© 2007–2025 XoaX.net LLC. All rights reserved.