saber 酱的抱枕

Fly me to the moon

01/22
2017
学习

动态设置rem使页面自适应缩放

更新:两年过去了,现在推荐使用 vw + rem 自适应布局


我们页面布局中,可以通过动态设置rem并使用rem单位来设置宽高,来使得页面元素的尺寸可以随设备宽度而变化,这样就能保持布局的一致性。

使用JavaScript动态设置rem的代码如下:

(function (doc, win) {
	var docEl = doc.documentElement,
	  resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
	  recalc = function () {
	      var clientWidth = docEl.clientWidth;
	      if (!clientWidth) return;
	      docEl.style.fontSize = 100 * (clientWidth / 640) + 'px';
	  };
    if (!doc.addEventListener) return;
    win.addEventListener(resizeEvt, recalc, false);
    doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);

公式是这样的:

100 * ( 浏览器页面宽度 / 设计稿宽度 )

第一部分:100是什么

这个100其实是我们使用的rem基础值,等于设置html标签的font-size=100px,这样,1rem也就是100px。

当1rem为100px时,页面上所有元素设置宽高大小时都除以100,就得出了该元素的rem值。比如设计稿上300px宽的元素,用rem设置就是width=3rem。

1rem并不是非要设置为100px,我们也可以设置成别的,比如设置1rem=50px,那么300px的元素是6rem。我们一般取1rem=100px是为了方便计算。如果实际项目中计算页面元素的rem值时不是按1rem=100px来算的,则需要修改公式里的100为实际使用的1rem值。

第二部分:浏览器页面宽度 / 设计稿宽度 是什么

这个可以理解为页面在设备上的缩放比例。比如iphone 6 plus的设备宽度是414px,我们的设计稿是640px。

414/640=0.646875,得出我们的页面在iphone 6 plus上应该显示为设计稿大小的0.646875倍。

最后我们把rem的基础值与页面缩放比例相乘,得出实际使用的rem基础值。rem的基础值变了,页面上所有元素的宽高、大小也会随之改变,这样就达到了页面自适应的效果。
Read More →

动态设置rem使页面自适应缩放

01/9
2017
学习

使用js的insertAdjacentHTML方法插入元素

以往我们插入、移动DOM元素经常是使用appendChild和insertBefore方法。

appendChild:在父级元素内追加新元素。
insertBefore:在父级元素内的某个元素之前插入新元素。

但是这两个方法的参数只能接收元素对象,不能使用字符形式的html代码,而且它们插入元素的位置也不够灵活。我们可以使用insertAdjacentHTML方法来更方便的插入元素。

insertAdjacentHTML可以将字符串形式的html代码(需要能解析为DOM元素)解析为一个节点,并将其追加到指定元素的指定位置。

insertAdjacentHTML方法的语法如下:

element.insertAdjacentHTML(position, text);

position参数有以下四个值(都是字符串形式):

beforebegin:在元素的开始位置之前插入。
beforeend:在元素的结束位置之前插入。
afterbegin:在元素的开始位置之后插入。
afterend:在元素的结束位置之后插入。

text参数则是字符串形式的html代码。

根据position参数,我们可以将新元素插入到到指定元素的四个位置:

使用js的insertAdjacentHTML方法插入元素

示例:

<div id="a">
	<div></div>
</div>
<script type="text/javascript" defer>
	var a=document.querySelector("#a");
	a.insertAdjacentHTML("afterbegin","<a href='' >xxx</a");
</script>

结果如下:

<div id="a">
	<a href="">xxx</a>
	<div></div>
</div>

insertAdjacentHTML方法的兼容性表现良好,主流浏览器均已支持。我们也可以如下语句来检查浏览器是否支持方法:

document.documentElement.insertAdjacentHTML

此外,由于insertAdjacentHTML是根据位置插入元素的,因此它不能把新元素插入到img、input等单标签元素里(想这么做的人才是有毛病吧)。

相关文档:《https://developer.mozilla.org/zh-CN/docs/Web/API/Element/insertAdjacentHTML》


ps:与insertAdjacentHTML系列“同一系列”的还有insertAdjacentElement方法和insertAdjacentText方法。

insertAdjacentElement方法除了第二个参数是DOM节点(不能是字符串形式)外和insertAdjacentHTML方法都一样。

insertAdjacentText方法则只接收字符串格式的参数,并输出为字符串。其他地方也和insertAdjacentHTML方法一样。

使用js的insertAdjacentHTML方法插入元素

01/8
2017
学习

bilibili上使用的一个下雪效果

今天fgo开了圣诞活动,bilibili上的活动页面上下着雪,于是我把代码扒了下来。

这个下雪的js依赖jquery,实际使用中感觉效果一般←_←

<body style="background: #000;">
    <canvas class="snow-canvas" speed="1" interaction="true" size="8" count="40" start-color="rgba(253,252,251,1)" end-color="rgba(251,252,253,0.3)" opacity="0.00001" wind-power="2" image="false"></canvas>
    <script src="//apps.bdimg.com/libs/jquery/1.9.0/jquery.js"></script>
    <script src="//static.biligame.net/fgo/event_santa/pc/js/snow.js?v=d659f803.js"></script>
    <script>
    	$(".snow-canvas").snow();
    </script>
    <style>
    	.snow-canvas { position: fixed; display: block; width: 100%; height: 100%; top: 0; left: 0; pointer-events: none; }
    </style>
</body>

demo如下:

效果不是很好……不过如果像活动页面那样,有背景图片什么的,瑕疵应该不会很明显。

bilibili上使用的一个下雪效果

01/3
2017
学习

JavaScript实现全国三级城市联动select选择

JavaScript实现全国三级城市联动select选择

刚才在懒人之家找了一个JavaScript做的全国省市县三级联动的下拉选择插件,记录一下。

下载压缩包

这个js文件的日期是2014年,使用方法如下:

<select id="s_province" name="s_province"></select>  
<select id="s_city" name="s_city" ></select>  
<select id="s_county" name="s_county"></select>
<script src="form/area.js" type="text/javascript"></script>
<script type="text/javascript">_init_area();</script>

JavaScript实现全国三级城市联动select选择

12/30
2016
学习

使用FileReader读取并将文件存储在localStorage中

本文要做的事情是,用户通过file控件选择一个文件,之后我们使用FileReader将其转换为base64编码,并储存在LocalStorage里。

如下代码,在用户选择一张图片时,程序会将图片以base64编码保存到LocalStorage里,然后把这张图作为网页的背景图片。

<input type="file" name="img">
<br>
<input type="button" name="clearMyBG" value="清除我的设置">
<script>
// 尝试读取localStorage中存储的背景图片,如果有就设置
var myBGStorage = localStorage.getItem("myBG");
if (myBGStorage) {
 document.body.style.backgroundImage="url("+myBGStorage+")";
}

// 将选择的文件储存在localStorage里
document.querySelector("input[name=img]").addEventListener("change",function(){
	if (!/image\/\w/.test(this.files[0].type)) {
		alert("请确保文件为图像类型");
		return false;
	}
	setMyBG(this.files[0]);
})

//清除存储的背景图片
document.querySelector("input[name=clearMyBG]").addEventListener("click",function(){
	localStorage.removeItem("myBG");
	alert("设置已清除");
	location.reload();
})

//转换、存储和设置背景图片
function setMyBG (imgfile){
	var fileReader = new FileReader();
	fileReader.readAsDataURL(imgfile);
	fileReader.onload=function(){
		var result = this.result;
		document.body.style.backgroundImage="url("+result+")";
		try {
			localStorage.setItem("myBG", result);
		}catch (e) {
			console.log("Storage failed: " + e);
		}
	}
}
</script>

如下图,是localStorage中存储的键值对。注意localStorage的值都会被转换成string类型的。

使用FileReader读取并将文件存储在localStorage中

相关资料:
FileReader localStorage

有一个检测localStorage容量上限的工具:
Test of localStorage

它会在你的localStorage里存储数据,直到塞满为止。chrome约为5M。据说opera和firefox可以自己调整限制,厉害了。
Read More →

使用FileReader读取并将文件存储在localStorage中

12/29
2016
学习

使用URL.createObjectURL创建url对象

今天发现了window.URL.createObjectURL这个东西,非常的好用啊。

语法如下:

objectURL = URL.createObjectURL(blob || file);

URL.createObjectURL()方法会根据传入的参数创建一个指向该参数对象的URL. 这个URL的生命仅存在于它被创建的这个文档里. 新的对象URL指向执行的File对象或者是Blob对象。

我们可以使用URL.createObjectURL()方法给file对象或blob对象创建一个url来使用它。

blob对象产生的url格式如下:

blob:null/c694da24-ecd6-48ee-9a21-4c2979e6ef84

在处理本地数据时,它是很有用的,比如说上传前预览。

下面代码展示了一个表单,我们想用它上传图片和声音文件。

<form id="form1">
	<input type="file" name="img">
	<input type="file" name="audio">
</form>
<img src="" id="preview" width="300">
<audio autoplay="autoplay" controls="controls" src=""></audio>
<script>
	document.querySelector("#form1 input[name=img]").addEventListener("change",function(){
		var img=this.files[0];
		var imgUrl=window.URL.createObjectURL(img);
		document.querySelector("#preview").src=imgUrl;
	})

	document.querySelector("#form1 input[name=audio]").addEventListener("change",function(){
		var audio=this.files[0];
		var audioUrl=window.URL.createObjectURL(audio);
		document.querySelector("audio").src=audioUrl;
	})
</script>

在页面上有一个空的img元素和audio元素,在用户选择了图片或音乐后,该图片或音乐会直接显示/播放。是不是很方便呢?

你可以在下面直接操作:(第一个按钮传图片,第二个按钮传音乐)





虽然blob对象是个很方便的东西,但需要注意的是,当页面被关闭时,这个页面上生成的blob对象会被浏览器自动释放(清空)(但刷新页面不会清空blob对象),给它创建的url也就失效了。


此外有个URL.revokeObjectURL方法,用于释放blob对象的url。语法如下:

window.URL.revokeObjectURL(objectURL);

更加详细的信息可以参考此处

使用URL.createObjectURL创建url对象

12/20
2016
学习

使用HTML5的formData做ajax提交表单

我之前写过一篇《JavaScript表单序列化》的文章,表单序列化可以方便我们使用ajax来提交表单数据,避免网页刷新。我在这篇文章的末尾也附上了示例代码。但是使用表单序列化也有不太方便的地方:
第一,需要额外的代码来做表单序列化;
第二,需要在请求头里规定表单数据的格式。我第一次使用的时候因为不知道加这个就出错了。而且这个格式还有好几种。
第三,有很多用原生js做的表单序列化代码不能通过ajax提交附件。jquery的表单序列化可以,但也有点麻烦。

现在,HTML5的formData将上面的问题全部解决了,进一步简化了使用ajax提交表单的步骤。

当点击提交按钮时,通过 Fetch 发送数据:

const formData = new FormData(document.querySelector("#formID")); //生成formData

fetch(url, {
    method: 'post',
    body: formData,
})
.then(…)

Read More →

使用HTML5的formData做ajax提交表单

11/29
2016
学习

在javascript中实现startWith和endWith

javaScript本身没有startWith和endWith方法,我们可以通过正则表达式来实现类似的功能。

String.prototype.startWith=function(str){     
  var reg=new RegExp("^"+str);     
  return reg.test(this);        
}  

String.prototype.endWith=function(str){     
  var reg=new RegExp(str+"$");     
  return reg.test(this);        
}

//示例
var a="aaa.com";
var b="com";
a.endWith(b);

在javascript中实现startWith和endWith

11/27
2016
学习

去除hitomi.la上的点击限制的脚本

今天我在看hitomi.la这个网站,发现它会时不时在页面上覆盖一层flash,导致我们无法点击链接。本脚本通过移除这个flash来使页面可以被点击。

左键点击不动,右键弹出了flash的菜单
去除hitomi.la上的点击限制

页面上的flash元素:
去除hitomi.la上的点击限制

代码如下:

!function () {
let clearT=window.setInterval(function(){
  if (!!document.querySelector("object")) {
    document.querySelector("object").remove();
  }
},500);
}()

安装此脚本

顺便发现了CL-orz系列本子,全彩好评

去除hitomi.la上的点击限制的脚本