js 改变change方法_JS都可以来帮助我们做什么有趣的事情?三个小案例分享给你们...

0640477cf5484611f9ba1f5880c5b81e.png

案例一:JS根据用户照片和姓名生成海报

需求描述

用户点击按钮进行照片上传

照片上传完成后,将照片进行裁剪,并和海报背景、姓名等组合得到海报

将生成的海报上传

效果大概如下:

海报背景:

f5f03e3ae73685fbfa8f66c8c1145c3f.png

成品:

565b111912cce2cf5163c0262a668b14.png

实现过程

1、初始化 canvas

canvas#poster-canvas(width='960' height='1280')
function initCanvas() { canvasCtx = document.getElementById("poster-canvas").getContext('2d');}

2、绘制海报背景

海报背景为预先提供的一张照片,将其设置到一个隐藏的 img 标签里面,

并且预留一个 canvas 元素用于绘制海报:

img.poster-background(src='/assets/xxx/poster-background.jpeg')

页面加载完成后,将海报背景绘制到 canvas 内:

$('img.poster-background').on('load', function () {
var backgroundImg = $('img.poster-background')[0];
canvasCtx.drawImage(backgroundImg, 0, 0, 960, 1280);
renderName();
});

海报背景绘制完成之后,需要将用户姓名绘制到特定位置。由于用户姓名长度不一,因此需要进行计算确定字体大小:

function renderName() {
var name = $('input[name="chName"]').val();
var fontSize;
if (name.length < 3) {
fontSize = 100;
} else {
fontSize = parseInt(320 / name.length);
}
canvasCtx.font = "bold " + fontSize + "px Courier New";
canvasCtx.fillStyle = "#de071b";
canvasCtx.fillText(name, 20, 1066);
}

3、上传照片

使用 file 类型的 input 元素,因为页面上表现为点击按钮,因此使用经典的将 input 元素透明化并覆盖按钮的方法:

a.upload-btn input#photo(type='file' name='photo' accept='image/jpeg, image/png')


| 上传自己的照片生成专属海报
.upload-btn input {
position: absolute;
left: 0;
top: 0;
opacity: 0;
width: 100%;
height: 68px;
cursor: pointer;
}

然后监听 input 元素的 change 事件,然后使用 FormData API 构造表单数据,使用 ajax 进行异步上传,照片上传完成之后。得到一个地址,将这个地址设置到页面上预留的一个 img 标签里面:

$('#photo').on('change', function (e) {
var file = e.target.files[0];
var type = file.type;
if (type !== 'image/jpeg' && type !== 'image/png') {
window.toastr.error('请上传 jpg 或 png 格式的图片');
} else {
var formData = new FormData();
formData.append('avatar', file);
$.ajax({
type: 'POST',
url: '/upload_url',
data: formData,
contentType: false,
processData: false,
success: function(result) {
var avatarUrl = result.data.url;
$('img.avatar').attr('src', avatarUrl);
},
error: function(err) {
}
});
}
});

4、绘制照片

海报中放置照片的区域为正方形,但是用户上传的照片却不一定,因此需要对照片进行裁剪,裁剪的原则为取照片中间部分。然后将裁剪参数传进 canvas 的 drawImage 方法,进行绘制:

$('img.avatar').on('load', function () {
var avatarImg = $('img.avatar')[0];
var originWidth = avatarImg.width;
var originHeight = avatarImg.height;
var newWidth, cutStartX, cutStartY;
if (originWidth < originHeight) {
newWidth = originWidth;
cutStartX = 0;
cutStartY = (originHeight - originWidth) / 2;
} else if (originWidth > originHeight) {
newWidth = originHeight;
cutStartX = (originWidth - originHeight) / 2;
cutStartY = 0;
} else {
newWidth = originWidth;
cutStartX = 0;
cutStartY = 0;
}
canvasCtx.drawImage(avatarImg, cutStartX, cutStartY,newWidth, newWidth, 0, 0, 960, 960); uploadPoster();
});

前面绘制海报背景和这里绘制照片,调用的是同一个方法,只不过后者多传进去了裁剪参数。但是需要注意的是,裁剪参数是在绘制位置之前传进去的,而不是简单的补在后面:

canvasCtx.drawImage(backgroundImg, 0, 0, 960, 1280);
canvasCtx.drawImage(avatarImg, cutStartX, cutStartY, newWidth, newWidth, 0, 0, 960, 960);

5、上传海报

依然使用 FormData API,因此需要先用 canvas 构造一个 Blob 对象。

新版本的 Chrome 和 Firefox 支持 canvas 的 toBlob 方法,可以直接使用:document.getElementById("poster-canvas").toBlob(function (blob) {});其它浏览器里,可以先用 toDataURL方法得到 base64 格式的图片数据,再转为 Blob:

