LIGHTS OUT - vue.js
LIGHTS OUT - vue.js
by covayashi
HTML
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Rajdhani" rel="stylesheet">
</head>
<body>
<h1>lights out</h1>
<div id="js-vue">
<lightout></lightout>
</div>
<script type="text/javascript" src="https://unpkg.com/vue@2.1.10/dist/vue.js"></script>
</body>
</html>
CSS
a,
abbr,
acronym,
address,
applet,
article,
aside,
audio,
b,
big,
blockquote,
body,
canvas,
caption,
center,
cite,
code,
dd,
del,
details,
dfn,
div,
dl,
dt,
em,
embed,
fieldset,
figcaption,
figure,
footer,
form,
h0,
h2,
h3,
h4,
h5,
h6,
header,
html,
i,
iframe,
img,
ins,
kbd,
label,
legend,
li,
mark,
menu,
nav,
object,
ol,
output,
p,
pre,
q,
ruby,
s,
samp,
section,
small,
span,
strike,
strong,
sub,
summary,
sup,
table,
tbody,
td,
tfoot,
th,
thead,
time,
tr,
tt,
u,
ul,
var,
video {
margin: 0;
padding: 0;
border: 0;
vertical-align: baseline
}
* {
box-sizing: border-box
}
body {
padding: 10px
}
h1 {
margin-bottom: 50px
}
#specification {
border-radius: 5px;
border: 1px solid #ccc;
padding: 10px;
margin-top: 50px
}
body {
background: #111;
background-size: .2em 100%;
font-family: 'Rajdhani', sans-serif;
font-size: 3em;
text-transform: uppercase;
margin: 0;
}
h1 {
text-align: center;
color: #256073;
margin: 20px 0;
}
.lightout {
display: flex;
flex-wrap: wrap;
width: 260px;
margin: 0 auto;
}
.lightout .box {
margin: 1px;
width: 50px;
height: 50px;
border-radius: 4px;
}
.on {
/* box-shadow */
box-shadow: 0px 0px 20px 4px #fff0ba inset;
-moz-box-shadow: 0px 0px 20px 4px #fff0ba inset;
-webkit-box-shadow: 0px 0px 20px 4px #fff0ba inset;
/* border-radius */
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
/* border */
border: 1px solid #fff500;
}
.off {
/* box-shadow */
box-shadow: 0px 0px 20px 4px #2a4171 inset;
-moz-box-shadow: 0px 0px 20px 4px #2a4171 inset;
-webkit-box-shadow: 0px 0px 20px 4px #2a4171 inset;
/* border-radius */
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
/* border */
border: 1px solid #1a5682;
}
.target {
border: 1px solid #98aeff;
}
.clear {
color: red;
text-align: center;
}
JavaScript
var temp = '<div v-if="setFlg">' + ' <div class="lightout" v-if="!goal">' + ' <div v-for="(val, index) in boxes" class="box" @click="pochi()" :class="[val == 1 ? \'on\' : \'off\', targetKey.indexOf(index) > -1 ? \'target\' : \'\']" @mouseover="search(index)" @mouseout="out()"></div>' + ' </div>' + ' <div v-else class="clear">Clear!</div>' + '</div>';
Vue.component('lightout', {
template: temp,
data: function() {
return {
setFlg: false,
targetKey: [],
boxes: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
};
},
methods: {
out: function() {
this.targetKey = [];
},
search: function(index) {
this.targetKey.push(index); //自身
if (index > 4) {
this.targetKey.push(index - 5); //上
}
if (index < 20) {
this.targetKey.push(index + 5); //下
}
if (index % 5 != 4) {
this.targetKey.push(index + 1); //右
}
if (index % 5 != 0) {
this.targetKey.push(index - 1); //左
}
},
pochi: function() {
this.targetKey.forEach(function(index) {
this.toggle(index);
}, this);
},
toggle: function(index) {
if (this.boxes[index] === 0) {
Vue.set(this.boxes, index, 1);
} else {
Vue.set(this.boxes, index, 0);
}
},
rand: function(min, max) {
var num = Math.floor(Math.random() * (max + 1 - min)) + min;
return num;
}
},
computed: {
goal: function() {
if (this.setFlg) {
if (this.boxes.indexOf(1) < 0) {
return true;
} else {
return false;
}
} else {
return false;
}
}
},
created: function() {
var imax = this.rand(10, 15);
for (var i = 0; i < imax; i++) {
var r = this.rand(0, 24);
this.search(r);
this.pochi();
this.out();
}
this.setFlg = true;
}
});
var vue = new Vue({
el: '#js-vue'
});