童年回忆
我小时候,家里的庭院有一棵枝繁叶茂的树,那时候家里没有空调,夏天会在树荫下铺个席子,或是午睡,或是看书。后来,家里给我买了一台掌上游戏机,那个时候还挺奢侈的。于是,暑假大部分时间都是在俄罗斯方块的旋转、移动中度过的。
我用CSS复刻了一个游戏机
记忆中的游戏机已经模糊了,于是我搜索了一下游戏机的图片。尤其卡通图片,圆乎乎的真可爱。游戏机的主体和屏幕是矩形的,按键是圆形或者圆角矩形。有趣又比较好实现。
所以我便用CSS复刻了一个游戏机。
UI展示
机体
- 游戏机的主体是一个矩形,带有边框和弧度;
- 为了呈现立体感,通过box-shadow游戏机主体设置了向外的阴影;
css
.player { width: 280px; height: 460px; background: #ffc600;border: 6pxsolid#5a1f12;border-radius: 15px15px45px15px; position: relative; box-shadow: 30px20px10px10px#9e988b;}
html
<divclass="player"></div>
听筒
掌上游戏机在玩游戏的时候,会有音效,所以我设计了一个听筒。
- 听筒是一个平面圆角矩形,通过设置border-radius的值可以实现两边的圆角;
css
.head { width: 100%; height: 26px; position: absolute; top: 0; left: 0; border-bottom: 5pxsolid#5a1f12;} .head::before { content: ''; width: 6px; height: 26px; background: #5a1f12;position: absolute; top: 0; left: 20px; } .head::after { content: ''; width: 6px; height: 26px; background: #5a1f12;position: absolute; top: 0; right: 20px; } .receiver { width: 50px; height: 8px; background: #eba260;border: 4pxsolid#5a1f12;border-radius: 8px; position: absolute; top: 5px; left: 35px; }
html
<divclass="head"><divclass="receiver"></div></div>
屏幕
屏幕除了边框之外,显示部分由两个内容构成,开机前和开机后,两个不共存。
开机前
- 开机前展示绿色的屏幕和反光效果,我小时的游戏机屏幕是浅绿色的,这个我还有点印象;
- 反光效果,主要是为了增加趣味性和表现屏幕的光亮感。我将反光效果设计为一个白条从屏幕上方移动到下方,这个效果通过animation实现;
css
.screen { width: 220px; height: 170px; background: #9c6766;border: 5pxsolid#5a1f12;border-radius: 10px10px30px10px; position: absolute; top: 40px; left: 50%; margin-left: -115px; } .monitor { width: 180px; height: 120px; background: #d5eabd;border: 5pxsolid#5a1f12;margin: 20pxauto; position: relative; overflow: hidden; } .monitor .light { width: 20px; height: 220px; background: #e2f0d8;position: absolute; top: -33px; left: -23px; transform: rotate(44deg); animation: monitorlight3sinfinite; } @keyframesmonitorlight { 50% { left: 80%; } 51% { left: 80%; opacity: 1; } 61% { left: 80%; opacity: 0.3; } 71% { left: 80%; opacity: 1; } 81% { left: 80%; opacity: 0.3; } 91% { left: 80%; opacity: 1; } 100% { left: 80%; opacity: 1; } }
html
<divclass="screen"><divclass="monitor"id="monitor"><divclass="light"></div></div></div>
开机后
- 开机后展示俄罗斯方块的界面,包括左侧的游戏区域和右侧的游戏记录两个部分;
- 游戏区域目前仅实现展示游戏名称的功能;
css
.screen .game { width: 190px; height: 150px; background: #d5eabd;border-radius: 10px10px30px10px; margin: 10pxauto; display: none; } .game .left { float: left; width: 52%; height: 128px; border: 1pxsolid#333;margin: 10px0010px; position: relative; } .game .game-name { width: 100%; height: 100%; position: absolute; top: 0; left: 0; color: #000;line-height: 1; background: rgba(158, 174, 134, 0.8); justify-content: center; display: none; } .game .game-name .name-box { animation: 1.5slineargamenameforwards; font-size: 15px; padding: 54px0010px; } @keyframesgamename { 30% { opacity: 0.3; } 60% { opacity: 1; } 90% { opacity: 0.3; } 91% { opacity: 1; } 100% { opacity: 1; } } .game .left-content { position: absolute; top: 10px; left: 8px; } .game .left-box .integral-block.b { border: 2pxsolid#333;} .game .left-box .integral-block.b::after { background: #333;} .game .right { float: right; width: 30%; font-size: 12px; font-weight: 300; text-align: left; line-height: 1.5; padding: 10px; color: #000;} .game .integral-num { font-size: 13px; font-weight: 500; text-align: right; } .game .integral-graph { position: relative; } .game .integral-box { position: relative; height: 14px; width: 40px; } .game .integral-box .integral-block { border: 2pxsolid#333;} .game .integral-box .integral-block::after { background: #333;} .game .integral-block { display: block; width: 6px; height: 6px; padding: 1px; border: 2pxsolid#9eae86;margin: 02px2px0; float: left; } .game .integral-block::after { content: ''; display: block; width: 6px; height: 6px; background: #9eae86;overflow: hidden; } .game .integral-box1 { top: 4px; left: 13px; } .game .integral-box2 { top: 7px; left: 27px; }
html
<divclass='screen'><divclass='game'id='game'><divclass='left'><divclass='left-content'><divclass='left-box'><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span></div><divclass='left-box'><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span></div><divclass='left-box'><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span></div><divclass='left-box'><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span></div><divclass='left-box'><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span></div><divclass='left-box'><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span></div><divclass='left-box'><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span></div><divclass='left-box'><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span><spanclass='integral-block'></span></div></div><divclass='game-name'id='gameName'><divclass='name-box'>游戏开始</div></div></div><divclass='right'><divclass='integral-title'>最高分</div><divclass='integral-num'>10</div><divclass='integral-title'>起始行</div><divclass='integral-num'>0</div><divclass='integral-title'>下一个</div><divclass='integral-graph'><divclass='integral-box integral-box1'><spanclass='integral-block'></span><spanclass='integral-block'></span></div><divclass='integral-box integral-box2'><spanclass='integral-block'></span><spanclass='integral-block'></span></div></div></div></div></div>
分割线
- 分割线为了更好区分屏幕和按键两个区域;
- 包括左右两个横向和中间六个点;
css
.dividing { width: 100%; height: 24px; display: flex; justify-content: space-between; align-items: center; position: absolute; top: 220px; left: 0; } .dleft { width: 50px; height: 5px; background: #5a1f12;margin-left: 30px; border-radius: 5px; } .dcenter { display: flex; } .dspot { width: 3px; height: 5px; background: #5a1f12;margin-right: 3px; border-radius: 3px; } .dright { width: 80px; height: 5px; background: #5a1f12;margin-right: 30px; border-radius: 5px; }
html
<divclass='dividing'><divclass='dleft'></div><divclass='dcenter'><divclass='dspot'></div><divclass='dspot'></div><divclass='dspot'></div><divclass='dspot'></div><divclass='dspot'></div><divclass='dspot'></div></div><divclass='dright'></div></div>
按键
- 上下左右操作按键,由圆和十字图形组成,十字图形通过横向和竖向的矩形组成,为了增加立体感,十字的矩形添加了外部的阴影;
- 开始按键,右侧倾斜的圆角矩形上侧的红色圆点为开始按键,点击之后,屏幕点亮并展示内容,同时开始按键不可重复点击,停止按键可以点击;
- 停止按键右侧倾斜的圆角矩形下侧的红色圆点为开始按键,点击之后,屏幕关闭展示绿色屏幕,同时停止按键不可重复点击,开始按键可以点击;
- 声音按键,底部两个圆角矩形为声音按键;
css
.push-direction { width: 80px; height: 80px; background: #ee9731;border: 4pxsolid#5a1f12;border-radius: 50%; position: absolute; top: 260px; left: 15px; } .push-direction::before { content: ''; width: 54px; height: 20px; background: #7b4a45;position: absolute; top: 30px; left: 13px; box-shadow: 0-3px00#fff;border-radius: 5px; } .push-direction::after { content: ''; width: 20px; height: 54px; background: #7b4a45;position: absolute; top: 13px; right: 30px; box-shadow: 0-3px00#fff;border-radius: 5px; } .push-control { width: 36px; height: 80px; background: #eb9430;border: 4pxsolid#5a1f12;border-radius: 40px; position: absolute; top: 260px; right: 35px; transform: rotate(55deg); } .push-control .begin, .push-control .stop { width: 26px; height: 26px; line-height: 26px; text-align: center; color: #fff;background: #ff4822;position: absolute; left: 6px; box-shadow: inset03px00#fff;border-radius: 50%; font-size: 13px; cursor: pointer; } .push-control .begin { top: 10px; } .push-control .stop { top: 45px; } .push-sound { width: 16px; height: 50px; background: #864949;position: absolute; top: 350px; border: 2pxsolid#5a1f12;border-radius: 16px; box-shadow: inset3px000#fff;transform: rotate(60deg); } .push-sound::before { content: ''; width: 24px; height: 4px; background: #5a1f12;position: absolute; bottom: 21px; left: 12px; border-radius: 4px; transform: rotate(-90deg); } .push-sound-top { left: 80px; } .push-sound-bottom { left: 140px; }
html
<divclass="push-direction"></div><divclass="push-control"><divclass="begin"id="pushBegin">B</div><divclass="stop"id="pushStop">S</div></div><divclass="push-sound push-sound-top"></div><divclass="push-sound push-sound-bottom"></div>
js
varleftBox=document.getElementsByClassName('left-box'); varpushBegin=document.getElementById('pushBegin'); varpushStop=document.getElementById('pushStop'); varmonitor=document.getElementById('monitor'); vargame=document.getElementById('game'); vargameName=document.getElementById('gameName'); // 屏幕展示方法functionshow() { monitor.style.display='none'; game.style.display='block'; // 设置开始按钮不可以点击pushBegin.disabled=false; // 设置关闭按钮可以点击pushStop.disabled=true; setTimeout(function () { for (vari=0; i<leftBox.length; i++) { varblock=leftBox[i].getElementsByClassName('integral-block'); for (varj=0; j<block.length; j++) { block[j].classList.add('b'); } } }, 800); setTimeout(function () { gameName.style.display='block'; }, 1500); } // 屏幕停止方法functionstop() { monitor.style.display='block'; game.style.display='none'; // 设置开始按钮可以点击pushBegin.disabled=true; // 设置关闭按钮不可以点击pushStop.disabled=false; for (vari=0; i<leftBox.length; i++) { varblock=leftBox[i].getElementsByClassName('integral-block'); for (varj=0; j<block.length; j++) { block[j].classList.remove('b'); } } } pushBegin.onclick=show; pushStop.onclick=stop;
总结
这次用CSS实现儿时的游戏机,带给我很多启发,一大批卡通形象汇聚到了我的大脑中,等我有时间慢慢实现。
创作的过程真的很有意思,代码成了我的画笔,作为一个不擅长绘画但是喜欢卡通的人,代码帮助我实现了想实现的画作。(*^▽^*)
不过,还有两个功能待实现。第一个是按行点亮方块的功能,另一个是俄罗斯方块游戏的开发。前面这个最近在探索中。后面的功能,算法是我的短板,也希望未来能补足。