var blob = dataURLtoBlob(document.getElementById("poster-canvas").toDataURL());function dataURLtoBlob(dataurl) {
if (dataurl.indexOf('base64') < 0) {
dataurl = 'data:image/jpeg;base64,' + dataurl;
}
var arr = dataurl.split(',');
var mime = arr[0].match(/:(.*?);/)[1];
var bstr = atob(arr[1]);
var n = bstr.length;
var u8arr = new Uint8Array(n);
while (n --) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type: mime});
}

然后进行上传,步骤和前面上传照片一致:

var formData = new FormData();
formData.append('poster', blob);
$.ajax({
type: 'POST',
url: '/upload_poster_url',
data: formdata,
contentType: false,
processData: false,
success: function(result) {
},
error: function(err) {
}
});

案例二:JS实现简易刻度时钟

如图所示,利用JS实现简易的刻度时钟;

原理如下:利用60等份的li进行布局,li两两之间的间隔为6deg,把基点定在圆心上,使得li圆形分布。然后另外设置三条针线的样式的位置,基点同样定在圆心上,然后秒针每秒动6deg,分针每秒动1/60deg,时针每秒动1/3600deg。

布局代码如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css" id="sty">
*{
margin: 0;
padding: 0;
list-style: none;
}
#wrap{
width: 200px;
height: 200px;
border: 1px solid #000;
border-radius: 50%;
margin: 20px auto;
position: relative;
}
#wrap ul{
position: relative;
}
#wrap ul li{
width: 2px;
height: 6px;
background: #000;
position: absolute;
left: 99px;
top: 0;
-moz-transform-origin: center 100px;
}
#wrap ul li:nth-child(5n){
height: 10px;
}
#con{
width: 10px;
height: 10px;
background: #000;
border-radius: 50%;
position: absolute;
left: 95px;
top: 95px;
}
#hour{
width: 5px;
height: 70px;
background: red;
border-radius: 50%;
position: absolute;
left: 98px;
top: 35px;
-moz-transform-origin: center 65px;
}
#min{
width: 3px;
height: 85px;
background: #000;
border-radius: 50%;
position: absolute;
left: 98.5px;
top: 20px;
-moz-transform-origin: center 80px;
}
#sec{
width: 2px;
height: 100px;
background: gray;
border-radius: 50%;
position: absolute;
left: 98.5px;
top: 20px;
-moz-transform-origin: center 80px;
}
</style>
</head>
<body>
<div id="wrap">
<ul id="list">
</ul>
<div id="hour"></div>
<div id="min"></div>
<div id="sec"></div>
<div id="con"></div>
</div>
</body>
</html>

布局代码里需要注意的是:每隔四个刻度就有一个刻度比较长,所以我们在设置样式的时候要特别注意加上:#wrap ul li:nth-child(5n){height: 10px;}。第5n个的长度变长。

JS代码中主要搞清楚三针之间的度数关系就好做了,代码如下:

<script type="text/javascript">
window.οnlοad=function(){
var oWrap=document.getElementById('wrap');
var oList=document.getElementById('list');
var oSty=document.getElementById('sty');
var tump='';
for(var i=0;i<60;i++){
var aLi=document.createElement('li');
oList.appendChild(aLi); tump+='#wrap ul li:nth-child('+(i+1)+'){transform: rotate('+(i+1)*6+'deg);}'; oSty.innerHTML+=tump;
}
var oSec=document.getElementById('sec');
var oMin=document.getElementById('min');
var oHour=document.getElementById('hour');
function time(){
var date=new Date();
var s=date.getSeconds();
var m=date.getMinutes()+(s/60);
var h=date.getHours()+(m/60);
oSec.style.transform='rotate('+s*6+'deg)';
oMin.style.transform='rotate('+m*6+'deg)';
oHour.style.transform='rotate('+h*30+'deg)';
}
time();
setInterval(time,1000);
}
</script>

案例三:JS实现的自动打字效果

本文实例讲述了JS实现的自动打字效果。分享给大家供大家参考,具体如下:

<!DOCTYPE html>

<html>

<head>

<meta charset='utf-8'>

<title>js typing</title>

</head>

<body>

<div id='divTyping'></div>

<script>

var str = 'js 实现的 打字效果,感觉蛮有趣的。';

var i = 0;

function typing(){

var divTyping = document.getElementById('divTyping');

if (i <= str.length) {

divTyping.innerHTML = str.slice(0, i++) + '_';

setTimeout('typing()', 200);//递归调用

}

else{

divTyping.innerHTML = str;//结束打字,移除 _ 光标

}

}

typing();

</script>

</body>

</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值