Sorcerer's IsleCode Scatter / files

  1<!-- Scatter v0.1 | (c) Peter Boughton | License: LGPLv3 | https://www.sorcerersisle.com/software/scatter -->
  2<!doctype html><meta charset=utf-8 />
  3<title>Cards Scatter Demo</title>
  4
  5<h1>Cards Scatter Demo</h1>
  6<p>A full deck of playing cards strewn across a table.
  7<p>Uses random mode plus <em>not</em> setting overflow:hidden style on the container to allow cards to overlap the edge.
  8<p>Click to flip a card - uses custom handler for click event to modify the CSS transform.
  9<p>Each individual card uses Scatter too - pre-defined pip coordinates are passed to a fixed mode Scatter instance with click events disabled.
 10
 11<p><i>(View source to see markup, script and CSS used.)</i>
 12<script src="../scatter.js"></script>
 13
 14
 15<style>
 16	body
 17	{
 18		font-family:sans-serif;
 19		background:#CCC;
 20	}
 21
 22	#Table
 23	{
 24		display:block;
 25		background:#484;
 26		border: solid 1px black;
 27		width:960px;
 28		margin:auto;
 29		height:480px;
 30		margin-top:4em;
 31	}
 32
 33	#Table>*
 34	{
 35		transition: 0.3s;
 36	}
 37
 38	.card
 39	{
 40		position:relative;
 41		display: inline-block;
 42		background: white;
 43		border: solid 2px white;
 44		border-radius: 9px;
 45		height: 342px; /* 3.5in ~ 346px */
 46		width: 236px; /* 2.5in ~ 240px */
 47		box-shadow: 0 0 2px rgba(0,0,0,0.2);
 48
 49		font-family: serif;
 50		text-align:center;
 51	}
 52	.card.hearts,.card.diams { color: red; }
 53	.card.spades,.card.clubs { color: black; }
 54
 55	.card .inv{ transform: rotate(180deg); }
 56
 57	.card .corner
 58	{
 59		width: 30px;
 60		font-size: 34px;
 61		line-height: 1;
 62		position: absolute;
 63	}
 64	.card .corner:not(.inv){left:0;top:0;}
 65	.card .corner.inv{right:0;bottom:0;}
 66
 67	.card .body
 68	{
 69		width:100%;
 70		height:100%;
 71		font-size:80px;
 72	}
 73
 74	/* Larger pip for Ace of Spades */
 75	.card.spades.v1 .body
 76	{
 77		font-size: 160px;
 78		margin-top:-20px;
 79	}
 80
 81
 82	.card .body.picture
 83	{
 84		margin: 22px auto;
 85		padding: 4px 0;
 86		width:176px;
 87		height:282px;
 88		border:solid 1px navy;
 89		background:#FFE;
 90	}
 91
 92	.card.facedown
 93	{
 94		background-color: white;
 95		background-image: radial-gradient(circle,white,navy 6px,white 12px,white);
 96		background-size: 18px 20px;
 97	}
 98	.card.facedown>*
 99	{
100		display:none;
101	}
102</style>
103
104
105<div id="Table"></div>
106
107
108<script>
109	var Suits = ['spades','hearts','clubs','diams'];
110	var Labels = {  1:'A' , 11:'J' , 12:'Q' , 13:'K' , 10:'1<span style="margin-left:-0.4ch;">0</span>' };
111
112	var Ends       = 126;
113	var Sides      = 54;
114	var Corners    = [[-Sides,-Ends],[Sides,-Ends],[-Sides,Ends,180],[Sides,Ends,180]];
115	var MidRow     = [[-Sides,0],[Sides,0]];
116	var NineTen    = [[-Sides,-48],[Sides,-48],[-Sides,48,180],[Sides,48,180]];
117	var Pictures   = [[-Sides,-Ends],[Sides,Ends,180],[0,-Ends+30],[0,Ends-30,180],[0,-Ends+60],[0,Ends-60,180]];
118
119	var Hats = {11:'&#9815;',12:'&#9813;',13:'&#9818;'};
120
121	var PipPositions =
122		{ 1:  [[0,0]]
123		, 2:  [[0,-Ends],[0,Ends,180]]
124		, 3:  [[0,0],[0,-Ends],[0,Ends,180]]
125		, 4:  Corners
126		, 5:  Corners.concat([[0,0]])
127		, 6:  Corners.concat(MidRow)
128		, 7:  Corners.concat(MidRow).concat([[0,-68]])
129		, 8:  Corners.concat(MidRow).concat([[0,-68],[0,68,180]])
130		, 9:  Corners.concat(NineTen).concat([[0,0]])
131		, 10: Corners.concat(NineTen).concat([[0,-87],[0,87,180]])
132		, 11: Pictures
133		, 12: Pictures
134		, 13: Pictures
135		};
136
137
138	function renderCard(Value,Suit)
139	{
140		var SuitHtml = '&'+Suit+';';
141
142		var Label = Labels[Value] || Value;
143
144		var CardHtml = '<div class="card '+Suit+' v'+Value+'">'
145			+'<div class="corner"><div class="value">'+Label+'</div><div class="suit">'+SuitHtml+'</div></div>'
146			;
147
148		if ( Value > 10 )
149		{
150			CardHtml += '<div class="body picture">'
151				+ '<div class="pip">'+SuitHtml+'</div><div class="pip">'+SuitHtml+'</div>'
152				+ '<div class="hat">'+Hats[Value]+'</div><div class="hat">'+Hats[Value]+'</div>'
153				+ '<div class="head">&#9786;</div><div class="head">&#9786;</div>'
154				+ '</div>'
155				;
156		}
157		else
158		{
159			CardHtml += '<div class="body">';
160			for ( var i = 1 ; i <= Value ; ++i )
161				CardHtml += '<div class="pip">'+SuitHtml+'</div>';
162			CardHtml += '</div>';
163		}
164
165		CardHtml += '<div class="corner inv"><div class="value">'+Label+'</div><div class="suit">'+SuitHtml+'</div></div>'
166			+'</div>';
167
168		return CardHtml;
169	}
170
171	/*
172		render each card and positions pips using
173	*/
174	var Table = document.getElementById('Table');
175	for ( var i=0 ; i<Suits.length ; ++i )
176	{
177		for ( var Value = 1 ; Value <= 13 ; ++Value )
178		{
179			Table.innerHTML += renderCard(Value,Suits[i]);
180
181			var CardOptions =
182				{ InitialMode     : 'fixed'
183				, FixedRelativeTo : 'center'
184				, FixedPositions  : PipPositions[Value]
185				, ChildEvents     : {'click':void 0}
186				, ContainerEvents : {'click':void 0}
187				};
188
189			new Scatter('.card.v'+Value+'.'+Suits[i]+' .body',CardOptions );
190		}
191	}
192
193	function flipCard(event)
194	{
195		event.stopPropagation();
196		event.currentTarget.classList.toggle('facedown');
197
198		if ( event.currentTarget.style.transform.indexOf('rotate3d') !== -1 )
199		{
200			event.currentTarget.style.transform = event.currentTarget.style.transform.replace(/rotate3d\([^)]+\)/,'');
201		}
202		else
203		{
204			// non-zero z rotation overcomes animation glitch when card has clockwise 2d rotation.
205			event.currentTarget.style.transform += ' rotate3d(0,1,0.001,180deg)';
206		}
207	}
208
209	var CardOptions =
210		{ Mode        : 'random'
211		, InitialMode : 'random'
212		, Scale       : 0.3
213		, MaxRotation : 45
214		, Shuffle     : true
215		, ChildEvents : {click:flipCard}
216		};
217	var CardScatter = new Scatter(document.getElementById('Table'),CardOptions);
218
219</script>