JSFiddle - React, Tailwind, and code Playground
by neonDog
HTML
<div class="window-body border">
<div class="column">
<div class="borde">
<div class="map-wrapper">
<img class="ingen-logo" src="https://vignette.wikia.nocookie.net/jurassicpark/images/b/b0/Ingenicon3.png/revision/latest?cb=20141208195042">
<svg class="map" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 595.28 768.52">
<defs>
<style>
.cls-1 {
fill: #10a1c7;
}
.cls-2 {
}
.cls-3, .cls-4, .cls-5, .cls-6, .cls-7 {
fill: none;
}
.cls-3 {
stroke: #e8e8e8;
}
.cls-3, .cls-4, .cls-5, .cls-7 {
stroke-linecap: round;
stroke-linejoin: round;
}
.cls-3, .cls-4 {
stroke-width: 3px;
}
.cls-4 {
stroke: #f15a29;
}
.cls-5, .cls-7 {
stroke: #fbb040;
}
.cls-6 {
/*stroke: #231f20; This is the main tour path that is followed*/
}
.cls-7 {
stroke-width: 2px;
}
</style>
<pattern id="img1" patternUnits="userSpaceOnUse" width="550" height="700">
<image xlink:href="https://neoncreativestudios.co.uk/island.png" x="40" y="40"
width="598" height="726" />
</pattern>
</defs>
<rect id="sea" class="cls-1" width="595.28" height="768.52"/>
<g id="island">
<path class="cls-2" fill="url(#img1)"...
SCSS
html, body {
margin:0;
padding:0;
font-family:sans-serif;
}
*, *:before, *:after {
box-sizing: border-box;
}
@mixin input-box-borders {
border-bottom: 3px solid #f4f4f4;
border-right: 3px solid #f4f4f4;
border-left: 3px solid #848484;
border-top: 3px solid #848484;
}
@mixin button-box-borders {
border-top: 3px solid #f4f4f4;
border-left: 3px solid #f4f4f4;
border-right: 3px solid #848484;
border-bottom: 3px solid #848484;
}
@mixin button-box-borders-dark {
border-top: 2px solid #333;
border-left: 2px solid #333;
border-right: 2px solid #aaa;
border-bottom: 2px solid #aaa;
}
@mixin button-box-borders-jp {
border:20px solid transparent;
border-image: url('https://neoncreativestudios.co.uk/border2.png') 24;
}
.map-wrapper {
width: 100%;
height: 900px;
position: relative;
overflow:hidden;
background:#10a1c7;
display:inline-block;
vertical-align:text-top;
svg {
position: absolute;
transform:scale(1);
}
}
svg text {
fill:white;
font-family:sans-serif;
font-size:12px;
}
.window-body {
width:100%;
border: 1px solid gray;
background: #727481;
position: relative;
padding: 1px;
box-shadow: 2px 2px 2px #424242;
border-top: 1px solid white;
border-left: 1px solid white;
border-right: 1px solid #848484;
border-bottom: 1px solid #848484;
//margin:5px;
}
.border {
@include button-box-borders-jp;
padding:10px;
background-color: #727481;
}
.button-container {
height:120px;
}
.button-classic {
display:inline;
cursor: pointer;
padding:8px;
margin:0;
font-size:1.5em;
width: 65px;
height: 65px;
background-color: #aaa;
color:#222;
@include button-box-borders;
&:focus {
outline: none;
}
&:active {
@include input-box-borders;
}
}
.vehicle-status {
visibility:hidden;
&.show {
visibility:visible;
}
.body {
z-index:10;
width:100%;
position:absolute;
margin-top:40px;
//opacity:0.7;
bottom:0;
...
JavaScript
const audioCtx = new AudioContext();
class vehicle {
constructor(settings={}) {
this.id = settings.id || null;
this.type = settings.type || 'explorer'; //Vehicle type
this.pathCompletion = settings.pathCompletion || 0; //Percentage of route completed
this.path = settings.path || null; //which road/route the vehicle is on
this.pathDirection = settings.pathDirection || true; //Travelling forwards
this.currentStageIndex = null; //Current path stage index
this.nextStagePercentage = null; //When vehicle moves to the next stage
this.batteryLevel = 1; //Percentage
this.chargeStatus = false; //false|true
this.currentZone = null;
this.speed = settings.speed || 0; //Vehicle's current speed
this.acceleration = 0.001; //Vehicle's acceleration rate
this.deacceleration = 0.005; //Vehicle's deacceleration rate
this.targetSpeed = 10; //The desired speed
this.speedWaitDuration = null;
}
setSpeed(targetSpeed=null,duration=null) {
if (targetSpeed !== null) {
this.targetSpeed = targetSpeed;
//} else if (this.currentZone && 'targetSpeed' in this.currentZone) {
// this.targetSpeed = this.currentZone.targetSpeed;
}
this.speedWaitDuration = duration ? new Date().getTime() + (duration * 1000) : null;
}
clearPathMeta() {
this.currentStageIndex = null;
this.nextStagePercentage = null;
this.currentStage = null;
this.currentZOne = null;
}
setZone(zone) {
if (zone === this.currentZone) return;
//Vehicle has entered a new zone
this.currentZone = zone;
}
setPath(path,pathCompletion) {
if (path === this.path) return;
this.clearPathMeta(pathCompletion);
this.path = path;
this.pathCompletion = pathCompletion || 0;
}
}
class vehicleController {
constructor(settings={}) {
let defaults = {
onVehicleAdd:function(id,data){},
onChange:function(){}
};
this.options =...