JSFiddle - React, Tailwind, and code Playground
HTML
<div id="container">
<input type="checkbox" id="cDoor" />
<input type="checkbox" id="cRoof" />
<input type="checkbox" id="cWinL" />
<input type="checkbox" id="cWinR" />
<div id="wrap">
<div id="ground">
<svg viewBox="0 0 50 55">
<path id="wFront" d="m0,55h18v-26h14v26h18v-30l-25,-25-25,25z"/>
</svg>
<svg viewBox="0 0 50 55">
<path id="wBack" d="m0,55h50v-30l-25,-25-25,25zm7,-25h15v15h-15zm21,0h15v15h-15z" fill-rule="evenodd"/>
</svg>
<div></div>
<div></div>
<div></div>
<svg viewBox="0 0 50 35.36">
<defs>
<pattern id="pattern" patternUnits="userSpaceOnUse" width="3" height="5">
<image xlink:href="https://s-media-cache-ak0.pinimg.com/736x/75/d4/28/75d42817a3c36f0da00b9ef37b6bcafa.jpg" x="0" y="0" width="8.5" height="8.5" />
</pattern>
</defs>
<path id="wRoof" d="m0,0h50v35.36h-50zm20,15h10v15h-10z" fill-rule="evenodd"/>
</svg>
<div id="dDoor"><label for="cDoor"></label></div>
<div id="dRoof"><label for="cRoof"></label></div>
<div id="dWinL">
<label for="cWinL"></label>
<label for="cWinL"></label>
</div>
<div id="dWinR">
<label for="cWinR"></label>
<label for="cWinR"></label>
</div>
</div>
</div>
</div>
CSS
:root {
--ground: #575;
--wall1: #CCC;
--wall2: #DDD;
}
body {
margin: 0;
overflow: hidden;
background-color: #20262E;
}
#container {
margin: auto;
margin-top: 10vmin;
width: 80vmin;
height: 80vmin;
perspective: 140vmin;
}
#container > input {
display: none;
}
#wrap {
transform-origin: 40vmin 40vmin;
transform-style: preserve-3d;
transform: rotateX(60deg) rotateZ(30deg);
}
#wrap * {
position: absolute;
transform-style: preserve-3d;
}
#ground {
left: 10vmin;
top: 10vmin;
width: 60vmin;
height: 60vmin;
background-color: var(--ground);
transform: translateZ(-20vmin);
}
#ground svg {
pointer-events: none;
}
#ground > svg:nth-child(1) {
width: 50vmin;
height: 55vmin;
transform: translate3d(5vmin, 27.5vmin, 27.5vmin) rotateX(-90deg);
fill: var(--wall1);
}
#ground > svg:nth-child(2) {
width: 50vmin;
height: 55vmin;
transform: translate3d(5vmin, -22.5vmin, 27.5vmin) rotate(180deg) rotateX(-90deg);
fill: var(--wall1);
}
#ground > div:nth-child(3) {
width: 50vmin;
height: 30vmin;
background-color: var(--wall2);
transform: translate3d(-20vmin, 15vmin, 15vmin) rotate(90deg) rotateX(-90deg);
}
#ground > div:nth-child(4) {
width: 50vmin;
height: 30vmin;
background-color: var(--wall2);
transform: translate3d(30vmin, 15vmin, 15vmin) rotate(-90deg) rotateX(-90deg);
}
#ground > div:nth-child(5) {
width: 50vmin;
height: 35.36vmin;
background-image: url(https://s-media-cache-ak0.pinimg.com/736x/75/d4/28/75d42817a3c36f0da00b9ef37b6bcafa.jpg);
background-size: 18% 18%;
transform: translate3d(-7.5vmin, 12.32vmin, 42.5vmin) rotate(90deg) rotateX(-45deg);
}
#ground > svg:nth-child(6) {
width: 50vmin;
height: 35.36vmin;
fill: url(#pattern);
transform: translate3d(17.5vmin, 12.32vmin, 42.5vmin) rotate(-90deg) rotateX(-45deg);
}
#ground label {
transition: transform 300ms;
}
#dDoor {
transform-origin: 7vmin 13vmin;
transform: translate3d(23vmin, 42vmin, 13vmin)...
JavaScript
var wrap = document.getElementById("wrap");
var begX, begY, prevX, prevY, newX, newY, dv;
newX=33; newY=67;
document.onmousedown = beginD;
document.onmouseup = stopD;
function beginD(e){
dv = wrap.parentNode.offsetWidth >> 7;
begX = e.clientX/(dv!=0?dv:dv=1);
begY = e.clientY/dv;
prevX = newX;
prevY = newY;
drag = true;
document.onmousemove = letsD;
return false;
}
function letsD(e) {
if (!drag) return;
(prevY > 0 && prevY < 200) ? (newX = prevX - (e.clientX/dv) + begX) : (newX = prevX + (e.clientX/dv) - begX);
newY = prevY - (e.clientY /dv) + begY;
wrap.style.transform = "rotateX(" + newY + "grad) rotateZ(" + newX + "grad)";
return false;
}
function stopD() {
drag = false;
rotReset();
}
function rotReset() {
if (newX >= 400 || newX < 0) newX -= 400 * Math.floor(newX / 400);
if (newY >= 400 || newY < 0) newY -= 400 * Math.floor(newY / 400);
wrap.style.transform = "rotateX(" + newY + "grad) rotateZ(" + newX + "grad)";
}
wrap.style.transform = "rotateX(" + (newY += .11) + "grad) rotateZ(" + (newX += .11) + "grad)"; //flicker preventer