-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsearch.xml
105 lines (105 loc) · 40.4 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[javascript | 提取JSON值为纯数组,键为title]]></title>
<url>%2F2019%2F03%2F26%2FarrayToJson%2F</url>
<content type="text"><![CDATA[#需求Json对象提取值储存纯数组,提取键做title,为上一文章导出Excel作数据 javascript 结果 #javascript1234567891011121314151617181920212223242526272829303132333435363738394041/*** @param { JSONObject:[obj,obj,obj] }* @return { Array }* */function JSONToArray(){};JSONToArray.prototype = { count: 0, _init: function (data){ console.log(data) if(navigator.userAgent.indexOf('MSIE') > 0){ this._getIEObjLength(data); return this._go(data); }else { this.count = Object.keys(data[0]).length; console.log(this._go(data)) return this._go(data); } }, _go: function (data){ var valArr = new Array(); var keyArr = new Array(); for (var i = 0; i < data.length; i++) { valArr[i] = []; for(var k in data[i]){ valArr[i].push(data[i][k]); if(keyArr.length < this.count){ keyArr.push(k); } } } valArr.unshift(keyArr); return valArr; }, _getIEObjLength: function (data){ for(var o in data[0]){ this.count ++; } }} #结果123456789101112//原数据[ {"id":10000,"username":"user-0","sex":"女","city":"城市-0","sign":"签名-0","experience":255,"logins":24}, {"id":10001,"username":"user-1","sex":"男","city":"城市-1","sign":"签名-1","experience":884,"logins":58},]//处理后[ ["id","username","sex","city","sign","experience","logins"], [10000,"user-0","女","城市-0","签名-0",255,24], [10001,"user-1","男","城市-1","签名-1",884,58]] 兼容ie6-11]]></content>
<tags>
<tag>javascript</tag>
<tag>json</tag>
<tag>array</tag>
</tags>
</entry>
<entry>
<title><![CDATA[javascript | JSON导出Excel]]></title>
<url>%2F2019%2F03%2F24%2FjsonToExcel%2F</url>
<content type="text"><![CDATA[#需求最近后端返回了一段json对象数据,要求导出Excel,同时兼容IE8,这可让我郁闷了查了一下大多数插件,都只是兼容到ie9,本贴代码已测试,兼容ie6-11那下面就让我们来会会这狗屎一样的IE吧 工具 代码 调用 问题 #工具使用了 FileSaver.js & Blob.js #代码123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990(function(){ var EXCEL_CONTENTTYPE = "application/vnd.ms-excel;", EXCEL_URI = 'data:application/vnd.ms-excel;base64,', EXCE_TEMPLATE = '<html><head><meta charset="UTF-8"></head><body>{html}</body></html>', __PREVFIX = "\uFEFF", ieVersion = window.navigator.userAgent.toLowerCase().match(/(msie\s|trident.*rv:)([\w.]+)/), useIE = ieVersion && ieVersion[2] < 10, isIE1011 = ieVersion && ieVersion[2] > 9; var Export = { /* *@param datas Two-dimensional array : datas, export only with data or String : DOM id, export html content *@param fileName export file name */ toExcel: function(datas, fName){ var isId = typeof datas === 'string'; if(isId || datas instanceof Array){ if(useIE || isId && isIE1011){ Export.__ieExport(datas); } else{ Export.__oTherExport(datas, fName); } } else{ alert("datas params need Two-dimensional array or String."); } }, __ieExport : function(datas){ var oXL = new ActiveXObject("Excel.Application"), oWB = oXL.Workbooks.Add(), oSheet = oWB.ActiveSheet, i = 0, j; if(typeof datas === 'string'){ var elem = document.getElementById(datas); var sel = document.body.createTextRange(); sel.moveToElementText(elem); try{ sel.select(); //there ie10、11 will be error, i don't know why, but also can export } catch(e){} sel.execCommand("Copy"); oSheet.Paste(); } else { for(; i < datas.length; i++){ var row = datas[i]; for (j = 0; j < row.length; j++) { oSheet.Cells(i + 1, j + 1).value = row[j]; } } } oXL.Visible = true; }, __oTherExport : function(datas, fileName){ if(typeof datas === 'string'){ var elem = document.getElementById(datas), content = EXCE_TEMPLATE.replace("{html}", elem.outerHTML); //TODO: need test large amount of data window.location.href = EXCEL_URI + window.btoa(unescape(encodeURIComponent(content))); } else { var blob, i = 0, j, str = __PREVFIX; for(; i < datas.length; i++){ var row = datas[i]; // the value add double quotation marks on both sides, for separate values. str += "\""+ row.join("\",\"") + "\"\n"; } //on safari: TypeError: '[object BlobConstructor]' is not a constructor (evaluating 'new Blob([str],{ //import Blob.js to fix, but still have a problem : the fileName will be 'Unknown' , //but if you add suffix name, content can be seen. blob = new Blob([str],{ type: EXCEL_CONTENTTYPE }); saveAs(blob, fileName || "Download.xls"); } } } window.ExportUtil = Export;})(); #调用12345678910//数据方式ExportUtil.toExcel([ ["学号", "姓名", "年龄"], ["1", "haha", "19"], ["2", "heihei", "10"], ["3", "lolo", "23"] ],"test.xls"); //table方式ExportUtil.toExcel("id"); //id为table的id #问题 由于没有safari的需求,safari兼容性请自测 建议用数据方式导出,HTML标签方式效果不太好 参考 github]]></content>
<tags>
<tag>javascript</tag>
<tag>json</tag>
<tag>excel</tag>
<tag>FileSaver.js</tag>
</tags>
</entry>
<entry>
<title><![CDATA[npm采踩坑系列]]></title>
<url>%2F2019%2F03%2F06%2Fnpm_eroor%2F</url>
<content type="text"><![CDATA[#前言这几天想给添加一点东西,于是就用npm安装了一个插件,然后就提示出错了 来踩坑了 错误 解决 #错误证书错误12345npm install -g create-react-app//出错提示UNABLE_TO_VERIFY_LEAF_SIGNATUREUNABLE_TO_VERIFY_LEAF_SIGNATUREunable to verify the first certificate//无法验证第一证书 #解决123//因为npm install走的是https协议,需要通过数字证书来保证的,//所以,取消ssl验证npm config set strict-ssl false]]></content>
<tags>
<tag>npm</tag>
<tag>webpack</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Promise对象入门]]></title>
<url>%2F2019%2F02%2F22%2Fpromise%2F</url>
<content type="text"><![CDATA[#简介 promise对象可以获取异步操作的消息,提供统一的API,各个异步操作都可以用同样的方法进行处理。promise对象不受外界影响,其有三种状态:pending(进行中)、fulfilled(成功)、rejected(失败),只有异步操作的结果可以决定当前状态,一旦状态改变就不可以再变化,状态改变方向有两种:pending -> fulfilled、pending -> rejectedpromise对象的意义就在于将异步操作以同步操作的流程表达,避免层层嵌套的回调函数 基本用法 catch finally all #基本用法1234567let promise = new Promise(function (resolve, reject) { if () { resolve(value) // 异步操作成功 } else { reject(error) // 失败抛错 }}) Promise构造函数接受一个函数作为参数,该函数有两个参数:resolve、reject,当执行resolve函数时Promise对象状态pending -> fulfilled,当执行reject时Promise对象状态pending -> rejected 12345promise.then(function (value) { }, function (error) { }) Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数,第二个参数为可选参数,例子: 12345678let promise = new Promise(function (resolve, reject) { console.log('promise') resolve('11')})promise.then(function (value) { console.log(value)})console.log('22') 执行结果’promise -> 22 -> 11’,promise对象新建后立即执行,then方法的回调会在所有同步任务执行完成后执行 #catchpromise.prototype.catch()是then()方法的别名,用于指定发生错误时的回调函数 1234567new Promise(function () {}).then(() => {}).catch(err => { console.log(err)}) 如果异步操作抛出错误,状态就会变为reject,就会调用catch中的回调,当状态为resolve,执行then方法中的回调时,若报错同样回进入catch的回调意义:当我们使用promise异步操作时,但是没有使用catch捕获错误时,若promise异步执行报错时,外部代码并不会接收到错误,而是继续执行不受影响 123456789const someAsyncThing = function() { return new Promise(function(resolve, reject) { resolve(x); });};someAsyncThing().then(function() { console.log('ok');});setTimeout(() => { console.log('continue') }, 100); 如代码所示,x变量并没有定义,期待的操作是执行报错,然后停止运行,实际上continue会执行输出,这说明当没有catch捕获错误时,外部代码不会知道Promise对象内部执行已经报错,因此会继续执行。 #finally不管Promise对象最后结果如何,都会执行的操作,finally方法中的回调函数不接受任何参数1234promise.then(result => {···}).catch(error => {···}).finally(() => {···}); #allPromise.all方法用于将多个Promise实例包装成一个新的实例12345Promise.all([p1,p2,p3]).then((array) => { }).catch((err) => { }) 只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。]]></content>
<tags>
<tag>javascript</tag>
<tag>promise</tag>
</tags>
</entry>
<entry>
<title><![CDATA[一道JS闭包面试题]]></title>
<url>%2F2019%2F02%2F22%2Fbibao%2F</url>
<content type="text"><![CDATA[#说明最近看到这样一段代码 12345678910111213function fun(n,o){ console.log(o); return { fun:function(m){ return fun(m,n); } };}var a = fun(0);a.fun(1);a.fun(2);a.fun(3);var b = fun(0).fun(1).fun(2).fun(3);var c = fun(0).fun(1);c.fun(2);c.fun(3);//问:三行a,b,c的输出分别是什么? 觉得有点意思,和大家一起来聊聊。我相信如果你不是非常理解JavaScript中的闭包,一定是不想看这段代码的。 解释 总结 #解释好的,我们暂时先不去想这段代码,先看点简单的 123456789function fun0(){ var a=1; console.log(a);}function fun1(){ console.log(a);}fun0(); //1fun1(); //报错 a is not defined 这段代码,我相信大家应该知道最后为什么结果会是 1 和 报错 的,在函数内声明的变量只在函数体内定义,它们是局部变量,作用域是局部的,所以 函数 fun1 调用后,找不到a,就报错了,JavaScript采用词法作用域,函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,所以我们只要改改上面函数 fun1的位置,它就不会报错了。 1234567891011function fun0(){ var a=1; console.log(a); //把fun1放在fun0中,就不报错了 function fun1(){ console.log(a); } fun1(); //1}fun0(); //1 代码改成这样,只是把fun1 放在 fun0 中就不报错了,函数调用后都输出1好了,我们来看最开始提到的代码,先简化一下 1234function fun(n,o){ return { }} 我们先看这段代码,fun 调用后会怎么样?很明显会返回一个空对象,记住,fun调用后会返回对象,这点很重要。 12345678910function fun(n,o){ console.log(o); return { fun:function(m){ return fun(m,n); } }; } var a = fun(0); 这里提一句,当调用函数的时候传入的实参比函数声明时指定的形参个数要少,剩下的形参都将设置为undefined值。console.log(o); 输出undefinedvar a = fun(0); 那a是值是什么,是fun(0),返回的那个对象 12345{ fun:function(m){ return fun(m,0); }} 这个对象,有一个fun的方法,方法返回的结果就是最外面 fun 调用的结果。 var a=fun(0),传入一个参数0,那就是说,函数fun中参数 n 的值是0了,而返回的那个对象中,需要一个参数n,而这个对象的作用域中没有n,它就继续沿着作用域向上一级的作用域中寻找n,最后在函数fun中找到了n,n的值是0,这段话是本文的重点, 明白这段,那问题就容易解决了。说到这里,这道题基本上可以解决了,希望大家能听明白我上面说的话,下面的就简单了。我们一步一步看。现在我们知道 a 是 12345{ fun:function(m){ return fun(m,0); }} 这样的一个对象a.fun(1); 会怎么样?看代码 12345{ fun:function(1){ return fun(1,0); }} a.fun(1); 返回的结果,就是 fun(1,0),返回的结果 123456789 function fun(n,o){ //n的值为1,o的值为0 console.log(o); return { fun:function(m){ return fun(m,n);//n的值为1 } };}fun(1,0); //输出0,并返回一个对象,这个对象有一个fun的方法,这个方法调用后,会返回外层fun函数调用的结果,并且外层函数的第二个参数是 n 的值,也就是1 a.fun(2); 会怎么样?看代码 12345{ fun:function(2){ return fun(2,0); }} a.fun(2); 返回的结果,就是 fun(2,0),返回的结果 123456789function fun(n,o){ //n的值为2,o的值为0 console.log(o); return { fun:function(m){ return fun(m,n); //n的值为2 } };}fun(2,0); //输出0,并返回一个对象,这个对象有一个fun的方法,这个方法调用后,会返回外层fun函数调用的结果,并且外层函数的第二个参数是 n 的值,也就是2 a.fun(3); 就不说了,一样的。 12var a = fun(0); a.fun(1); a.fun(2); a.fun(3);var b = fun(0).fun(1).fun(2).fun(3); 把返回的对象,重新赋值给a,这样两行的结果就是一样的了。var c = fun(0).fun(1); c.fun(2); c.fun(3);c 与他们的不同,只是var c = fun(0).fun(1); 之后用的是同一个对象罢了。 #总结说下结果 12345678var a = fun(0); a.fun(1); a.fun(2); a.fun(3);//undefined 0 0 0 var b = fun(0).fun(1).fun(2).fun(3);//undefined 0 1 2 var c = fun(0).fun(1); c.fun(2); c.fun(3);//undefined 0 1 1 转载来自http://www.cnblogs.com/xxcanghai/p/4991870.html顺便推荐几篇讲解闭包的文章学习Javascript闭包(Closure)Javascript闭包——懂不懂由你,反正我是懂了 JS闭包可被利用的常见场景]]></content>
<tags>
<tag>javascript</tag>
<tag>闭包</tag>
</tags>
</entry>
<entry>
<title><![CDATA[css | 三栏布局]]></title>
<url>%2F2019%2F02%2F18%2Fcss_layout_three_column%2F</url>
<content type="text"><![CDATA[#本文会分别介绍三种CSS实现三栏布局的方法 方法一:自身浮动的方法 方法二:margin负值法 方法三:绝对定位法 #方法一:自身浮动的方法实现方法:需要左栏向左浮动,右栏向右浮动,中间设左右margin来撑开距离123456789101112131415161718192021222324252627282930313233343536373839404142<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>CSS实现三栏布局1</title> <style type="text/css"> body{ margin: 0; padding: 0; } .left{ width:200px; height: 300px; background-color: #DC698A; float:left; } .middle{ /*width:100%;*/ /*中间栏不要设宽度,包括100%*/ height: 300px; background-color: #8CB08B; margin:0 200px; } .right{ width: 200px; height: 300px; background-color: #3EACDD; float: right; } </style></head><body> <!-- 左栏左浮右栏右浮,中间不设宽度用左右margin值撑开距离,且布局中中间栏放最后 --> <!-- 中间栏实际宽度是当前屏的100% --> <div class="left">左栏</div> <div class="right">右栏</div> <div class="middle">中间栏</div></body></html> 注意:该方法在html布局时,要把中间栏放在左栏、右栏后面,左栏和右栏的顺序不定 实现的效果如下:自身浮动实现三栏布局 #方法二:margin负值法实现方法:两边两栏宽度固定,中间栏宽度自适应,左栏、右栏、中间栏向左浮动,左栏的margin-left设为-100%,中间栏的width设为100%,右栏的margin-left设为-右栏宽度12345678910111213141516171819202122232425262728293031323334353637383940414243<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>CSS实现三栏布局2</title> <style type="text/css"> body{ margin:0; padding:0; } .left{ width:200px; height: 300px; background-color: #DC698A; float:left; margin-left:-100%; } .middle{ width:100%; height: 300px; background-color: #8CB08B; float:left; } .right{ width:200px; height: 300px; background-color: #3EACDD; float: left; margin-left: -200px; } </style></head><body> <!-- 左栏中间栏右栏左浮,左栏margin-left:-100%,中间栏宽100%,,右栏margin-left:-右栏宽度 且布局上必须中间栏放第一个--> <div class="middle">中间栏</div> <div class="left">左栏</div> <div class="right">右栏</div></body></html> 注意:该方法在html布局时,要把中间栏放在第一个 此方法是实现圣杯布局和双飞翼布局的基础。实现的效果如下:margin负值法实现三栏布局 #方法三:绝对定位法实现方法:左栏、右栏绝对定位,分别固定到页面左右两侧,中间栏不设宽度,用左右margin来撑开距离1234567891011121314151617181920212223242526272829303132333435363738394041424344<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>CSS实现三栏布局3</title> <style type="text/css"> body{ margin:0; padding: 0; } .left{ width:200px; height: 300px; background-color: #DC698A; position: absolute; left:0; top:0; } .middle{ /*width: 100%;*/ height: 300px; background-color: #8CB08B; margin:0 200px; } .right{ width:200px; height: 300px; background-color: #3EACDD; position: absolute; right:0; top:0; } </style></head><body> <!-- 左右两栏绝对定位,分别固定到页面的左右两侧,中间栏不设宽度,用左右margin撑开距离 --> <!-- 中间栏的实际宽度是当前屏的100% --> <div class="left">左栏</div> <div class="middle">中间栏</div> <div class="right">右栏</div></body></html> 实现的效果如下:]]></content>
<tags>
<tag>css</tag>
<tag>layout</tag>
</tags>
</entry>
<entry>
<title><![CDATA[css | flex常见面试题]]></title>
<url>%2F2019%2F02%2F18%2Fcss_flex_layout%2F</url>
<content type="text"><![CDATA[废话不多说! flex-内容宽度等分 左右布局,一侧定宽,一侧自适应撑满 未知高宽上下左右居中 #flex-内容宽度等分123456789//css .box { display: flex; } .box div { flex: 1; border: 1px solid red; } 123456//html <div class="box"> <div>1</div> <div>2</div> <div>3</div> </div> #左右布局,一侧定宽,一侧自适应撑满12345678910111213141516171819202122232425//css html, body { height: 100% } .main { display: flex; height: 100%; } .left, .right { height: 100%; border: 1px solid red; box-sizing: border-box; } .left { width: 300px; } .right { width: 100%; } 12345//html <div class="main"> <div class="left">固定宽度300px</div> <div class="right">自适应宽度</div> </div> #未知高宽上下左右居中1234567891011121314151617//css html, body { height: 100% } .main { display: flex; height: 100%; justify-content: center; align-items: center } .box { width: 300px; border: 1px solid red; } 1234//html <div class="main"> <div class="box">未知高度上下左右居中</div></div>]]></content>
<tags>
<tag>css</tag>
<tag>flex</tag>
</tags>
</entry>
<entry>
<title><![CDATA[javascript | 两数相除]]></title>
<url>%2F2019%2F02%2F16%2FPhrase%2F</url>
<content type="text"><![CDATA[给定两个整数,被除数dividend和除数divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。 返回被除数dividend除以除数divisor得到的商。 示例 说明 答案参考 #示例示例 1: 输入: dividend = 10, divisor = 3输出: 3 示例 2: 输入: dividend = 7, divisor = -3输出: -2 #说明被除数和除数均为32位有符号整数。除数不为0。假设我们的环境只能存储32位有符号整数,其数值范围是[−2^31, 2^31 − 1]。本题中,如果除法结果溢出,则返回2^31 − 1。 #答案参考12345678910111213141516171819202122232425262728293031323334353637383940/** * @param {number} dividend * @param {number} divisor * @return {number} */var divide = function (dividend, divisor) { let result = 0, sign = 1, mul = 1; if ((dividend > 0 && divisor < 0) || (dividend < 0 && divisor > 0)) { sign = -1; } dividend = Math.abs(dividend); divisor = Math.abs(divisor); divisor2 = divisor; while (dividend >= divisor2) { if (dividend > (divisor2 + divisor2)) { divisor2 += divisor2; mul += mul; } dividend -= divisor2; result += mul; } while (dividend >= divisor) { dividend -= divisor; result += 1; } if (sign == 1 && result > (Math.pow(2, 31) - 1)) { return Math.pow(2, 31) - 1; } else if (sign == -1 && result < -Math.pow(2, 31)) { return -Math.pow(2, 31); } if (sign == 1) { return result; } else { return -result; }};]]></content>
<tags>
<tag>javascript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[js读取input[type=file]图片,以及预览]]></title>
<url>%2F2019%2F02%2F15%2FFileReader%2F</url>
<content type="text"><![CDATA[#前言之前为了实现input[type=file]选择图片后实时展示图片,是把图片上传后,后端返回路径再显示感觉多此一举,这样的方法实在太笨了,也太慢了,也就摸索出另一种方法 FileReader FileReader 属性和方法 属性 事件处理 方法 开始 html js 结果 #FileReader 属性和方法来看下FileReader的属性和方法 #属性FileReader.error 只读一个DOMException,表示在读取文件时发生的错误 。 FileReader.readyState 只读表示FileReader状态的数字。取值如下: 常量名 值 描述 EMPTY 0 还没有加载任何数据. LOADING 1 数据正在被加载. DONE 2 已完成全部的读取请求. FileReader.result 只读文件的内容。该属性仅在读取操作完成后才有效,数据的格式取决于使用哪个方法来启动读取操作。 #事件处理FileReader.onabort处理abort事件。该事件在读取操作被中断时触发。 FileReader.onerror处理error事件。该事件在读取操作发生错误时触发。 FileReader.onload处理load事件。该事件在读取操作完成时触发。 FileReader.onloadstart处理loadstart事件。该事件在读取操作开始时触发。 FileReader.onloadend处理loadend事件。该事件在读取操作结束时(要么成功,要么失败)触发。 FileReader.onprogress处理progress事件。该事件在读取Blob时触发。 因为 FileReader 继承自EventTarget,所以所有这些事件也可以通过addEventListener方法使用。 #方法FileReader.abort()中止读取操作。在返回时,readyState属性为DONE。 FileReader.readAsArrayBuffer()开始读取指定的 Blob中的内容, 一旦完成, result 属性中保存的将是被读取文件的 ArrayBuffer 数据对象. FileReader.readAsBinaryString()开始读取指定的Blob中的内容。一旦完成,result属性中将包含所读取文件的原始二进制数据。 FileReader.readAsDataURL()开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容。 FileReader.readAsText()开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个字符串以表示所读取的文件内容。 那我们就知道要用到那些事件和方法了 文档来源 #开始#html123<input type="file" id="file"/> <img src="" id="img"/> <p id="text"></p> #js12345678910111213141516<script> document.querySelector('#file').onchange = function (){ if(this.files.length){ let file = this.files[0]; let reader = new FileReader(); //新建 FileReader 对象 reader.onload = function(){ // 当 FileReader 读取文件时候,读取的结果会放在 FileReader.result 属性中 document.querySelector('#img').src = this.result; document.querySelector('#text').innerHTML = this.result; }; // 设置以什么方式读取文件,这里以base64方式 reader.readAsDataURL(file); } }</script> #结果]]></content>
<tags>
<tag>javascript</tag>
<tag>fileReader</tag>
<tag>input[type=file]</tag>
</tags>
</entry>
<entry>
<title><![CDATA[javascript推箱子]]></title>
<url>%2F2018%2F11%2F24%2FSokoban%2F</url>
<content type="text"><![CDATA[#前言 闲来没事做,想来没写过推箱子,便写来玩玩推箱子游戏的 逻辑非常简单,但是如果不动手的话,还是不太清楚。我在这里讲一下自己的思路。 思路 开始 html部分 样式 javascript部分 结语 #思路先来看下游戏资源 和地图的对比 123456789101112131415160, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 1, 1, 1, 3, 0, 3, 2, 1, 0, 0, 0, 0,0, 0, 0, 0, 1, 2, 0, 3, 4, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 1, 1, 1, 1, 3, 1, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 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, 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, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 可以看到地图中的人物以及建筑是和数据中一一对应1对应树2对应球3对应箱子4对应人 那我们就可以根据数字去生成地图生成地图的同时给所有的dom赋值坐标轴 根据坐标轴来制定游戏规则 #开始#html部分123<div id="box"></div><script src="./js/mapdata100.js"></script><!--mapdata100.js中的数组变量是levels--> #样式12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758#box { display: -webkit-flex; display: -moz-flex; display: -ms-flex; display: -o-flex; display: flex; flex-direction: column; width: 560px;}#wrap { position: relative; }.item { width: 35px; height: 35px; position: absolute;}.item img{ position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); margin-top: -7px;}#wrap .person { z-index: 2;}#wrap .person img{ margin-top: -17px;}#button { display: -webkit-flex; display: -moz-flex; display: -ms-flex; display: -o-flex; display: flex; flex-wrap: wrap; justify-content: center;}#button p { width: 100%; margin: 10px 0; text-align: center; }#button button{ margin: 0 20px;}#button div { width: 100%; margin: 20px auto; text-align: center; }#button input { width: 40%;} #javascript部分 定义一个函数123456window.onload =function(){ const box = document.getElementById('box'); var mygame = new game(); mygame.start(box);}var game = function(){} 添加属性123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334game.prototype = { variable: { x: 16,//坐标 y: 16,//坐标 data:levels,//关卡数据 person: null,//人物 wrap: null,//地图盒子 buttonDiv: null,//按钮盒子 box: null,//传进来的盒子 /也就是父盒子 level: 0,//第几关 passNum: 0,//通关次数 stepNum: 0//步数统计 }, //历史移动储存 用来返回上一步 step:{ person: [], box: [] }, //开始 start:function (box){ var wrap = document.createElement("div"); var button = document.createElement("div"); this.variable.wrap = wrap; this.variable.wrap.id = 'wrap'; this.variable.box = box; this.variable.buttonDiv = button; this.variable.buttonDiv.id = 'button'; this.variable.box.appendChild(this.variable.wrap); this.variable.box.appendChild(this.variable.buttonDiv); this.init(); }, //地图初始化 init: function (){ this.variable.wrap.innerHTML = '';//清空地图 this.variable.wrap.style.cssText = 'background:url(img/block.gif);' + 'width:'+ this.variable.x * 35 +'px;' + 'height:'+ this.variable.y * 35 +'px;';//布置地图 for(let k in this.variable.data[this.variable.level]){//根据关卡循环游戏资源布置建筑 switch(this.variable.data[this.variable.level][k]){ //树 case 1: this.createBasic('wall',k); break; //球 case 2: this.createBasic('ball',k); break; //箱子 case 3: this.createBasic('box',k); break; //人物 case 4: this.createBasic('down',k); break; } } this.controlPerson(this.variable.person);//人物移动控制 this.createButton();//创建按钮 }, //创建建筑 createBasic: function (type,k){ var Odiv = document.createElement("div"); var Oimg = new Image(); var y = parseInt(k/this.variable.x);//商/即是y轴 var x = parseInt(k%this.variable.y);//余数即是x轴 if(type == "down"){ Odiv.className = 'item '+ "person";//人物给类 this.variable.person = Odiv;//人物存储 }else { Odiv.className = 'item '+ type;//type给类 } Oimg.src = 'img/' + type + '.png';//src Odiv.x = x;//自定义属性,即元素存储坐标轴 也是用来判断人物/箱子/树/球之间的关系 也是思路的核心 Odiv.y = y; Odiv.style.cssText = 'left: '+ x*35+ 'px;top:' + y * 35 + 'px;z-index:' + (y*this.variable.x) +';';//坐标轴定义位置,z-index是为了上下层级(优化细节)/y越大的层级越高 Odiv.appendChild(Oimg); this.variable.wrap.appendChild(Odiv); }, //创建按钮 createButton:function (){ this.variable.buttonDiv.innerHTML = '';//清空按钮组 var _this = this;//点击事件要用的this变量 这里不懂得百度一下函数作用域和this指向 var p = document.createElement("p"); var next = document.createElement("button"); var prev = document.createElement("button"); var again = document.createElement("button"); var Prev_step = document.createElement("button"); var input_div = document.createElement("div"); var jump = document.createElement("button"); var text = document.createElement("input"); text.placeholder = 'Please enter 1~100 '; text.type = 'number'; input_div.appendChild(text); input_div.appendChild(jump); p.innerHTML = (this.variable.level+1) + 'level'; prev.innerHTML = 'prev level'; next.innerHTML = 'next level'; again.innerHTML = 'again'; Prev_step.innerHTML = 'Prev step'; jump.innerHTML = 'Level skip'; this.variable.buttonDiv.appendChild(p); this.variable.buttonDiv.appendChild(input_div); this.variable.buttonDiv.appendChild(prev); this.variable.buttonDiv.appendChild(next); this.variable.buttonDiv.appendChild(again); this.variable.buttonDiv.appendChild(Prev_step); prev.onclick = function (){ _this.variable.level --;//关卡-1 if(_this.variable.level < 0){ _this.variable.level = 0; } _this.init();//重新布置地图 } next.onclick = function (){ _this.variable.level ++;//关卡+1 if(_this.variable.level > 99){ _this.variable.level = 99; } _this.init();//重新布置地图 } again.onclick = function (){ _this.init();//重新布置地图 } Prev_step.onclick = function (){ _this.prev(_this);//退回上一步 传入_this } text.onkeyup = function (){//关卡跳转验证 var reg = new RegExp("^([1-9]|[1-9]\\d|100)$"); if(!reg.test(this.value)){ alert("请输入1-100的整数!") this.value = '' } } jump.onclick = function (){//关卡跳转 if(!text.value == '' || !text.value == null){ _this.variable.level = text.value _this.variable.level = parseInt(_this.variable.level) _this.variable.level--//不知道为什么关卡+1了,这里需要-1 //我也想不明白 _this.init()//重新布置地图 } } }, //人物控制 controlPerson: function (p){ var img = p.firstElementChild;//div下的图片 var _this = this; //键盘事件要用的this变量 document.onkeydown = function (ev){ ev = ev || window.event; var keycode = ev.keyCode; _this.step.person[_this.variable.stepNum] = {}//定义人物历史移动数据对象 _this.step.person[_this.variable.stepNum].src = _this.variable.person.firstElementChild.src;//人物历史移动朝向 switch(keycode){ //left case 37: img.src = 'img/left.png'; _this.movePerson({x:-1},p);//传入x-1,即坐标轴x-1,向左移动一步 下面同理 break; //up case 38: img.src = 'img/up.png'; _this.movePerson({y:-1},p);//传入y-1,即坐标轴y-1,向上移动一步 下面同理 break; //right case 39: img.src = 'img/right.png'; _this.movePerson({x:1},p); break; //down case 40: img.src = 'img/down.png'; _this.movePerson({y:1},p); break; } } }, //人物移动 movePerson: function (obj,el){ var x = obj.x || 0; var y = obj.y || 0; var k = this.variable.data[this.variable.level][ (el.x+x) + (el.y+y) * this.variable.x ]; //当前数据 //(el.x+x) + (el.y+y) * this.variable.x为下标 var box = this.variable.wrap.querySelectorAll(".box"); if(k != 1){//如果人物没撞上树 移动 //存储上一步 this.step.person[this.variable.stepNum].x = el.x; this.step.person[this.variable.stepNum].y = el.y; //人物移动 el.x += x; el.y += y; el.style.left = el.x * 35 + 'px'; el.style.top = el.y * 35 + 'px'; el.style.zIndex = el.x + el.y * this.variable.x; //移动结束 this.variable.stepNum ++;//移动步数+1 for (var i = box.length - 1; i >= 0; i--) { if(box[i].x == el.x && box[i].y == el.y){//人物移动后 人物与箱子的x,y相等 即人物撞上箱子 if(this.variable.data[this.variable.level][ (box[i].x+x) + (box[i].y+y) * this.variable.x ] != 1){//如果箱子没撞上树 //上面的(box[i].x+x) + (box[i].y+y) * this.variable.x 就是箱子在数据中的下标 if(this.collision(box[i],x,y)){//判断箱子之间的碰撞 没用碰撞执行 this.step.box[this.variable.stepNum-1] = {};//定义箱子的第·移动步数·个的对象 前面+1了,这里要-1 才是原来的步数 this.step.box[this.variable.stepNum-1].index = i;//箱子有未知个 要存储未知个箱子的上一步,就有未知个对象 存入this.step.box 也就是i个箱子 this.step.box[this.variable.stepNum-1].x = box[i].x;//上一步存入 this.step.box[this.variable.stepNum-1].y = box[i].y; //箱子移动 box[i].x += x; box[i].y += y; box[i].style.left = box[i].x * 35 + 'px'; box[i].style.top = box[i].y * 35 + 'px'; box[i].style.zIndex = box[i].x + box[i].y * this.variable.x; //移动结束 this.pass();//每一次箱子移动后 需要验证是否过关 }else {//箱子碰到箱子 箱子不做操作 但是上面人物已经移动 这里就需要把人还原 也就是坐标各-1 //人物移动 el.x -= x; el.y -= y; el.style.left = el.x * 35 + 'px'; el.style.top = el.y * 35 + 'px'; el.style.zIndex = el.x + el.y * this.variable.x; //移动结束 this.variable.stepNum --;//移动步数-1 this.step.person.pop();//上面人物移动前已经存储了历史移动 这里人物需要还原了 历史移动数组就得减去最后一个对象 } }else {//如果箱子撞上树 箱子不做操作 但是上面人物已经移动 这里就需要把人还原 也就是坐标各-1 el.x -= x;//这里跟上面一样 还原 el.y -= y; el.style.left = el.x * 35 + 'px'; el.style.top = el.y * 35 + 'px'; el.style.zIndex = el.x + el.y * this.variable.x; this.variable.stepNum --; this.step.person.pop(); } } } } }, //箱子与箱子的碰撞 collision: function (el,x,y){ //传入得值分别是 box[i]第i个箱子,移动的x值,移动的y值(也就是this.movePerson中的x,y) var box = this.variable.wrap.querySelectorAll(".box");//所有的箱子 for (var i = box.length - 1; i >= 0; i--) { //循环所有箱子 if(box[i] != el){//两个箱子是不是同一个 if(box[i].x == el.x+x && box[i].y == el.y+y){//下一步的坐标与一个箱子的坐标相等,也就是说两个箱子有重合, 返回false return false; } } } //下一步的坐标与一个箱子的坐标不相等,也就是说两个箱子不重合, 返回true return true }, //过关检测 pass: function (){ var box = this.variable.wrap.querySelectorAll(".box");//箱子 var ball = this.variable.wrap.querySelectorAll(".ball");//球 var ballNum = 0;//箱子有未知个 要计数 for (var i = box.length - 1; i >= 0; i--) { for (var g = ball.length - 1; g >= 0; g--) { if(box[i].x == ball[g].x && box[i].y == ball[g].y){//箱子和球的坐标相等 则成功的箱子+1 ballNum ++; } } } if(ballNum == ball.length){//成功的箱子个数等于球的个数 游戏过关 alert("success"); this.variable.level ++;//成功后关卡+1 this.init();//重置地图 进入下一关 } }, //上一步 prev: function (_this){ var w_box = _this.variable.wrap.querySelectorAll(".box");//所有箱子 if(_this.variable.stepNum != 0){//移动步数不等于0 _this.variable.person.x = _this.step.person[_this.variable.stepNum-1].x;//返回上一步 移动步数-1 赋值人物坐标 _this.variable.person.y = _this.step.person[_this.variable.stepNum-1].y; _this.variable.person.style.left = _this.variable.person.x * 35 + 'px';//人物坐标退回上一步 _this.variable.person.style.top = _this.variable.person.y * 35 + 'px'; _this.variable.person.style.zIndex = _this.variable.person.x + _this.variable.person.y * _this.variable.x;//层级也要重新赋值 _this.variable.person.firstElementChild.src = _this.step.person[_this.variable.stepNum-1].src;//人物朝向更改 if(_this.step.box[_this.variable.stepNum-1]){//箱子与人物的移动步数不一样 另外判断 是否存在 var box_i = w_box[_this.step.box[_this.variable.stepNum-1].index]//第i个box 也就是箱子移动时储存的i box_i.x = _this.step.box[_this.variable.stepNum-1].x;//返回上一步 移动步数-1 赋值箱子坐标 box_i.y = _this.step.box[_this.variable.stepNum-1].y; box_i.style.left = box_i.x * 35 + 'px';//人物坐标退回上一步 box_i.style.top = box_i.y * 35 + 'px'; } _this.variable.stepNum--;//返回上一步后 移动步数-1 } } } #结语还是挺好玩的 啦啦啦啦预览]]></content>
<tags>
<tag>javascript</tag>
<tag>推箱子</tag>
<tag>小游戏</tag>
</tags>
</entry>
<entry>
<title><![CDATA[welcome]]></title>
<url>%2F2018%2F11%2F20%2Ftest%2F</url>
<content type="text"><![CDATA[123456 _ _ _____ _ ___ _____ _ _ _____( ) /\ ( ) ( ____) ( ) / _ \ ( _ ) ( ) ( ) ( ____) \ \ / \ / / | |___ | | | ( (_) | | | | | \ / | | |___ \ \/ \/ / | ___) | | | | _ | | | | | |\ \ / /| | | ___) \ /\ / | |___ | |____ | (_( ) | |_| | | | \ \/ / | | | |___ \_/ \_/ (_____) (______) \___/ (_____) (_) \__/ (_) (_____)]]></content>
<tags>
<tag>welcome</tag>
</tags>
</entry>
</search>